Tests and refactoring
This commit is contained in:
parent
b24f79645d
commit
694973a4e3
@ -21,7 +21,7 @@ type DiffService interface {
|
|||||||
RemoveObjects(ids []string)
|
RemoveObjects(ids []string)
|
||||||
AllIds() []string
|
AllIds() []string
|
||||||
|
|
||||||
Init(objectIds []string, deletionState *deletionstate.DeletionState)
|
Init(objectIds []string, deletionState deletionstate.DeletionState)
|
||||||
Close() (err error)
|
Close() (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ func NewDiffService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *diffService) Init(objectIds []string, deletionState *deletionstate.DeletionState) {
|
func (d *diffService) Init(objectIds []string, deletionState deletionstate.DeletionState) {
|
||||||
d.fillDiff(objectIds)
|
d.fillDiff(objectIds)
|
||||||
d.syncer.Init(deletionState)
|
d.syncer.Init(deletionState)
|
||||||
d.periodicSync.Run()
|
d.periodicSync.Run()
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type DiffSyncer interface {
|
|||||||
Sync(ctx context.Context) error
|
Sync(ctx context.Context) error
|
||||||
RemoveObjects(ids []string)
|
RemoveObjects(ids []string)
|
||||||
UpdateHeads(id string, heads []string)
|
UpdateHeads(id string, heads []string)
|
||||||
Init(deletionState *deletionstate.DeletionState)
|
Init(deletionState deletionstate.DeletionState)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDiffSyncer(
|
func newDiffSyncer(
|
||||||
@ -49,10 +49,10 @@ type diffSyncer struct {
|
|||||||
storage storage.SpaceStorage
|
storage storage.SpaceStorage
|
||||||
clientFactory spacesyncproto.ClientFactory
|
clientFactory spacesyncproto.ClientFactory
|
||||||
log *zap.Logger
|
log *zap.Logger
|
||||||
deletionState *deletionstate.DeletionState
|
deletionState deletionstate.DeletionState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *diffSyncer) Init(deletionState *deletionstate.DeletionState) {
|
func (d *diffSyncer) Init(deletionState deletionstate.DeletionState) {
|
||||||
d.deletionState = deletionState
|
d.deletionState = deletionState
|
||||||
d.deletionState.AddObserver(d.RemoveObjects)
|
d.deletionState.AddObserver(d.RemoveObjects)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,17 +8,21 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Deleter interface {
|
||||||
|
Delete()
|
||||||
|
}
|
||||||
|
|
||||||
type deleter struct {
|
type deleter struct {
|
||||||
st storage.SpaceStorage
|
st storage.SpaceStorage
|
||||||
state *deletionstate.DeletionState
|
state deletionstate.DeletionState
|
||||||
getter treegetter.TreeGetter
|
getter treegetter.TreeGetter
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDeleter(st storage.SpaceStorage, state *deletionstate.DeletionState, getter treegetter.TreeGetter) *deleter {
|
func newDeleter(st storage.SpaceStorage, state deletionstate.DeletionState, getter treegetter.TreeGetter) Deleter {
|
||||||
return &deleter{st, state, getter}
|
return &deleter{st, state, getter}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deleter) delete() {
|
func (d *deleter) Delete() {
|
||||||
allQueued := d.state.GetQueued()
|
allQueued := d.state.GetQueued()
|
||||||
for _, id := range allQueued {
|
for _, id := range allQueued {
|
||||||
err := d.getter.DeleteTree(context.Background(), d.st.Id(), id)
|
err := d.getter.DeleteTree(context.Background(), d.st.Id(), id)
|
||||||
|
|||||||
@ -7,7 +7,16 @@ import (
|
|||||||
|
|
||||||
type StateUpdateObserver func(ids []string)
|
type StateUpdateObserver func(ids []string)
|
||||||
|
|
||||||
type DeletionState struct {
|
type DeletionState interface {
|
||||||
|
AddObserver(observer StateUpdateObserver)
|
||||||
|
Add(ids []string) (err error)
|
||||||
|
GetQueued() (ids []string)
|
||||||
|
Delete(id string) (err error)
|
||||||
|
Exists(id string) bool
|
||||||
|
FilterJoin(ids ...[]string) (filtered []string)
|
||||||
|
}
|
||||||
|
|
||||||
|
type deletionState struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
queued map[string]struct{}
|
queued map[string]struct{}
|
||||||
deleted map[string]struct{}
|
deleted map[string]struct{}
|
||||||
@ -15,21 +24,21 @@ type DeletionState struct {
|
|||||||
storage storage.SpaceStorage
|
storage storage.SpaceStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeletionState(storage storage.SpaceStorage) *DeletionState {
|
func NewDeletionState(storage storage.SpaceStorage) DeletionState {
|
||||||
return &DeletionState{
|
return &deletionState{
|
||||||
queued: map[string]struct{}{},
|
queued: map[string]struct{}{},
|
||||||
deleted: map[string]struct{}{},
|
deleted: map[string]struct{}{},
|
||||||
storage: storage,
|
storage: storage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *DeletionState) AddObserver(observer StateUpdateObserver) {
|
func (st *deletionState) AddObserver(observer StateUpdateObserver) {
|
||||||
st.Lock()
|
st.Lock()
|
||||||
defer st.Unlock()
|
defer st.Unlock()
|
||||||
st.stateUpdateObservers = append(st.stateUpdateObservers, observer)
|
st.stateUpdateObservers = append(st.stateUpdateObservers, observer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *DeletionState) Add(ids []string) (err error) {
|
func (st *deletionState) Add(ids []string) (err error) {
|
||||||
st.Lock()
|
st.Lock()
|
||||||
defer func() {
|
defer func() {
|
||||||
st.Unlock()
|
st.Unlock()
|
||||||
@ -71,7 +80,7 @@ func (st *DeletionState) Add(ids []string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *DeletionState) GetQueued() (ids []string) {
|
func (st *deletionState) GetQueued() (ids []string) {
|
||||||
st.RLock()
|
st.RLock()
|
||||||
defer st.RUnlock()
|
defer st.RUnlock()
|
||||||
ids = make([]string, 0, len(st.queued))
|
ids = make([]string, 0, len(st.queued))
|
||||||
@ -81,7 +90,7 @@ func (st *DeletionState) GetQueued() (ids []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *DeletionState) Delete(id string) (err error) {
|
func (st *deletionState) Delete(id string) (err error) {
|
||||||
st.Lock()
|
st.Lock()
|
||||||
defer st.Unlock()
|
defer st.Unlock()
|
||||||
delete(st.queued, id)
|
delete(st.queued, id)
|
||||||
@ -93,13 +102,13 @@ func (st *DeletionState) Delete(id string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *DeletionState) Exists(id string) bool {
|
func (st *deletionState) Exists(id string) bool {
|
||||||
st.RLock()
|
st.RLock()
|
||||||
defer st.RUnlock()
|
defer st.RUnlock()
|
||||||
return st.exists(id)
|
return st.exists(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *DeletionState) FilterJoin(ids ...[]string) (filtered []string) {
|
func (st *deletionState) FilterJoin(ids ...[]string) (filtered []string) {
|
||||||
st.RLock()
|
st.RLock()
|
||||||
defer st.RUnlock()
|
defer st.RUnlock()
|
||||||
filter := func(ids []string) {
|
filter := func(ids []string) {
|
||||||
@ -115,7 +124,7 @@ func (st *DeletionState) FilterJoin(ids ...[]string) (filtered []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *DeletionState) exists(id string) bool {
|
func (st *deletionState) exists(id string) bool {
|
||||||
if _, exists := st.deleted[id]; exists {
|
if _, exists := st.deleted[id]; exists {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
//go:generate mockgen -destination mock_settingsdocument/mock_settingsdocument.go github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/settingsdocument DeletedIdsProvider
|
|
||||||
package settingsdocument
|
package settingsdocument
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/settingsdocument (interfaces: DeletedIdsProvider)
|
// Source: github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/settingsdocument (interfaces: DeletedIdsProvider,Deleter)
|
||||||
|
|
||||||
// Package mock_settingsdocument is a generated GoMock package.
|
// Package mock_settingsdocument is a generated GoMock package.
|
||||||
package mock_settingsdocument
|
package mock_settingsdocument
|
||||||
@ -49,3 +49,38 @@ func (mr *MockDeletedIdsProviderMockRecorder) ProvideIds(arg0, arg1 interface{})
|
|||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvideIds", reflect.TypeOf((*MockDeletedIdsProvider)(nil).ProvideIds), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProvideIds", reflect.TypeOf((*MockDeletedIdsProvider)(nil).ProvideIds), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MockDeleter is a mock of Deleter interface.
|
||||||
|
type MockDeleter struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockDeleterMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockDeleterMockRecorder is the mock recorder for MockDeleter.
|
||||||
|
type MockDeleterMockRecorder struct {
|
||||||
|
mock *MockDeleter
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockDeleter creates a new mock instance.
|
||||||
|
func NewMockDeleter(ctrl *gomock.Controller) *MockDeleter {
|
||||||
|
mock := &MockDeleter{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockDeleterMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockDeleter) EXPECT() *MockDeleterMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete mocks base method.
|
||||||
|
func (m *MockDeleter) Delete() {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "Delete")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete indicates an expected call of Delete.
|
||||||
|
func (mr *MockDeleterMockRecorder) Delete() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockDeleter)(nil).Delete))
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
//go:generate mockgen -destination mock_settingsdocument/mock_settingsdocument.go github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/settingsdocument DeletedIdsProvider,Deleter
|
||||||
package settingsdocument
|
package settingsdocument
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -29,9 +30,10 @@ type Deps struct {
|
|||||||
Account account.Service
|
Account account.Service
|
||||||
TreeGetter treegetter.TreeGetter
|
TreeGetter treegetter.TreeGetter
|
||||||
Store spacestorage.SpaceStorage
|
Store spacestorage.SpaceStorage
|
||||||
DeletionState *deletionstate.DeletionState
|
DeletionState deletionstate.DeletionState
|
||||||
// prov exists mainly for the ease of testing
|
// testing dependencies
|
||||||
prov DeletedIdsProvider
|
prov DeletedIdsProvider
|
||||||
|
del Deleter
|
||||||
}
|
}
|
||||||
|
|
||||||
type settingsDocument struct {
|
type settingsDocument struct {
|
||||||
@ -44,14 +46,20 @@ type settingsDocument struct {
|
|||||||
buildFunc BuildTreeFunc
|
buildFunc BuildTreeFunc
|
||||||
loop *deleteLoop
|
loop *deleteLoop
|
||||||
|
|
||||||
deletionState *deletionstate.DeletionState
|
deletionState deletionstate.DeletionState
|
||||||
lastChangeId string
|
lastChangeId string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSettingsDocument(deps Deps, spaceId string) (doc SettingsDocument, err error) {
|
func NewSettingsDocument(deps Deps, spaceId string) (doc SettingsDocument) {
|
||||||
deleter := newDeleter(deps.Store, deps.DeletionState, deps.TreeGetter)
|
var deleter Deleter
|
||||||
|
if deps.del == nil {
|
||||||
|
deleter = newDeleter(deps.Store, deps.DeletionState, deps.TreeGetter)
|
||||||
|
} else {
|
||||||
|
deleter = deps.del
|
||||||
|
}
|
||||||
|
|
||||||
loop := newDeleteLoop(func() {
|
loop := newDeleteLoop(func() {
|
||||||
deleter.delete()
|
deleter.Delete()
|
||||||
})
|
})
|
||||||
deps.DeletionState.AddObserver(func(ids []string) {
|
deps.DeletionState.AddObserver(func(ids []string) {
|
||||||
loop.notify()
|
loop.notify()
|
||||||
@ -89,10 +97,12 @@ func (s *settingsDocument) updateIds(tr tree.ObjectTree, lastChangeId string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update is called as part of UpdateListener interface
|
||||||
func (s *settingsDocument) Update(tr tree.ObjectTree) {
|
func (s *settingsDocument) Update(tr tree.ObjectTree) {
|
||||||
s.updateIds(tr, s.lastChangeId)
|
s.updateIds(tr, s.lastChangeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rebuild is called as part of UpdateListener interface (including when the object is built for the first time, e.g. on Init call)
|
||||||
func (s *settingsDocument) Rebuild(tr tree.ObjectTree) {
|
func (s *settingsDocument) Rebuild(tr tree.ObjectTree) {
|
||||||
// at initial build "s" may not contain the object tree, so it is safer to provide it from the function parameter
|
// at initial build "s" may not contain the object tree, so it is safer to provide it from the function parameter
|
||||||
s.updateIds(tr, "")
|
s.updateIds(tr, "")
|
||||||
@ -128,6 +138,7 @@ func (s *settingsDocument) DeleteObject(id string) (err error) {
|
|||||||
},
|
},
|
||||||
Snapshot: nil,
|
Snapshot: nil,
|
||||||
}
|
}
|
||||||
|
// TODO: add snapshot logic
|
||||||
res, err := change.Marshal()
|
res, err := change.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -1,7 +1,108 @@
|
|||||||
package settingsdocument
|
package settingsdocument
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account/mock_account"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/settingsdocument/deletionstate"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/settingsdocument/mock_settingsdocument"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage/mock_storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/mock_synctree"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter/mock_treegetter"
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type settingsFixture struct {
|
||||||
|
spaceId string
|
||||||
|
docId string
|
||||||
|
doc SettingsDocument
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
treeGetter *mock_treegetter.MockTreeGetter
|
||||||
|
spaceStorage *mock_storage.MockSpaceStorage
|
||||||
|
provider *mock_settingsdocument.MockDeletedIdsProvider
|
||||||
|
deleter *mock_settingsdocument.MockDeleter
|
||||||
|
syncTree *mock_synctree.MockSyncTree
|
||||||
|
delState *deletionstate.DeletionState
|
||||||
|
account *mock_account.MockService
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSettingsFixture(t *testing.T) *settingsFixture {
|
||||||
|
spaceId := "spaceId"
|
||||||
|
docId := "documentId"
|
||||||
|
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
acc := mock_account.NewMockService(ctrl)
|
||||||
|
treeGetter := mock_treegetter.NewMockTreeGetter(ctrl)
|
||||||
|
st := mock_storage.NewMockSpaceStorage(ctrl)
|
||||||
|
delState := deletionstate.NewDeletionState(st)
|
||||||
|
prov := mock_settingsdocument.NewMockDeletedIdsProvider(ctrl)
|
||||||
|
syncTree := mock_synctree.NewMockSyncTree(ctrl)
|
||||||
|
del := mock_settingsdocument.NewMockDeleter(ctrl)
|
||||||
|
|
||||||
|
buildFunc := BuildTreeFunc(func(ctx context.Context, id string, listener updatelistener.UpdateListener) (synctree.SyncTree, error) {
|
||||||
|
require.Equal(t, docId, id)
|
||||||
|
return syncTree, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
deps := Deps{
|
||||||
|
BuildFunc: buildFunc,
|
||||||
|
Account: acc,
|
||||||
|
TreeGetter: treeGetter,
|
||||||
|
Store: st,
|
||||||
|
DeletionState: delState,
|
||||||
|
prov: prov,
|
||||||
|
del: del,
|
||||||
|
}
|
||||||
|
doc := NewSettingsDocument(deps, spaceId)
|
||||||
|
return &settingsFixture{
|
||||||
|
spaceId: spaceId,
|
||||||
|
docId: docId,
|
||||||
|
doc: doc,
|
||||||
|
ctrl: ctrl,
|
||||||
|
treeGetter: treeGetter,
|
||||||
|
spaceStorage: st,
|
||||||
|
provider: prov,
|
||||||
|
deleter: del,
|
||||||
|
syncTree: syncTree,
|
||||||
|
account: acc,
|
||||||
|
delState: delState,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fx *settingsFixture) stop() {
|
||||||
|
fx.ctrl.Finish()
|
||||||
|
}
|
||||||
|
|
||||||
func TestSettingsDocument_Init(t *testing.T) {
|
func TestSettingsDocument_Init(t *testing.T) {
|
||||||
|
fx := newSettingsFixture(t)
|
||||||
|
defer fx.stop()
|
||||||
|
|
||||||
|
fx.spaceStorage.EXPECT().SpaceSettingsId().Return(fx.docId)
|
||||||
|
fx.deleter.EXPECT().Delete()
|
||||||
|
fx.syncTree.EXPECT().Close().Return(nil)
|
||||||
|
|
||||||
|
err := fx.doc.Init(context.Background())
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = fx.doc.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSettingsDocument_DeleteObject(t *testing.T) {
|
||||||
|
fx := newSettingsFixture(t)
|
||||||
|
defer fx.stop()
|
||||||
|
|
||||||
|
fx.spaceStorage.EXPECT().SpaceSettingsId().Return(fx.docId)
|
||||||
|
fx.deleter.EXPECT().Delete()
|
||||||
|
fx.syncTree.EXPECT().Close().Return(nil)
|
||||||
|
|
||||||
|
err := fx.doc.Init(context.Background())
|
||||||
|
require.NoError(t, err)
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
|
||||||
|
err = fx.doc.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -167,10 +167,7 @@ func (s *space) Init(ctx context.Context) (err error) {
|
|||||||
Store: s.storage,
|
Store: s.storage,
|
||||||
DeletionState: deletionState,
|
DeletionState: deletionState,
|
||||||
}
|
}
|
||||||
s.settingsDocument, err = settingsdocument.NewSettingsDocument(deps, s.id)
|
s.settingsDocument = settingsdocument.NewSettingsDocument(deps, s.id)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
objectGetter := newCommonSpaceGetter(s.id, s.aclList, s.cache, s.settingsDocument)
|
objectGetter := newCommonSpaceGetter(s.id, s.aclList, s.cache, s.settingsDocument)
|
||||||
s.syncService.Init(objectGetter)
|
s.syncService.Init(objectGetter)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user