From 772825766c3b5113f2d0a6d979606d4cc2b07430 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Thu, 14 Sep 2023 18:39:58 +0200 Subject: [PATCH 1/8] coverage workflow --- .github/workflows/coverage.yml | 45 +++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index f8cd237..db553ef 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -3,7 +3,9 @@ on: branches: - main -name: coverage +permissions: + contents: write + pull-requests: write jobs: test: @@ -14,17 +16,6 @@ jobs: - '1.21' env: GOPRIVATE: github.com/anyproto - # redis for tests - services: - redis: - image: redis - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 6379:6379 steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 @@ -35,17 +26,42 @@ jobs: - name: git config run: git config --global url.https://${{ secrets.ANYTYPE_PAT }}@github.com/.insteadOf https://github.com/ + - name: Setup license repository + uses: actions/checkout@master + with: + repository: anyproto/open + ref: refs/heads/main + path: ./open + - name: Check licenses + run: | + cd open + python3 tools/generate.py --platform golang + cd .. + sudo gem install license_finder + license_finder inherited_decisions add open/decisions.yml + license_finder --enabled-package-managers gomodules + - name: deps - run: make deps CGO_ENABLED=0 + run: make deps - name: unit tests - run: make test CGO_ENABLED=0 + run: make test - name: Quality Gate - Test coverage shall be above threshold env: TESTCOVERAGE_THRESHOLD: 0 run: | go test ./... -coverprofile coverage.out -covermode count + + generated_pattern='^\/\/ Code generated .* DO NOT EDIT\.$' + files_list=$(grep -rl "$generated_pattern" . | grep '\.go$' | sed 's/^\.\///') + + for file in $files_list; do + echo "Removing $file from coverage report" + grep -v "$file" coverage.out > temp_file + mv temp_file coverage.out + done + go tool cover -func coverage.out echo "Quality Gate: checking test coverage is above threshold ..." echo "Threshold : $TESTCOVERAGE_THRESHOLD %" @@ -58,3 +74,4 @@ jobs: echo "Failed" exit 1 fi + - uses: seriousben/go-patch-cover-action@v1 From 94c2c99d24860fd8d490dc906fc6acd5f51084df Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Thu, 14 Sep 2023 20:26:50 +0200 Subject: [PATCH 2/8] storageKey instead spaceId --- filenode/filenode.go | 65 +++++++++++------------------ filenode/filenode_test.go | 59 ++++++++++++++------------ filenode/rpchandler.go | 3 +- go.mod | 2 +- go.sum | 8 ++++ index/index.go | 17 ++++---- index/mock_index/mock_index.go | 38 ++++++++--------- index/redisindex/bind.go | 2 +- index/redisindex/bind_test.go | 8 ++-- index/redisindex/redisindex.go | 34 ++++++++------- index/redisindex/redisindex_test.go | 56 +++++++++++++++++-------- index/redisindex/unbind.go | 2 +- index/redisindex/unbind_test.go | 6 +-- limit/limit.go | 28 +++++++------ limit/limit_test.go | 16 ++++--- limit/mock_limit/mock_limit.go | 7 ++-- 16 files changed, 192 insertions(+), 159 deletions(-) diff --git a/filenode/filenode.go b/filenode/filenode.go index 12c43ac..fb2edbb 100644 --- a/filenode/filenode.go +++ b/filenode/filenode.go @@ -68,31 +68,10 @@ func (fn *fileNode) Get(ctx context.Context, k cid.Cid) (blocks.Block, error) { } func (fn *fileNode) Add(ctx context.Context, spaceId string, fileId string, bs []blocks.Block) error { - // temporary code for migration - if fileId == "migration" { - return fn.migrate(ctx, bs) - } - if err := fn.ValidateSpaceId(ctx, spaceId, true); err != nil { - return err - } - unlock, err := fn.index.Lock(ctx, testutil.BlocksToKeys(bs)) - if err != nil { - return err - } - defer unlock() - toUpload, err := fn.index.GetNonExistentBlocks(ctx, bs) + storeKey, err := fn.ValidateSpaceId(ctx, spaceId, true) if err != nil { return err } - if len(toUpload) > 0 { - if err = fn.store.Add(ctx, toUpload); err != nil { - return err - } - } - return fn.index.Bind(ctx, spaceId, fileId, bs) -} - -func (fn *fileNode) migrate(ctx context.Context, bs []blocks.Block) error { unlock, err := fn.index.Lock(ctx, testutil.BlocksToKeys(bs)) if err != nil { return err @@ -107,19 +86,20 @@ func (fn *fileNode) migrate(ctx context.Context, bs []blocks.Block) error { return err } } - return fn.index.AddBlocks(ctx, toUpload) + return fn.index.Bind(ctx, storeKey, fileId, bs) } func (fn *fileNode) Check(ctx context.Context, spaceId string, cids ...cid.Cid) (result []*fileproto.BlockAvailability, err error) { + var storeKey string if spaceId != "" { - if err = fn.ValidateSpaceId(ctx, spaceId, false); err != nil { + if storeKey, err = fn.ValidateSpaceId(ctx, spaceId, false); err != nil { return } } result = make([]*fileproto.BlockAvailability, 0, len(cids)) var inSpaceM = make(map[string]struct{}) if spaceId != "" { - inSpace, err := fn.index.ExistsInSpace(ctx, spaceId, cids) + inSpace, err := fn.index.ExistsInStorage(ctx, storeKey, cids) if err != nil { return nil, err } @@ -148,7 +128,8 @@ func (fn *fileNode) Check(ctx context.Context, spaceId string, cids ...cid.Cid) } func (fn *fileNode) BlocksBind(ctx context.Context, spaceId, fileId string, cids ...cid.Cid) (err error) { - if err = fn.ValidateSpaceId(ctx, spaceId, true); err != nil { + storeKey, err := fn.ValidateSpaceId(ctx, spaceId, true) + if err != nil { return err } unlock, err := fn.index.Lock(ctx, cids) @@ -156,25 +137,26 @@ func (fn *fileNode) BlocksBind(ctx context.Context, spaceId, fileId string, cids return err } defer unlock() - return fn.index.BindCids(ctx, spaceId, fileId, cids) + return fn.index.BindCids(ctx, storeKey, fileId, cids) } -func (fn *fileNode) ValidateSpaceId(ctx context.Context, spaceId string, checkLimit bool) (err error) { +func (fn *fileNode) ValidateSpaceId(ctx context.Context, spaceId string, checkLimit bool) (storageKey string, err error) { if spaceId == "" { - return fileprotoerr.ErrForbidden + return "", fileprotoerr.ErrForbidden } // this call also confirms that space exists and valid - limitBytes, err := fn.limit.Check(ctx, spaceId) + limitBytes, storageKey, err := fn.limit.Check(ctx, spaceId) if err != nil { return } + if checkLimit { - currentSize, e := fn.index.SpaceSize(ctx, spaceId) + currentSize, e := fn.index.StorageSize(ctx, storageKey) if e != nil { - return e + return "", e } if currentSize >= limitBytes { - return fileprotoerr.ErrSpaceLimitExceeded + return "", fileprotoerr.ErrSpaceLimitExceeded } } return @@ -183,13 +165,14 @@ func (fn *fileNode) ValidateSpaceId(ctx context.Context, spaceId string, checkLi func (fn *fileNode) SpaceInfo(ctx context.Context, spaceId string) (info *fileproto.SpaceInfoResponse, err error) { info = &fileproto.SpaceInfoResponse{} // we have space/identity validation in limit.Check - if info.LimitBytes, err = fn.limit.Check(ctx, spaceId); err != nil { + var storageKey string + if info.LimitBytes, storageKey, err = fn.limit.Check(ctx, spaceId); err != nil { return nil, err } - if info.UsageBytes, err = fn.index.SpaceSize(ctx, spaceId); err != nil { + if info.UsageBytes, err = fn.index.StorageSize(ctx, storageKey); err != nil { return nil, err } - si, err := fn.index.SpaceInfo(ctx, spaceId) + si, err := fn.index.StorageInfo(ctx, storageKey) if err != nil { return nil, err } @@ -199,11 +182,12 @@ func (fn *fileNode) SpaceInfo(ctx context.Context, spaceId string) (info *filepr } func (fn *fileNode) FilesDelete(ctx context.Context, spaceId string, fileIds []string) (err error) { - if err = fn.ValidateSpaceId(ctx, spaceId, false); err != nil { + storeKey, err := fn.ValidateSpaceId(ctx, spaceId, false) + if err != nil { return } for _, fileId := range fileIds { - if err = fn.index.UnBind(ctx, spaceId, fileId); err != nil { + if err = fn.index.UnBind(ctx, storeKey, fileId); err != nil { return } } @@ -211,10 +195,11 @@ func (fn *fileNode) FilesDelete(ctx context.Context, spaceId string, fileIds []s } func (fn *fileNode) FileInfo(ctx context.Context, spaceId, fileId string) (info *fileproto.FileInfo, err error) { - if err = fn.ValidateSpaceId(ctx, spaceId, false); err != nil { + storeKey, err := fn.ValidateSpaceId(ctx, spaceId, false) + if err != nil { return } - fi, err := fn.index.FileInfo(ctx, spaceId, fileId) + fi, err := fn.index.FileInfo(ctx, storeKey, fileId) if err != nil { return nil, err } diff --git a/filenode/filenode_test.go b/filenode/filenode_test.go index 0b9a1a6..dc51c18 100644 --- a/filenode/filenode_test.go +++ b/filenode/filenode_test.go @@ -31,17 +31,18 @@ func TestFileNode_Add(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) var ( - spaceId = testutil.NewRandSpaceId() - fileId = testutil.NewRandCid().String() - b = testutil.NewRandBlock(1024) + spaceId = testutil.NewRandSpaceId() + storeKey = "sk:" + spaceId + fileId = testutil.NewRandCid().String() + b = testutil.NewRandBlock(1024) ) - fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(123), nil) - fx.index.EXPECT().SpaceSize(ctx, spaceId).Return(uint64(120), nil) + fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(123), storeKey, nil) + fx.index.EXPECT().StorageSize(ctx, storeKey).Return(uint64(120), nil) fx.index.EXPECT().Lock(ctx, []cid.Cid{b.Cid()}).Return(func() {}, nil) fx.index.EXPECT().GetNonExistentBlocks(ctx, []blocks.Block{b}).Return([]blocks.Block{b}, nil) fx.store.EXPECT().Add(ctx, []blocks.Block{b}) - fx.index.EXPECT().Bind(ctx, spaceId, fileId, []blocks.Block{b}) + fx.index.EXPECT().Bind(ctx, storeKey, fileId, []blocks.Block{b}) resp, err := fx.handler.BlockPush(ctx, &fileproto.BlockPushRequest{ SpaceId: spaceId, @@ -56,13 +57,14 @@ func TestFileNode_Add(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) var ( - spaceId = testutil.NewRandSpaceId() - fileId = testutil.NewRandCid().String() - b = testutil.NewRandBlock(1024) + spaceId = testutil.NewRandSpaceId() + storeKey = "sk:" + spaceId + fileId = testutil.NewRandCid().String() + b = testutil.NewRandBlock(1024) ) - fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(123), nil) - fx.index.EXPECT().SpaceSize(ctx, spaceId).Return(uint64(124), nil) + fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(123), storeKey, nil) + fx.index.EXPECT().StorageSize(ctx, storeKey).Return(uint64(124), nil) resp, err := fx.handler.BlockPush(ctx, &fileproto.BlockPushRequest{ SpaceId: spaceId, @@ -146,13 +148,14 @@ func TestFileNode_Check(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) var spaceId = testutil.NewRandSpaceId() + var storeKey = "sk:" + spaceId var bs = testutil.NewRandBlocks(3) cids := make([][]byte, len(bs)) for _, b := range bs { cids = append(cids, b.Cid().Bytes()) } - fx.limit.EXPECT().Check(ctx, spaceId) - fx.index.EXPECT().ExistsInSpace(ctx, spaceId, testutil.BlocksToKeys(bs)).Return(testutil.BlocksToKeys(bs[:1]), nil) + fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(100000), storeKey, nil) + fx.index.EXPECT().ExistsInStorage(ctx, storeKey, testutil.BlocksToKeys(bs)).Return(testutil.BlocksToKeys(bs[:1]), nil) fx.index.EXPECT().Exists(ctx, bs[1].Cid()).Return(true, nil) fx.index.EXPECT().Exists(ctx, bs[2].Cid()).Return(false, nil) resp, err := fx.handler.BlocksCheck(ctx, &fileproto.BlocksCheckRequest{ @@ -170,21 +173,22 @@ func TestFileNode_BlocksBind(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) var ( - spaceId = testutil.NewRandSpaceId() - fileId = testutil.NewRandCid().String() - bs = testutil.NewRandBlocks(3) - cidsB = make([][]byte, len(bs)) - cids = make([]cid.Cid, len(bs)) + spaceId = testutil.NewRandSpaceId() + storeKey = "sk:" + spaceId + fileId = testutil.NewRandCid().String() + bs = testutil.NewRandBlocks(3) + cidsB = make([][]byte, len(bs)) + cids = make([]cid.Cid, len(bs)) ) for i, b := range bs { cids[i] = b.Cid() cidsB[i] = b.Cid().Bytes() } - fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(123), nil) - fx.index.EXPECT().SpaceSize(ctx, spaceId).Return(uint64(12), nil) + fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(123), storeKey, nil) + fx.index.EXPECT().StorageSize(ctx, storeKey).Return(uint64(12), nil) fx.index.EXPECT().Lock(ctx, cids).Return(func() {}, nil) - fx.index.EXPECT().BindCids(ctx, spaceId, fileId, cids) + fx.index.EXPECT().BindCids(ctx, storeKey, fileId, cids) resp, err := fx.handler.BlocksBind(ctx, &fileproto.BlocksBindRequest{ SpaceId: spaceId, @@ -200,13 +204,14 @@ func TestFileNode_FileInfo(t *testing.T) { defer fx.Finish(t) var ( - spaceId = testutil.NewRandSpaceId() - fileId1 = testutil.NewRandCid().String() - fileId2 = testutil.NewRandCid().String() + spaceId = testutil.NewRandSpaceId() + storeKey = "sk:" + spaceId + fileId1 = testutil.NewRandCid().String() + fileId2 = testutil.NewRandCid().String() ) - fx.limit.EXPECT().Check(ctx, spaceId).AnyTimes() - fx.index.EXPECT().FileInfo(ctx, spaceId, fileId1).Return(index.FileInfo{1, 1}, nil) - fx.index.EXPECT().FileInfo(ctx, spaceId, fileId2).Return(index.FileInfo{2, 2}, nil) + fx.limit.EXPECT().Check(ctx, spaceId).AnyTimes().Return(uint64(100000), storeKey, nil) + fx.index.EXPECT().FileInfo(ctx, storeKey, fileId1).Return(index.FileInfo{1, 1}, nil) + fx.index.EXPECT().FileInfo(ctx, storeKey, fileId2).Return(index.FileInfo{2, 2}, nil) resp, err := fx.handler.FilesInfo(ctx, &fileproto.FilesInfoRequest{ SpaceId: spaceId, diff --git a/filenode/rpchandler.go b/filenode/rpchandler.go index 40c79b0..2b06b3b 100644 --- a/filenode/rpchandler.go +++ b/filenode/rpchandler.go @@ -166,7 +166,8 @@ func (r rpcHandler) FilesInfo(ctx context.Context, req *fileproto.FilesInfoReque resp = &fileproto.FilesInfoResponse{ FilesInfo: make([]*fileproto.FileInfo, len(req.FileIds)), } - if err = r.f.ValidateSpaceId(ctx, req.SpaceId, false); err != nil { + _, err = r.f.ValidateSpaceId(ctx, req.SpaceId, false) + if err != nil { return nil, err } var info *fileproto.FileInfo diff --git a/go.mod b/go.mod index f1e910d..f224d26 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/ahmetb/govvv v0.3.0 - github.com/anyproto/any-sync v0.3.0 + github.com/anyproto/any-sync v0.3.1-0.20230914174308-e178d8f8c67e github.com/aws/aws-sdk-go v1.44.327 github.com/go-redsync/redsync/v4 v4.8.1 github.com/gogo/protobuf v1.3.2 diff --git a/go.sum b/go.sum index ce2ad70..da45ba9 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,14 @@ github.com/ahmetb/govvv v0.3.0 h1:YGLGwEyiUwHFy5eh/RUhdupbuaCGBYn5T5GWXp+WJB0= github.com/ahmetb/govvv v0.3.0/go.mod h1:4WRFpdWtc/YtKgPFwa1dr5+9hiRY5uKAL08bOlxOR6s= github.com/anyproto/any-sync v0.3.0 h1:4lVxHf6aA2BrefGqjzbyn/wnSuNoriU2o8IsABBMfJE= github.com/anyproto/any-sync v0.3.0/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= +github.com/anyproto/any-sync v0.3.1-0.20230913182213-8f26b7dbfe3b h1:i27ykx2q6tIf45rgN/YiBKTW37Q+Nk496jw37HXQaa4= +github.com/anyproto/any-sync v0.3.1-0.20230913182213-8f26b7dbfe3b/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= +github.com/anyproto/any-sync v0.3.1-0.20230914161813-89373e5247f8 h1:Lt0BTdd7tN+ImIBuKf2vLphxi1hVZIlw9MZcM6ZaqZM= +github.com/anyproto/any-sync v0.3.1-0.20230914161813-89373e5247f8/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= +github.com/anyproto/any-sync v0.3.1-0.20230914163253-f7e95db95bd1 h1:naGWtEfprsVMestVHQHIJyAxdqnMdyo/dS+SCVtr8OY= +github.com/anyproto/any-sync v0.3.1-0.20230914163253-f7e95db95bd1/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= +github.com/anyproto/any-sync v0.3.1-0.20230914174308-e178d8f8c67e h1:APK2DvVUXEWxch6EePmjBpqCY/RWckiZwpnfuLktfsE= +github.com/anyproto/any-sync v0.3.1-0.20230914174308-e178d8f8c67e/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY= github.com/anyproto/go-chash v0.1.0/go.mod h1:0UjNQi3PDazP0fINpFYu6VKhuna+W/V+1vpXHAfNgLY= github.com/anyproto/go-slip10 v1.0.0 h1:uAEtSuudR3jJBOfkOXf3bErxVoxbuKwdoJN55M1i6IA= diff --git a/index/index.go b/index/index.go index 523d6c8..28fa065 100644 --- a/index/index.go +++ b/index/index.go @@ -16,20 +16,21 @@ var ( type Index interface { Exists(ctx context.Context, k cid.Cid) (exists bool, err error) IsAllExists(ctx context.Context, cids []cid.Cid) (exists bool, err error) - SpaceInfo(ctx context.Context, spaceId string) (info SpaceInfo, err error) + StorageInfo(ctx context.Context, key string) (info StorageInfo, err error) GetNonExistentBlocks(ctx context.Context, bs []blocks.Block) (nonExists []blocks.Block, err error) - Bind(ctx context.Context, spaceId, fileId string, bs []blocks.Block) error - BindCids(ctx context.Context, spaceId string, fileId string, cids []cid.Cid) error - UnBind(ctx context.Context, spaceId, fileId string) (err error) - ExistsInSpace(ctx context.Context, spaceId string, ks []cid.Cid) (exists []cid.Cid, err error) - FileInfo(ctx context.Context, spaceId, fileId string) (info FileInfo, err error) - SpaceSize(ctx context.Context, spaceId string) (size uint64, err error) + Bind(ctx context.Context, key, fileId string, bs []blocks.Block) error + BindCids(ctx context.Context, key string, fileId string, cids []cid.Cid) error + UnBind(ctx context.Context, key, fileId string) (err error) + ExistsInStorage(ctx context.Context, key string, ks []cid.Cid) (exists []cid.Cid, err error) + FileInfo(ctx context.Context, key, fileId string) (info FileInfo, err error) + StorageSize(ctx context.Context, key string) (size uint64, err error) Lock(ctx context.Context, ks []cid.Cid) (unlock func(), err error) AddBlocks(ctx context.Context, upload []blocks.Block) error app.Component } -type SpaceInfo struct { +type StorageInfo struct { + Key string FileCount int CidCount int } diff --git a/index/mock_index/mock_index.go b/index/mock_index/mock_index.go index 75bccfe..dfdf9ae 100644 --- a/index/mock_index/mock_index.go +++ b/index/mock_index/mock_index.go @@ -95,19 +95,19 @@ func (mr *MockIndexMockRecorder) Exists(arg0, arg1 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exists", reflect.TypeOf((*MockIndex)(nil).Exists), arg0, arg1) } -// ExistsInSpace mocks base method. -func (m *MockIndex) ExistsInSpace(arg0 context.Context, arg1 string, arg2 []cid.Cid) ([]cid.Cid, error) { +// ExistsInStorage mocks base method. +func (m *MockIndex) ExistsInStorage(arg0 context.Context, arg1 string, arg2 []cid.Cid) ([]cid.Cid, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ExistsInSpace", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "ExistsInStorage", arg0, arg1, arg2) ret0, _ := ret[0].([]cid.Cid) ret1, _ := ret[1].(error) return ret0, ret1 } -// ExistsInSpace indicates an expected call of ExistsInSpace. -func (mr *MockIndexMockRecorder) ExistsInSpace(arg0, arg1, arg2 interface{}) *gomock.Call { +// ExistsInStorage indicates an expected call of ExistsInStorage. +func (mr *MockIndexMockRecorder) ExistsInStorage(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExistsInSpace", reflect.TypeOf((*MockIndex)(nil).ExistsInSpace), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExistsInStorage", reflect.TypeOf((*MockIndex)(nil).ExistsInStorage), arg0, arg1, arg2) } // FileInfo mocks base method. @@ -198,34 +198,34 @@ func (mr *MockIndexMockRecorder) Name() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockIndex)(nil).Name)) } -// SpaceInfo mocks base method. -func (m *MockIndex) SpaceInfo(arg0 context.Context, arg1 string) (index.SpaceInfo, error) { +// StorageInfo mocks base method. +func (m *MockIndex) StorageInfo(arg0 context.Context, arg1 string) (index.StorageInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SpaceInfo", arg0, arg1) - ret0, _ := ret[0].(index.SpaceInfo) + ret := m.ctrl.Call(m, "StorageInfo", arg0, arg1) + ret0, _ := ret[0].(index.StorageInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// SpaceInfo indicates an expected call of SpaceInfo. -func (mr *MockIndexMockRecorder) SpaceInfo(arg0, arg1 interface{}) *gomock.Call { +// StorageInfo indicates an expected call of StorageInfo. +func (mr *MockIndexMockRecorder) StorageInfo(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpaceInfo", reflect.TypeOf((*MockIndex)(nil).SpaceInfo), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageInfo", reflect.TypeOf((*MockIndex)(nil).StorageInfo), arg0, arg1) } -// SpaceSize mocks base method. -func (m *MockIndex) SpaceSize(arg0 context.Context, arg1 string) (uint64, error) { +// StorageSize mocks base method. +func (m *MockIndex) StorageSize(arg0 context.Context, arg1 string) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SpaceSize", arg0, arg1) + ret := m.ctrl.Call(m, "StorageSize", arg0, arg1) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } -// SpaceSize indicates an expected call of SpaceSize. -func (mr *MockIndexMockRecorder) SpaceSize(arg0, arg1 interface{}) *gomock.Call { +// StorageSize indicates an expected call of StorageSize. +func (mr *MockIndexMockRecorder) StorageSize(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpaceSize", reflect.TypeOf((*MockIndex)(nil).SpaceSize), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageSize", reflect.TypeOf((*MockIndex)(nil).StorageSize), arg0, arg1) } // UnBind mocks base method. diff --git a/index/redisindex/bind.go b/index/redisindex/bind.go index ad9410c..6bd9b4f 100644 --- a/index/redisindex/bind.go +++ b/index/redisindex/bind.go @@ -64,7 +64,7 @@ func (op *bindOp) Bind(ctx context.Context, cids []CidInfo) (newCids []CidInfo, // increment space size if spaceIncreaseSize > 0 { - if err = op.ri.cl.HIncrBy(ctx, op.sk, spaceSizeKey, int64(spaceIncreaseSize)).Err(); err != nil { + if err = op.ri.cl.HIncrBy(ctx, op.sk, storeSizeKey, int64(spaceIncreaseSize)).Err(); err != nil { return nil, err } } diff --git a/index/redisindex/bind_test.go b/index/redisindex/bind_test.go index 51d40d1..cee8048 100644 --- a/index/redisindex/bind_test.go +++ b/index/redisindex/bind_test.go @@ -20,7 +20,7 @@ func TestRedisIndex_Bind(t *testing.T) { fileId := testutil.NewRandCid().String() require.NoError(t, fx.Bind(ctx, spaceId, fileId, bs)) - size, err := fx.SpaceSize(ctx, spaceId) + size, err := fx.StorageSize(ctx, spaceId) require.NoError(t, err) assert.Equal(t, sumSize, size) }) @@ -38,7 +38,7 @@ func TestRedisIndex_Bind(t *testing.T) { require.NoError(t, fx.Bind(ctx, spaceId, fileId1, bs[:2])) require.NoError(t, fx.Bind(ctx, spaceId, fileId2, bs)) - size, err := fx.SpaceSize(ctx, spaceId) + size, err := fx.StorageSize(ctx, spaceId) require.NoError(t, err) assert.Equal(t, sumSize, size) }) @@ -55,7 +55,7 @@ func TestRedisIndex_Bind(t *testing.T) { require.NoError(t, fx.Bind(ctx, spaceId, fileId, bs)) require.NoError(t, fx.Bind(ctx, spaceId, fileId, bs)) - size, err := fx.SpaceSize(ctx, spaceId) + size, err := fx.StorageSize(ctx, spaceId) require.NoError(t, err) assert.Equal(t, sumSize, size) }) @@ -76,7 +76,7 @@ func TestRedisIndex_BindCids(t *testing.T) { require.NoError(t, fx.Bind(ctx, spaceId, fileId1, bs)) require.NoError(t, fx.BindCids(ctx, spaceId, fileId2, testutil.BlocksToKeys(bs))) - size, err := fx.SpaceSize(ctx, spaceId) + size, err := fx.StorageSize(ctx, spaceId) require.NoError(t, err) assert.Equal(t, sumSize, size) diff --git a/index/redisindex/redisindex.go b/index/redisindex/redisindex.go index fd7b820..2174368 100644 --- a/index/redisindex/redisindex.go +++ b/index/redisindex/redisindex.go @@ -35,7 +35,7 @@ const CName = "filenode.redisindex" var log = logger.NewNamed(CName) const ( - spaceSizeKey = "size" + storeSizeKey = "size" ) func New() index.Index { @@ -93,9 +93,9 @@ func (r *redisIndex) GetNonExistentBlocks(ctx context.Context, bs []blocks.Block return } -func (r *redisIndex) Bind(ctx context.Context, spaceId, fileId string, bs []blocks.Block) error { +func (r *redisIndex) Bind(ctx context.Context, key, fileId string, bs []blocks.Block) error { bop := bindOp{ - sk: spaceKey(spaceId), + sk: storageKey(key), fk: fileIdKey(fileId), ri: r, } @@ -106,7 +106,7 @@ func (r *redisIndex) Bind(ctx context.Context, spaceId, fileId string, bs []bloc return r.cidsAddRef(ctx, newCids) } -func (r *redisIndex) BindCids(ctx context.Context, spaceId, fileId string, ks []cid.Cid) error { +func (r *redisIndex) BindCids(ctx context.Context, key, fileId string, ks []cid.Cid) error { cids, err := r.cidInfoByKeys(ctx, ks) if err != nil { return err @@ -115,7 +115,7 @@ func (r *redisIndex) BindCids(ctx context.Context, spaceId, fileId string, ks [] return index.ErrCidsNotExist } bop := bindOp{ - sk: spaceKey(spaceId), + sk: storageKey(key), fk: fileIdKey(fileId), ri: r, } @@ -128,7 +128,7 @@ func (r *redisIndex) BindCids(ctx context.Context, spaceId, fileId string, ks [] func (r *redisIndex) UnBind(ctx context.Context, spaceId, fileId string) (err error) { uop := unbindOp{ - sk: spaceKey(spaceId), + sk: storageKey(spaceId), fk: fileIdKey(fileId), ri: r, } @@ -139,8 +139,8 @@ func (r *redisIndex) UnBind(ctx context.Context, spaceId, fileId string) (err er return r.cidsRemoveRef(ctx, removedCids) } -func (r *redisIndex) ExistsInSpace(ctx context.Context, spaceId string, ks []cid.Cid) (exists []cid.Cid, err error) { - var sk = spaceKey(spaceId) +func (r *redisIndex) ExistsInStorage(ctx context.Context, spaceId string, ks []cid.Cid) (exists []cid.Cid, err error) { + var sk = storageKey(spaceId) cidKeys := make([]string, len(ks)) for i, k := range ks { cidKeys[i] = k.String() @@ -158,8 +158,8 @@ func (r *redisIndex) ExistsInSpace(ctx context.Context, spaceId string, ks []cid return } -func (r *redisIndex) SpaceSize(ctx context.Context, spaceId string) (size uint64, err error) { - result, err := r.cl.HGet(ctx, spaceKey(spaceId), spaceSizeKey).Result() +func (r *redisIndex) StorageSize(ctx context.Context, key string) (size uint64, err error) { + result, err := r.cl.HGet(ctx, storageKey(key), storeSizeKey).Result() if err != nil { if err == redis.Nil { err = nil @@ -169,8 +169,8 @@ func (r *redisIndex) SpaceSize(ctx context.Context, spaceId string) (size uint64 return strconv.ParseUint(result, 10, 64) } -func (r *redisIndex) SpaceInfo(ctx context.Context, spaceId string) (info index.SpaceInfo, err error) { - res, err := r.cl.HKeys(ctx, spaceKey(spaceId)).Result() +func (r *redisIndex) StorageInfo(ctx context.Context, key string) (info index.StorageInfo, err error) { + res, err := r.cl.HKeys(ctx, storageKey(key)).Result() if err != nil { if err == redis.Nil { err = nil @@ -180,15 +180,16 @@ func (r *redisIndex) SpaceInfo(ctx context.Context, spaceId string) (info index. for _, r := range res { if strings.HasPrefix(r, "f:") { info.FileCount++ - } else if r != spaceSizeKey { + } else if r != storeSizeKey { info.CidCount++ } } + info.Key = key return } -func (r *redisIndex) FileInfo(ctx context.Context, spaceId, fileId string) (info index.FileInfo, err error) { - fcl, err := r.newFileCidList(ctx, spaceKey(spaceId), fileIdKey(fileId)) +func (r *redisIndex) FileInfo(ctx context.Context, key, fileId string) (info index.FileInfo, err error) { + fcl, err := r.newFileCidList(ctx, storageKey(key), fileIdKey(fileId)) if err != nil { return } @@ -257,6 +258,7 @@ func (r *redisIndex) cidsRemoveRef(ctx context.Context, cids []CidInfo) error { entry.UpdateTime = now.Unix() entry.Refs-- + // TODO: syncpool data, _ := entry.Marshal() if err = r.cl.Set(ctx, ck, data, 0).Err(); err != nil { return err @@ -337,7 +339,7 @@ func (r *redisIndex) cidInfoByByteKeys(ctx context.Context, ks [][]byte) (info [ return r.cidInfoByKeys(ctx, cids) } -func spaceKey(spaceId string) string { +func storageKey(spaceId string) string { return "s:" + spaceId } diff --git a/index/redisindex/redisindex_test.go b/index/redisindex/redisindex_test.go index b1ec224..a7268b0 100644 --- a/index/redisindex/redisindex_test.go +++ b/index/redisindex/redisindex_test.go @@ -19,12 +19,12 @@ var ctx = context.Background() func TestRedisIndex_Exists(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) - spaceId1 := testutil.NewRandSpaceId() + storeKey := testutil.NewRandSpaceId() var bs = make([]blocks.Block, 1) for i := range bs { bs[i] = testutil.NewRandBlock(rand.Intn(256 * 1024)) } - require.NoError(t, fx.Bind(ctx, spaceId1, "", bs)) + require.NoError(t, fx.Bind(ctx, storeKey, "", bs)) ex, err := fx.Exists(ctx, bs[0].Cid()) require.NoError(t, err) assert.True(t, ex) @@ -33,13 +33,13 @@ func TestRedisIndex_Exists(t *testing.T) { func TestRedisIndex_ExistsInSpace(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) - spaceId1 := testutil.NewRandSpaceId() + storeKey := testutil.NewRandSpaceId() var bs = make([]blocks.Block, 2) for i := range bs { bs[i] = testutil.NewRandBlock(rand.Intn(256 * 1024)) } - require.NoError(t, fx.Bind(ctx, spaceId1, testutil.NewRandCid().String(), bs[:1])) - ex, err := fx.ExistsInSpace(ctx, spaceId1, testutil.BlocksToKeys(bs)) + require.NoError(t, fx.Bind(ctx, storeKey, testutil.NewRandCid().String(), bs[:1])) + ex, err := fx.ExistsInStorage(ctx, storeKey, testutil.BlocksToKeys(bs)) require.NoError(t, err) assert.Len(t, ex, 1) } @@ -47,13 +47,13 @@ func TestRedisIndex_ExistsInSpace(t *testing.T) { func TestRedisIndex_IsAllExists(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) - spaceId1 := testutil.NewRandSpaceId() + storeKey := testutil.NewRandSpaceId() fileId := testutil.NewRandCid().String() var bs = make([]blocks.Block, 2) for i := range bs { bs[i] = testutil.NewRandBlock(rand.Intn(256 * 1024)) } - require.NoError(t, fx.Bind(ctx, spaceId1, fileId, bs[:1])) + require.NoError(t, fx.Bind(ctx, storeKey, fileId, bs[:1])) keys := testutil.BlocksToKeys(bs) exists, err := fx.IsAllExists(ctx, keys) require.NoError(t, err) @@ -66,13 +66,13 @@ func TestRedisIndex_IsAllExists(t *testing.T) { func TestRedisIndex_GetNonExistentBlocks(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) - spaceId1 := testutil.NewRandSpaceId() + storeKey := testutil.NewRandSpaceId() fileId := testutil.NewRandCid().String() var bs = make([]blocks.Block, 2) for i := range bs { bs[i] = testutil.NewRandBlock(rand.Intn(256 * 1024)) } - require.NoError(t, fx.Bind(ctx, spaceId1, fileId, bs[:1])) + require.NoError(t, fx.Bind(ctx, storeKey, fileId, bs[:1])) nonExistent, err := fx.GetNonExistentBlocks(ctx, bs) require.NoError(t, err) @@ -81,12 +81,32 @@ func TestRedisIndex_GetNonExistentBlocks(t *testing.T) { } func TestRedisIndex_SpaceSize(t *testing.T) { - fx := newFixture(t) - defer fx.Finish(t) - spaceId1 := testutil.NewRandSpaceId() - size, err := fx.SpaceSize(ctx, spaceId1) - require.NoError(t, err) - assert.Empty(t, size) + t.Run("space not found", func(t *testing.T) { + fx := newFixture(t) + defer fx.Finish(t) + storeKey := testutil.NewRandSpaceId() + size, err := fx.StorageSize(ctx, storeKey) + require.NoError(t, err) + assert.Empty(t, size) + }) + t.Run("success", func(t *testing.T) { + fx := newFixture(t) + defer fx.Finish(t) + var storeKey = testutil.NewRandSpaceId() + var expectedSize int + fileId := testutil.NewRandCid().String() + var bs = make([]blocks.Block, 2) + for i := range bs { + bs[i] = testutil.NewRandBlock(1024) + expectedSize += 1024 + } + require.NoError(t, fx.AddBlocks(ctx, bs)) + require.NoError(t, fx.Bind(ctx, storeKey, fileId, bs)) + + size, err := fx.StorageSize(ctx, storeKey) + require.NoError(t, err) + assert.Equal(t, expectedSize, int(size)) + }) } func TestRedisIndex_Lock(t *testing.T) { @@ -117,12 +137,12 @@ func Test100KCids(t *testing.T) { for n := range bs { bs[n] = testutil.NewRandBlock(rand.Intn(256)) } - spaceId := testutil.NewRandSpaceId() + storeKey := testutil.NewRandSpaceId() fileId := testutil.NewRandCid().String() - require.NoError(t, fx.Bind(ctx, spaceId, fileId, bs)) + require.NoError(t, fx.Bind(ctx, storeKey, fileId, bs)) t.Logf("bound %d cid for a %v", len(bs), time.Since(st)) st = time.Now() - sz, err := fx.SpaceSize(ctx, spaceId) + sz, err := fx.StorageSize(ctx, storeKey) require.NoError(t, err) t.Logf("space size is %d, dur: %v", sz, time.Since(st)) } diff --git a/index/redisindex/unbind.go b/index/redisindex/unbind.go index 394a2a4..74ba230 100644 --- a/index/redisindex/unbind.go +++ b/index/redisindex/unbind.go @@ -78,7 +78,7 @@ func (op *unbindOp) Unbind(ctx context.Context) (removedCids []CidInfo, err erro // increment space size if spaceDecreaseSize > 0 { - if err = op.ri.cl.HIncrBy(ctx, op.sk, spaceSizeKey, -int64(spaceDecreaseSize)).Err(); err != nil { + if err = op.ri.cl.HIncrBy(ctx, op.sk, storeSizeKey, -int64(spaceDecreaseSize)).Err(); err != nil { return nil, err } } diff --git a/index/redisindex/unbind_test.go b/index/redisindex/unbind_test.go index bbf16f2..7ea6535 100644 --- a/index/redisindex/unbind_test.go +++ b/index/redisindex/unbind_test.go @@ -23,7 +23,7 @@ func TestRedisIndex_UnBind(t *testing.T) { require.NoError(t, fx.Bind(ctx, spaceId, fileId, bs)) require.NoError(t, fx.UnBind(ctx, spaceId, fileId)) - size, err := fx.SpaceSize(ctx, spaceId) + size, err := fx.StorageSize(ctx, spaceId) require.NoError(t, err) assert.Empty(t, size) @@ -48,13 +48,13 @@ func TestRedisIndex_UnBind(t *testing.T) { require.NoError(t, fx.Bind(ctx, spaceId, fileId1, bs)) require.NoError(t, fx.Bind(ctx, spaceId, fileId2, bs[:3])) - si, err := fx.SpaceInfo(ctx, spaceId) + si, err := fx.StorageInfo(ctx, spaceId) require.NoError(t, err) assert.Equal(t, 2, si.FileCount) assert.Equal(t, len(bs), si.CidCount) require.NoError(t, fx.UnBind(ctx, spaceId, fileId1)) - si, err = fx.SpaceInfo(ctx, spaceId) + si, err = fx.StorageInfo(ctx, spaceId) require.NoError(t, err) assert.Equal(t, 1, si.FileCount) assert.Equal(t, 3, si.CidCount) diff --git a/limit/limit.go b/limit/limit.go index e82b74d..4b23438 100644 --- a/limit/limit.go +++ b/limit/limit.go @@ -21,7 +21,7 @@ func New() Limit { } type Limit interface { - Check(ctx context.Context, spaceId string) (limit uint64, err error) + Check(ctx context.Context, spaceId string) (limit uint64, storageKey string, err error) app.ComponentRunnable } @@ -47,7 +47,7 @@ func (l *limit) Run(ctx context.Context) (err error) { return } -func (l *limit) Check(ctx context.Context, spaceId string) (limit uint64, err error) { +func (l *limit) Check(ctx context.Context, spaceId string) (limit uint64, storageKey string, err error) { identity, err := peer.CtxIdentity(ctx) if err != nil { return @@ -56,7 +56,8 @@ func (l *limit) Check(ctx context.Context, spaceId string) (limit uint64, err er if err != nil { return } - return obj.(*entry).GetLimit(), nil + e := obj.(*entry) + return e.GetLimit(), e.storageKey, nil } func (l *limit) fetchLimit(ctx context.Context, id string) (value ocache.Object, err error) { @@ -64,15 +65,17 @@ func (l *limit) fetchLimit(ctx context.Context, id string) (value ocache.Object, if err != nil { return } - limitBytes, err := l.cl.FileLimitCheck(ctx, spaceId, identity) + result, err := l.cl.FileLimitCheck(ctx, spaceId, identity) if err != nil { return nil, err } + return &entry{ - spaceId: spaceId, - identity: identity, - lastUsage: atomic.NewTime(time.Now()), - limit: limitBytes, + spaceId: spaceId, + identity: identity, + lastUsage: atomic.NewTime(time.Now()), + limit: result.Limit, + storageKey: result.StorageKey, }, nil } @@ -97,10 +100,11 @@ func decodeId(id string) (spaceId string, identity []byte, err error) { } type entry struct { - spaceId string - identity []byte - lastUsage *atomic.Time - limit uint64 + spaceId string + identity []byte + lastUsage *atomic.Time + limit uint64 + storageKey string } func (e *entry) TryClose(objectTTL time.Duration) (res bool, err error) { diff --git a/limit/limit_test.go b/limit/limit_test.go index 878e153..fa91176 100644 --- a/limit/limit_test.go +++ b/limit/limit_test.go @@ -5,6 +5,7 @@ import ( "github.com/anyproto/any-sync/app" "github.com/anyproto/any-sync/coordinator/coordinatorclient" "github.com/anyproto/any-sync/coordinator/coordinatorclient/mock_coordinatorclient" + "github.com/anyproto/any-sync/coordinator/coordinatorproto" "github.com/anyproto/any-sync/net/peer" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -17,21 +18,26 @@ var ctx = context.Background() func TestLimit_Check(t *testing.T) { var spaceId = "122345.123" var identity = []byte("identity") - t.Run("succes", func(t *testing.T) { + t.Run("success space", func(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) - fx.client.EXPECT().FileLimitCheck(gomock.Any(), spaceId, identity).Return(uint64(123), nil) - res, err := fx.Check(peer.CtxWithIdentity(ctx, identity), spaceId) + fx.client.EXPECT().FileLimitCheck(gomock.Any(), spaceId, identity).Return(&coordinatorproto.FileLimitCheckResponse{ + Limit: 123, + StorageKey: "sk", + }, nil) + res, storageKey, err := fx.Check(peer.CtxWithIdentity(ctx, identity), spaceId) require.NoError(t, err) assert.Equal(t, uint64(123), res) - res, err = fx.Check(peer.CtxWithIdentity(ctx, identity), spaceId) + assert.Equal(t, "sk", storageKey) + res, storageKey, err = fx.Check(peer.CtxWithIdentity(ctx, identity), spaceId) require.NoError(t, err) assert.Equal(t, uint64(123), res) + assert.Equal(t, "sk", storageKey) }) t.Run("no identity", func(t *testing.T) { fx := newFixture(t) defer fx.Finish(t) - _, err := fx.Check(ctx, spaceId) + _, _, err := fx.Check(ctx, spaceId) require.Error(t, err) }) diff --git a/limit/mock_limit/mock_limit.go b/limit/mock_limit/mock_limit.go index b4889c0..59f9585 100644 --- a/limit/mock_limit/mock_limit.go +++ b/limit/mock_limit/mock_limit.go @@ -36,12 +36,13 @@ func (m *MockLimit) EXPECT() *MockLimitMockRecorder { } // Check mocks base method. -func (m *MockLimit) Check(arg0 context.Context, arg1 string) (uint64, error) { +func (m *MockLimit) Check(arg0 context.Context, arg1 string) (uint64, string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Check", arg0, arg1) ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } // Check indicates an expected call of Check. From b6a6ce1138306c8c97f00cf5772aab8df25e2a43 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Fri, 15 Sep 2023 11:15:31 +0200 Subject: [PATCH 3/8] rename space -> store --- filenode/filenode.go | 12 ++++++------ filenode/rpchandler.go | 2 +- index/redisindex/redisindex.go | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/filenode/filenode.go b/filenode/filenode.go index fb2edbb..a4a0680 100644 --- a/filenode/filenode.go +++ b/filenode/filenode.go @@ -68,7 +68,7 @@ func (fn *fileNode) Get(ctx context.Context, k cid.Cid) (blocks.Block, error) { } func (fn *fileNode) Add(ctx context.Context, spaceId string, fileId string, bs []blocks.Block) error { - storeKey, err := fn.ValidateSpaceId(ctx, spaceId, true) + storeKey, err := fn.StoreKey(ctx, spaceId, true) if err != nil { return err } @@ -92,7 +92,7 @@ func (fn *fileNode) Add(ctx context.Context, spaceId string, fileId string, bs [ func (fn *fileNode) Check(ctx context.Context, spaceId string, cids ...cid.Cid) (result []*fileproto.BlockAvailability, err error) { var storeKey string if spaceId != "" { - if storeKey, err = fn.ValidateSpaceId(ctx, spaceId, false); err != nil { + if storeKey, err = fn.StoreKey(ctx, spaceId, false); err != nil { return } } @@ -128,7 +128,7 @@ func (fn *fileNode) Check(ctx context.Context, spaceId string, cids ...cid.Cid) } func (fn *fileNode) BlocksBind(ctx context.Context, spaceId, fileId string, cids ...cid.Cid) (err error) { - storeKey, err := fn.ValidateSpaceId(ctx, spaceId, true) + storeKey, err := fn.StoreKey(ctx, spaceId, true) if err != nil { return err } @@ -140,7 +140,7 @@ func (fn *fileNode) BlocksBind(ctx context.Context, spaceId, fileId string, cids return fn.index.BindCids(ctx, storeKey, fileId, cids) } -func (fn *fileNode) ValidateSpaceId(ctx context.Context, spaceId string, checkLimit bool) (storageKey string, err error) { +func (fn *fileNode) StoreKey(ctx context.Context, spaceId string, checkLimit bool) (storageKey string, err error) { if spaceId == "" { return "", fileprotoerr.ErrForbidden } @@ -182,7 +182,7 @@ func (fn *fileNode) SpaceInfo(ctx context.Context, spaceId string) (info *filepr } func (fn *fileNode) FilesDelete(ctx context.Context, spaceId string, fileIds []string) (err error) { - storeKey, err := fn.ValidateSpaceId(ctx, spaceId, false) + storeKey, err := fn.StoreKey(ctx, spaceId, false) if err != nil { return } @@ -195,7 +195,7 @@ func (fn *fileNode) FilesDelete(ctx context.Context, spaceId string, fileIds []s } func (fn *fileNode) FileInfo(ctx context.Context, spaceId, fileId string) (info *fileproto.FileInfo, err error) { - storeKey, err := fn.ValidateSpaceId(ctx, spaceId, false) + storeKey, err := fn.StoreKey(ctx, spaceId, false) if err != nil { return } diff --git a/filenode/rpchandler.go b/filenode/rpchandler.go index 2b06b3b..5ed4e63 100644 --- a/filenode/rpchandler.go +++ b/filenode/rpchandler.go @@ -166,7 +166,7 @@ func (r rpcHandler) FilesInfo(ctx context.Context, req *fileproto.FilesInfoReque resp = &fileproto.FilesInfoResponse{ FilesInfo: make([]*fileproto.FileInfo, len(req.FileIds)), } - _, err = r.f.ValidateSpaceId(ctx, req.SpaceId, false) + _, err = r.f.StoreKey(ctx, req.SpaceId, false) if err != nil { return nil, err } diff --git a/index/redisindex/redisindex.go b/index/redisindex/redisindex.go index 2174368..fe8d25a 100644 --- a/index/redisindex/redisindex.go +++ b/index/redisindex/redisindex.go @@ -22,8 +22,8 @@ import ( CIDS: c:{cid}: proto(Entry) - SPACES: - s:{spaceId}: map + STORES: + s:{storeKey}: map f:{fileId} -> snappy(proto(CidList)) {cid} -> int(refCount) size -> int(summarySize) From 05f472803ed372662d14fb2673b182fe3d06489f Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Fri, 15 Sep 2023 13:31:06 +0200 Subject: [PATCH 4/8] move space to storageKey --- filenode/filenode.go | 8 ++++++++ filenode/filenode_test.go | 5 +++++ index/index.go | 5 ++++- index/mock_index/mock_index.go | 14 ++++++++++++++ index/redisindex/redisindex.go | 24 ++++++++++++++++++++++-- index/redisindex/redisindex_test.go | 26 ++++++++++++++++++++++++++ 6 files changed, 79 insertions(+), 3 deletions(-) diff --git a/filenode/filenode.go b/filenode/filenode.go index a4a0680..6e857b2 100644 --- a/filenode/filenode.go +++ b/filenode/filenode.go @@ -150,6 +150,14 @@ func (fn *fileNode) StoreKey(ctx context.Context, spaceId string, checkLimit boo return } + if storageKey != spaceId { + // try to move store to the new key + mErr := fn.index.MoveStorage(ctx, spaceId, storageKey) + if mErr != nil && mErr != index.ErrStorageNotFound && mErr != index.ErrTargetStorageExists { + return "", mErr + } + } + if checkLimit { currentSize, e := fn.index.StorageSize(ctx, storageKey) if e != nil { diff --git a/filenode/filenode_test.go b/filenode/filenode_test.go index dc51c18..d0ef4a8 100644 --- a/filenode/filenode_test.go +++ b/filenode/filenode_test.go @@ -38,6 +38,7 @@ func TestFileNode_Add(t *testing.T) { ) fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(123), storeKey, nil) + fx.index.EXPECT().MoveStorage(ctx, spaceId, storeKey).AnyTimes() fx.index.EXPECT().StorageSize(ctx, storeKey).Return(uint64(120), nil) fx.index.EXPECT().Lock(ctx, []cid.Cid{b.Cid()}).Return(func() {}, nil) fx.index.EXPECT().GetNonExistentBlocks(ctx, []blocks.Block{b}).Return([]blocks.Block{b}, nil) @@ -64,6 +65,7 @@ func TestFileNode_Add(t *testing.T) { ) fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(123), storeKey, nil) + fx.index.EXPECT().MoveStorage(ctx, spaceId, storeKey).AnyTimes() fx.index.EXPECT().StorageSize(ctx, storeKey).Return(uint64(124), nil) resp, err := fx.handler.BlockPush(ctx, &fileproto.BlockPushRequest{ @@ -155,6 +157,7 @@ func TestFileNode_Check(t *testing.T) { cids = append(cids, b.Cid().Bytes()) } fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(100000), storeKey, nil) + fx.index.EXPECT().MoveStorage(ctx, spaceId, storeKey).AnyTimes() fx.index.EXPECT().ExistsInStorage(ctx, storeKey, testutil.BlocksToKeys(bs)).Return(testutil.BlocksToKeys(bs[:1]), nil) fx.index.EXPECT().Exists(ctx, bs[1].Cid()).Return(true, nil) fx.index.EXPECT().Exists(ctx, bs[2].Cid()).Return(false, nil) @@ -186,6 +189,7 @@ func TestFileNode_BlocksBind(t *testing.T) { } fx.limit.EXPECT().Check(ctx, spaceId).Return(uint64(123), storeKey, nil) + fx.index.EXPECT().MoveStorage(ctx, spaceId, storeKey).AnyTimes() fx.index.EXPECT().StorageSize(ctx, storeKey).Return(uint64(12), nil) fx.index.EXPECT().Lock(ctx, cids).Return(func() {}, nil) fx.index.EXPECT().BindCids(ctx, storeKey, fileId, cids) @@ -210,6 +214,7 @@ func TestFileNode_FileInfo(t *testing.T) { fileId2 = testutil.NewRandCid().String() ) fx.limit.EXPECT().Check(ctx, spaceId).AnyTimes().Return(uint64(100000), storeKey, nil) + fx.index.EXPECT().MoveStorage(ctx, spaceId, storeKey).AnyTimes() fx.index.EXPECT().FileInfo(ctx, storeKey, fileId1).Return(index.FileInfo{1, 1}, nil) fx.index.EXPECT().FileInfo(ctx, storeKey, fileId2).Return(index.FileInfo{2, 2}, nil) diff --git a/index/index.go b/index/index.go index 28fa065..147376a 100644 --- a/index/index.go +++ b/index/index.go @@ -10,7 +10,9 @@ import ( ) var ( - ErrCidsNotExist = errors.New("cids not exist") + ErrCidsNotExist = errors.New("cids not exist") + ErrTargetStorageExists = errors.New("target storage exists") + ErrStorageNotFound = errors.New("storage not found") ) type Index interface { @@ -26,6 +28,7 @@ type Index interface { StorageSize(ctx context.Context, key string) (size uint64, err error) Lock(ctx context.Context, ks []cid.Cid) (unlock func(), err error) AddBlocks(ctx context.Context, upload []blocks.Block) error + MoveStorage(ctx context.Context, fromKey, toKey string) error app.Component } diff --git a/index/mock_index/mock_index.go b/index/mock_index/mock_index.go index dfdf9ae..bd82cbe 100644 --- a/index/mock_index/mock_index.go +++ b/index/mock_index/mock_index.go @@ -184,6 +184,20 @@ func (mr *MockIndexMockRecorder) Lock(arg0, arg1 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Lock", reflect.TypeOf((*MockIndex)(nil).Lock), arg0, arg1) } +// MoveStorage mocks base method. +func (m *MockIndex) MoveStorage(arg0 context.Context, arg1, arg2 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MoveStorage", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// MoveStorage indicates an expected call of MoveStorage. +func (mr *MockIndexMockRecorder) MoveStorage(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MoveStorage", reflect.TypeOf((*MockIndex)(nil).MoveStorage), arg0, arg1, arg2) +} + // Name mocks base method. func (m *MockIndex) Name() string { m.ctrl.T.Helper() diff --git a/index/redisindex/redisindex.go b/index/redisindex/redisindex.go index fe8d25a..735bde5 100644 --- a/index/redisindex/redisindex.go +++ b/index/redisindex/redisindex.go @@ -205,6 +205,26 @@ func (r *redisIndex) FileInfo(ctx context.Context, key, fileId string) (info ind return } +func (r *redisIndex) MoveStorage(ctx context.Context, fromKey, toKey string) (err error) { + ok, err := r.cl.RenameNX(ctx, storageKey(fromKey), storageKey(toKey)).Result() + if err != nil { + if err.Error() == "ERR no such key" { + return index.ErrStorageNotFound + } + return err + } + if !ok { + ex, err := r.cl.Exists(ctx, storageKey(toKey)).Result() + if err != nil { + return err + } + if ex > 0 { + return index.ErrTargetStorageExists + } + } + return +} + func (r *redisIndex) cidsAddRef(ctx context.Context, cids []CidInfo) error { now := time.Now() for _, c := range cids { @@ -339,8 +359,8 @@ func (r *redisIndex) cidInfoByByteKeys(ctx context.Context, ks [][]byte) (info [ return r.cidInfoByKeys(ctx, cids) } -func storageKey(spaceId string) string { - return "s:" + spaceId +func storageKey(storeKey string) string { + return "s:" + storeKey } func fileIdKey(fileId string) string { diff --git a/index/redisindex/redisindex_test.go b/index/redisindex/redisindex_test.go index a7268b0..902f53d 100644 --- a/index/redisindex/redisindex_test.go +++ b/index/redisindex/redisindex_test.go @@ -2,6 +2,7 @@ package redisindex import ( "context" + "github.com/anyproto/any-sync-filenode/index" "github.com/anyproto/any-sync-filenode/redisprovider/testredisprovider" "github.com/anyproto/any-sync-filenode/testutil" "github.com/anyproto/any-sync/app" @@ -127,6 +128,31 @@ func TestRedisIndex_Lock(t *testing.T) { unlock() } +func TestRedisIndex_MoveStorage(t *testing.T) { + const ( + oldKey = "oldKey" + newKey = "newKey" + ) + t.Run("success", func(t *testing.T) { + fx := newFixture(t) + defer fx.Finish(t) + require.NoError(t, fx.Bind(ctx, oldKey, "fid", testutil.NewRandBlocks(1))) + require.NoError(t, fx.MoveStorage(ctx, oldKey, newKey)) + }) + t.Run("err storage not found", func(t *testing.T) { + fx := newFixture(t) + defer fx.Finish(t) + assert.EqualError(t, fx.MoveStorage(ctx, oldKey, newKey), index.ErrStorageNotFound.Error()) + }) + t.Run("err taget exists", func(t *testing.T) { + fx := newFixture(t) + defer fx.Finish(t) + require.NoError(t, fx.Bind(ctx, oldKey, "fid", testutil.NewRandBlocks(1))) + require.NoError(t, fx.Bind(ctx, newKey, "fid", testutil.NewRandBlocks(1))) + assert.EqualError(t, fx.MoveStorage(ctx, oldKey, newKey), index.ErrTargetStorageExists.Error()) + }) +} + func Test100KCids(t *testing.T) { t.Skip() fx := newFixture(t) From bdad87fe8877618ee2a19de5a10aa16a94bd3329 Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Fri, 15 Sep 2023 13:43:47 +0200 Subject: [PATCH 5/8] check in case old coordinator, do not up lastUsage --- limit/limit.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/limit/limit.go b/limit/limit.go index 4b23438..e05c134 100644 --- a/limit/limit.go +++ b/limit/limit.go @@ -57,7 +57,7 @@ func (l *limit) Check(ctx context.Context, spaceId string) (limit uint64, storag return } e := obj.(*entry) - return e.GetLimit(), e.storageKey, nil + return e.limit, e.storageKey, nil } func (l *limit) fetchLimit(ctx context.Context, id string) (value ocache.Object, err error) { @@ -70,6 +70,9 @@ func (l *limit) fetchLimit(ctx context.Context, id string) (value ocache.Object, return nil, err } + if result.StorageKey == "" { + result.StorageKey = spaceId + } return &entry{ spaceId: spaceId, identity: identity, @@ -114,11 +117,6 @@ func (e *entry) TryClose(objectTTL time.Duration) (res bool, err error) { return true, e.Close() } -func (e *entry) GetLimit() uint64 { - e.lastUsage.Store(time.Now()) - return e.limit -} - func (e *entry) Close() error { return nil } From 05f0bba32d56d63d02aafd32a58fffd9f440b623 Mon Sep 17 00:00:00 2001 From: Grigory Efimov Date: Fri, 15 Sep 2023 12:53:10 +0000 Subject: [PATCH 6/8] .github/workflows/coverage.yml fixed --- .github/workflows/coverage.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index db553ef..d5403b1 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -3,6 +3,8 @@ on: branches: - main +name: coverage + permissions: contents: write pull-requests: write @@ -16,6 +18,17 @@ jobs: - '1.21' env: GOPRIVATE: github.com/anyproto + # redis for tests + services: + redis: + image: redis + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 6379:6379 steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 @@ -26,6 +39,7 @@ jobs: - name: git config run: git config --global url.https://${{ secrets.ANYTYPE_PAT }}@github.com/.insteadOf https://github.com/ + # check license {{ - name: Setup license repository uses: actions/checkout@master with: @@ -40,12 +54,13 @@ jobs: sudo gem install license_finder license_finder inherited_decisions add open/decisions.yml license_finder --enabled-package-managers gomodules + # }} - name: deps - run: make deps + run: make deps CGO_ENABLED=0 - name: unit tests - run: make test + run: make test CGO_ENABLED=0 - name: Quality Gate - Test coverage shall be above threshold env: From a1e10768444db9adc16b79fe5980637358324de8 Mon Sep 17 00:00:00 2001 From: Grigory Efimov Date: Fri, 15 Sep 2023 13:42:23 +0000 Subject: [PATCH 7/8] .github/workflows/coverage.yml fixed --- .github/workflows/coverage.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index d5403b1..aa4be9a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -5,10 +5,6 @@ on: name: coverage -permissions: - contents: write - pull-requests: write - jobs: test: runs-on: ubuntu-latest From b9cd37eb5a1012b226bd89072ec2c2d80598d66a Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Thu, 21 Sep 2023 14:21:09 +0200 Subject: [PATCH 8/8] update any-sync --- go.mod | 6 +++--- go.sum | 22 ++++++---------------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index f224d26..4679c6c 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/ahmetb/govvv v0.3.0 - github.com/anyproto/any-sync v0.3.1-0.20230914174308-e178d8f8c67e + github.com/anyproto/any-sync v0.3.1 github.com/aws/aws-sdk-go v1.44.327 github.com/go-redsync/redsync/v4 v4.8.1 github.com/gogo/protobuf v1.3.2 @@ -14,8 +14,8 @@ require ( github.com/redis/go-redis/v9 v9.1.0 github.com/stretchr/testify v1.8.4 go.uber.org/atomic v1.11.0 - go.uber.org/mock v0.2.0 - go.uber.org/zap v1.25.0 + go.uber.org/mock v0.3.0 + go.uber.org/zap v1.26.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index da45ba9..819861d 100644 --- a/go.sum +++ b/go.sum @@ -4,16 +4,8 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ahmetb/govvv v0.3.0 h1:YGLGwEyiUwHFy5eh/RUhdupbuaCGBYn5T5GWXp+WJB0= github.com/ahmetb/govvv v0.3.0/go.mod h1:4WRFpdWtc/YtKgPFwa1dr5+9hiRY5uKAL08bOlxOR6s= -github.com/anyproto/any-sync v0.3.0 h1:4lVxHf6aA2BrefGqjzbyn/wnSuNoriU2o8IsABBMfJE= -github.com/anyproto/any-sync v0.3.0/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= -github.com/anyproto/any-sync v0.3.1-0.20230913182213-8f26b7dbfe3b h1:i27ykx2q6tIf45rgN/YiBKTW37Q+Nk496jw37HXQaa4= -github.com/anyproto/any-sync v0.3.1-0.20230913182213-8f26b7dbfe3b/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= -github.com/anyproto/any-sync v0.3.1-0.20230914161813-89373e5247f8 h1:Lt0BTdd7tN+ImIBuKf2vLphxi1hVZIlw9MZcM6ZaqZM= -github.com/anyproto/any-sync v0.3.1-0.20230914161813-89373e5247f8/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= -github.com/anyproto/any-sync v0.3.1-0.20230914163253-f7e95db95bd1 h1:naGWtEfprsVMestVHQHIJyAxdqnMdyo/dS+SCVtr8OY= -github.com/anyproto/any-sync v0.3.1-0.20230914163253-f7e95db95bd1/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= -github.com/anyproto/any-sync v0.3.1-0.20230914174308-e178d8f8c67e h1:APK2DvVUXEWxch6EePmjBpqCY/RWckiZwpnfuLktfsE= -github.com/anyproto/any-sync v0.3.1-0.20230914174308-e178d8f8c67e/go.mod h1:8uddvzx/4Le7c9v5tb0jgma4GuAWfUDMTeRCBLu0MTo= +github.com/anyproto/any-sync v0.3.1 h1:AHsIYyhM9J+eqKVjnsuGgT/4u+f47JyEhfIBMnDLIIA= +github.com/anyproto/any-sync v0.3.1/go.mod h1:v0w3l3FBWjzNgg5t8aWlI+aYkcA8kLaoJFfr/GHsWYk= github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY= github.com/anyproto/go-chash v0.1.0/go.mod h1:0UjNQi3PDazP0fINpFYu6VKhuna+W/V+1vpXHAfNgLY= github.com/anyproto/go-slip10 v1.0.0 h1:uAEtSuudR3jJBOfkOXf3bErxVoxbuKwdoJN55M1i6IA= @@ -23,8 +15,6 @@ github.com/anyproto/go-slip21 v1.0.0/go.mod h1:gbIJt7HAdr5DuT4f2pFTKCBSUWYsm/fys github.com/aws/aws-sdk-go v1.44.327 h1:ZS8oO4+7MOBLhkdwIhgtVeDzCeWOlTfKJS7EgggbIEY= github.com/aws/aws-sdk-go v1.44.327/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= -github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bsm/ginkgo/v2 v2.5.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= @@ -234,14 +224,14 @@ go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0 go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= -go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU= -go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM= +go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=