Merge pull request #34 from anytypeio/account-deletion

This commit is contained in:
Mikhail Rakhmanov 2023-02-27 15:40:58 +01:00 committed by GitHub
commit 5906091051
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 1580 additions and 537 deletions

View File

@ -8,7 +8,7 @@ import (
"github.com/anytypeio/any-sync/commonspace/object/tree/synctree"
"github.com/anytypeio/any-sync/commonspace/object/treegetter"
"github.com/anytypeio/any-sync/commonspace/peermanager"
"github.com/anytypeio/any-sync/commonspace/settings/deletionstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
"github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/commonspace/syncstatus"
@ -22,7 +22,7 @@ type DiffSyncer interface {
Sync(ctx context.Context) error
RemoveObjects(ids []string)
UpdateHeads(id string, heads []string)
Init(deletionState deletionstate.DeletionState)
Init(deletionState settingsstate.ObjectDeletionState)
}
func newDiffSyncer(
@ -54,11 +54,11 @@ type diffSyncer struct {
storage spacestorage.SpaceStorage
clientFactory spacesyncproto.ClientFactory
log logger.CtxLogger
deletionState deletionstate.DeletionState
deletionState settingsstate.ObjectDeletionState
syncStatus syncstatus.StatusUpdater
}
func (d *diffSyncer) Init(deletionState deletionstate.DeletionState) {
func (d *diffSyncer) Init(deletionState settingsstate.ObjectDeletionState) {
d.deletionState = deletionState
d.deletionState.AddObserver(d.RemoveObjects)
}

View File

@ -12,7 +12,7 @@ import (
mock_treestorage "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage/mock_treestorage"
"github.com/anytypeio/any-sync/commonspace/object/treegetter/mock_treegetter"
"github.com/anytypeio/any-sync/commonspace/peermanager/mock_peermanager"
"github.com/anytypeio/any-sync/commonspace/settings/deletionstate/mock_deletionstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate/mock_settingsstate"
"github.com/anytypeio/any-sync/commonspace/spacestorage/mock_spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto/mock_spacesyncproto"
@ -106,7 +106,7 @@ func TestDiffSyncer_Sync(t *testing.T) {
factory := spacesyncproto.ClientFactoryFunc(func(cc drpc.Conn) spacesyncproto.DRPCSpaceSyncClient {
return clientMock
})
delState := mock_deletionstate.NewMockDeletionState(ctrl)
delState := mock_settingsstate.NewMockObjectDeletionState(ctrl)
spaceId := "spaceId"
aclRootId := "aclRootId"
l := logger.NewNamed(spaceId)

View File

@ -7,13 +7,17 @@ import (
"github.com/anytypeio/any-sync/app/logger"
"github.com/anytypeio/any-sync/commonspace/object/treegetter"
"github.com/anytypeio/any-sync/commonspace/peermanager"
"github.com/anytypeio/any-sync/commonspace/settings/deletionstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
"github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/commonspace/syncstatus"
"github.com/anytypeio/any-sync/net/peer"
"github.com/anytypeio/any-sync/nodeconf"
"github.com/anytypeio/any-sync/util/periodicsync"
"go.uber.org/zap"
"golang.org/x/exp/slices"
"strings"
"sync/atomic"
"time"
)
@ -23,7 +27,7 @@ type TreeHeads struct {
}
type HeadSync interface {
Init(objectIds []string, deletionState deletionstate.DeletionState)
Init(objectIds []string, deletionState settingsstate.ObjectDeletionState)
UpdateHeads(id string, heads []string)
HandleRangeRequest(ctx context.Context, req *spacesyncproto.HeadSyncRequest) (resp *spacesyncproto.HeadSyncResponse, err error)
@ -35,19 +39,23 @@ type HeadSync interface {
}
type headSync struct {
spaceId string
periodicSync periodicsync.PeriodicSync
storage spacestorage.SpaceStorage
diff ldiff.Diff
log logger.CtxLogger
syncer DiffSyncer
spaceId string
periodicSync periodicsync.PeriodicSync
storage spacestorage.SpaceStorage
diff ldiff.Diff
log logger.CtxLogger
syncer DiffSyncer
configuration nodeconf.Configuration
spaceIsDeleted *atomic.Bool
syncPeriod int
}
func NewHeadSync(
spaceId string,
spaceIsDeleted *atomic.Bool,
syncPeriod int,
configuration nodeconf.Configuration,
storage spacestorage.SpaceStorage,
peerManager peermanager.PeerManager,
cache treegetter.TreeGetter,
@ -58,26 +66,45 @@ func NewHeadSync(
l := log.With(zap.String("spaceId", spaceId))
factory := spacesyncproto.ClientFactoryFunc(spacesyncproto.NewDRPCSpaceSyncClient)
syncer := newDiffSyncer(spaceId, diff, peerManager, cache, storage, factory, syncStatus, l)
periodicSync := periodicsync.NewPeriodicSync(syncPeriod, time.Minute, syncer.Sync, l)
sync := func(ctx context.Context) (err error) {
// for clients cancelling the sync process
if spaceIsDeleted.Load() && !configuration.IsResponsible(spaceId) {
return spacesyncproto.ErrSpaceIsDeleted
}
return syncer.Sync(ctx)
}
periodicSync := periodicsync.NewPeriodicSync(syncPeriod, time.Minute, sync, l)
return &headSync{
spaceId: spaceId,
storage: storage,
syncer: syncer,
periodicSync: periodicSync,
diff: diff,
log: log,
syncPeriod: syncPeriod,
spaceId: spaceId,
storage: storage,
syncer: syncer,
periodicSync: periodicSync,
diff: diff,
log: log,
syncPeriod: syncPeriod,
configuration: configuration,
spaceIsDeleted: spaceIsDeleted,
}
}
func (d *headSync) Init(objectIds []string, deletionState deletionstate.DeletionState) {
func (d *headSync) Init(objectIds []string, deletionState settingsstate.ObjectDeletionState) {
d.fillDiff(objectIds)
d.syncer.Init(deletionState)
d.periodicSync.Run()
}
func (d *headSync) HandleRangeRequest(ctx context.Context, req *spacesyncproto.HeadSyncRequest) (resp *spacesyncproto.HeadSyncResponse, err error) {
if d.spaceIsDeleted.Load() {
peerId, err := peer.CtxPeerId(ctx)
if err != nil {
return nil, err
}
// stop receiving all request for sync from clients
if !slices.Contains(d.configuration.NodeIds(d.spaceId), peerId) {
return nil, spacesyncproto.ErrSpaceIsDeleted
}
}
return HandleRangeRequest(ctx, d.diff, req)
}

View File

@ -6,7 +6,7 @@ import (
"github.com/anytypeio/any-sync/app/logger"
"github.com/anytypeio/any-sync/commonspace/headsync/mock_headsync"
"github.com/anytypeio/any-sync/commonspace/object/tree/treestorage/mock_treestorage"
"github.com/anytypeio/any-sync/commonspace/settings/deletionstate/mock_deletionstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate/mock_settingsstate"
"github.com/anytypeio/any-sync/commonspace/spacestorage/mock_spacestorage"
"github.com/anytypeio/any-sync/util/periodicsync/mock_periodicsync"
"github.com/golang/mock/gomock"
@ -24,7 +24,7 @@ func TestDiffService(t *testing.T) {
treeStorageMock := mock_treestorage.NewMockTreeStorage(ctrl)
diffMock := mock_ldiff.NewMockDiff(ctrl)
syncer := mock_headsync.NewMockDiffSyncer(ctrl)
delState := mock_deletionstate.NewMockDeletionState(ctrl)
delState := mock_settingsstate.NewMockObjectDeletionState(ctrl)
syncPeriod := 1
initId := "initId"

View File

@ -8,7 +8,7 @@ import (
context "context"
reflect "reflect"
deletionstate "github.com/anytypeio/any-sync/commonspace/settings/deletionstate"
settingsstate "github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
gomock "github.com/golang/mock/gomock"
)
@ -36,7 +36,7 @@ func (m *MockDiffSyncer) EXPECT() *MockDiffSyncerMockRecorder {
}
// Init mocks base method.
func (m *MockDiffSyncer) Init(arg0 deletionstate.DeletionState) {
func (m *MockDiffSyncer) Init(arg0 settingsstate.ObjectDeletionState) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Init", arg0)
}

View File

@ -255,6 +255,21 @@ func (mr *MockObjectTreeMockRecorder) Lock() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Lock", reflect.TypeOf((*MockObjectTree)(nil).Lock))
}
// PrepareChange mocks base method.
func (m *MockObjectTree) PrepareChange(arg0 objecttree.SignableChangeContent) (*treechangeproto.RawTreeChangeWithId, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PrepareChange", arg0)
ret0, _ := ret[0].(*treechangeproto.RawTreeChangeWithId)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// PrepareChange indicates an expected call of PrepareChange.
func (mr *MockObjectTreeMockRecorder) PrepareChange(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrepareChange", reflect.TypeOf((*MockObjectTree)(nil).PrepareChange), arg0)
}
// RLock mocks base method.
func (m *MockObjectTree) RLock() {
m.ctrl.T.Helper()
@ -374,3 +389,18 @@ func (mr *MockObjectTreeMockRecorder) UnmarshalledHeader() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnmarshalledHeader", reflect.TypeOf((*MockObjectTree)(nil).UnmarshalledHeader))
}
// UnpackChange mocks base method.
func (m *MockObjectTree) UnpackChange(arg0 *treechangeproto.RawTreeChangeWithId) ([]byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UnpackChange", arg0)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UnpackChange indicates an expected call of UnpackChange.
func (mr *MockObjectTreeMockRecorder) UnpackChange(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnpackChange", reflect.TypeOf((*MockObjectTree)(nil).UnpackChange), arg0)
}

View File

@ -76,6 +76,9 @@ type ObjectTree interface {
AddContent(ctx context.Context, content SignableChangeContent) (AddResult, error)
AddRawChanges(ctx context.Context, changes RawChangesPayload) (AddResult, error)
UnpackChange(raw *treechangeproto.RawTreeChangeWithId) (data []byte, err error)
PrepareChange(content SignableChangeContent) (res *treechangeproto.RawTreeChangeWithId, err error)
Delete() error
Close() error
}
@ -191,6 +194,24 @@ func (ot *objectTree) AddContent(ctx context.Context, content SignableChangeCont
return
}
func (ot *objectTree) UnpackChange(raw *treechangeproto.RawTreeChangeWithId) (data []byte, err error) {
unmarshalled, err := ot.changeBuilder.Unmarshall(raw, true)
if err != nil {
return
}
data = unmarshalled.Data
return
}
func (ot *objectTree) PrepareChange(content SignableChangeContent) (res *treechangeproto.RawTreeChangeWithId, err error) {
payload, err := ot.prepareBuilderContent(content)
if err != nil {
return
}
_, res, err = ot.changeBuilder.Build(payload)
return
}
func (ot *objectTree) prepareBuilderContent(content SignableChangeContent) (cnt BuilderContent, err error) {
ot.aclList.RLock()
defer ot.aclList.RUnlock()

View File

@ -380,6 +380,21 @@ func (mr *MockSyncTreeMockRecorder) Lock() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Lock", reflect.TypeOf((*MockSyncTree)(nil).Lock))
}
// PrepareChange mocks base method.
func (m *MockSyncTree) PrepareChange(arg0 objecttree.SignableChangeContent) (*treechangeproto.RawTreeChangeWithId, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PrepareChange", arg0)
ret0, _ := ret[0].(*treechangeproto.RawTreeChangeWithId)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// PrepareChange indicates an expected call of PrepareChange.
func (mr *MockSyncTreeMockRecorder) PrepareChange(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrepareChange", reflect.TypeOf((*MockSyncTree)(nil).PrepareChange), arg0)
}
// RLock mocks base method.
func (m *MockSyncTree) RLock() {
m.ctrl.T.Helper()
@ -526,6 +541,21 @@ func (mr *MockSyncTreeMockRecorder) UnmarshalledHeader() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnmarshalledHeader", reflect.TypeOf((*MockSyncTree)(nil).UnmarshalledHeader))
}
// UnpackChange mocks base method.
func (m *MockSyncTree) UnpackChange(arg0 *treechangeproto.RawTreeChangeWithId) ([]byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UnpackChange", arg0)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UnpackChange indicates an expected call of UnpackChange.
func (mr *MockSyncTreeMockRecorder) UnpackChange(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnpackChange", reflect.TypeOf((*MockSyncTree)(nil).UnpackChange), arg0)
}
// MockReceiveQueue is a mock of ReceiveQueue interface.
type MockReceiveQueue struct {
ctrl *gomock.Controller

View File

@ -50,6 +50,20 @@ func (mr *MockTreeGetterMockRecorder) Close(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockTreeGetter)(nil).Close), arg0)
}
// DeleteSpace mocks base method.
func (m *MockTreeGetter) DeleteSpace(arg0 context.Context, arg1 string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteSpace", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// DeleteSpace indicates an expected call of DeleteSpace.
func (mr *MockTreeGetterMockRecorder) DeleteSpace(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSpace", reflect.TypeOf((*MockTreeGetter)(nil).DeleteSpace), arg0, arg1)
}
// DeleteTree mocks base method.
func (m *MockTreeGetter) DeleteTree(arg0 context.Context, arg1, arg2 string) error {
m.ctrl.T.Helper()

View File

@ -13,4 +13,5 @@ type TreeGetter interface {
app.ComponentRunnable
GetTree(ctx context.Context, spaceId, treeId string) (objecttree.ObjectTree, error)
DeleteTree(ctx context.Context, spaceId, treeId string) error
DeleteSpace(ctx context.Context, spaceId string) error
}

View File

@ -8,7 +8,10 @@ import (
"github.com/anytypeio/any-sync/commonspace/objectsync/synchandler"
"github.com/anytypeio/any-sync/commonspace/peermanager"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/nodeconf"
"go.uber.org/zap"
"golang.org/x/exp/slices"
"sync/atomic"
"time"
)
@ -26,20 +29,26 @@ type ObjectSync interface {
type objectSync struct {
spaceId string
messagePool MessagePool
objectGetter syncobjectgetter.SyncObjectGetter
messagePool MessagePool
objectGetter syncobjectgetter.SyncObjectGetter
configuration nodeconf.Configuration
syncCtx context.Context
cancelSync context.CancelFunc
syncCtx context.Context
cancelSync context.CancelFunc
spaceIsDeleted *atomic.Bool
}
func NewObjectSync(
spaceId string,
spaceIsDeleted *atomic.Bool,
configuration nodeconf.Configuration,
peerManager peermanager.PeerManager,
objectGetter syncobjectgetter.SyncObjectGetter) ObjectSync {
syncCtx, cancel := context.WithCancel(context.Background())
os := newObjectSync(
spaceId,
spaceIsDeleted,
configuration,
objectGetter,
syncCtx,
cancel)
@ -50,25 +59,26 @@ func NewObjectSync(
func newObjectSync(
spaceId string,
spaceIsDeleted *atomic.Bool,
configuration nodeconf.Configuration,
objectGetter syncobjectgetter.SyncObjectGetter,
syncCtx context.Context,
cancel context.CancelFunc,
) *objectSync {
return &objectSync{
objectGetter: objectGetter,
spaceId: spaceId,
syncCtx: syncCtx,
cancelSync: cancel,
//actionQueue: NewDefaultActionQueue(),
objectGetter: objectGetter,
spaceId: spaceId,
syncCtx: syncCtx,
cancelSync: cancel,
spaceIsDeleted: spaceIsDeleted,
configuration: configuration,
}
}
func (s *objectSync) Init() {
//s.actionQueue.Run()
}
func (s *objectSync) Close() (err error) {
//s.actionQueue.Close()
s.cancelSync()
return
}
@ -82,6 +92,14 @@ func (s *objectSync) HandleMessage(ctx context.Context, senderId string, message
}
func (s *objectSync) handleMessage(ctx context.Context, senderId string, msg *spacesyncproto.ObjectSyncMessage) (err error) {
log := log.With(zap.String("objectId", msg.ObjectId), zap.String("replyId", msg.ReplyId))
if s.spaceIsDeleted.Load() {
log = log.With(zap.Bool("isDeleted", true))
// preventing sync with other clients
if !slices.Contains(s.configuration.NodeIds(s.spaceId), senderId) {
return spacesyncproto.ErrSpaceIsDeleted
}
}
log.With(zap.String("objectId", msg.ObjectId), zap.String("replyId", msg.ReplyId)).DebugCtx(ctx, "handling message")
obj, err := s.objectGetter.GetObject(ctx, msg.ObjectId)
if err != nil {

View File

@ -3,7 +3,7 @@ package settings
import (
"context"
"github.com/anytypeio/any-sync/commonspace/object/treegetter"
"github.com/anytypeio/any-sync/commonspace/settings/deletionstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
"github.com/anytypeio/any-sync/commonspace/spacestorage"
"go.uber.org/zap"
)
@ -14,11 +14,11 @@ type Deleter interface {
type deleter struct {
st spacestorage.SpaceStorage
state deletionstate.DeletionState
state settingsstate.ObjectDeletionState
getter treegetter.TreeGetter
}
func newDeleter(st spacestorage.SpaceStorage, state deletionstate.DeletionState, getter treegetter.TreeGetter) Deleter {
func newDeleter(st spacestorage.SpaceStorage, state settingsstate.ObjectDeletionState, getter treegetter.TreeGetter) Deleter {
return &deleter{st, state, getter}
}

View File

@ -3,7 +3,7 @@ package settings
import (
"fmt"
"github.com/anytypeio/any-sync/commonspace/object/treegetter/mock_treegetter"
"github.com/anytypeio/any-sync/commonspace/settings/deletionstate/mock_deletionstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate/mock_settingsstate"
"github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacestorage/mock_spacestorage"
"github.com/golang/mock/gomock"
@ -14,7 +14,7 @@ func TestDeleter_Delete(t *testing.T) {
ctrl := gomock.NewController(t)
treeGetter := mock_treegetter.NewMockTreeGetter(ctrl)
st := mock_spacestorage.NewMockSpaceStorage(ctrl)
delState := mock_deletionstate.NewMockDeletionState(ctrl)
delState := mock_settingsstate.NewMockObjectDeletionState(ctrl)
deleter := newDeleter(st, delState, treeGetter)

View File

@ -0,0 +1,73 @@
package settings
import (
"context"
"github.com/anytypeio/any-sync/commonspace/object/treegetter"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
"github.com/anytypeio/any-sync/util/slice"
"go.uber.org/zap"
)
type SpaceIdsProvider interface {
AllIds() []string
}
type DeletionManager interface {
UpdateState(ctx context.Context, state *settingsstate.State) (err error)
}
func newDeletionManager(
spaceId string,
settingsId string,
isResponsible bool,
treeGetter treegetter.TreeGetter,
deletionState settingsstate.ObjectDeletionState,
provider SpaceIdsProvider,
onSpaceDelete func()) DeletionManager {
return &deletionManager{
treeGetter: treeGetter,
isResponsible: isResponsible,
spaceId: spaceId,
settingsId: settingsId,
deletionState: deletionState,
provider: provider,
onSpaceDelete: onSpaceDelete,
}
}
type deletionManager struct {
deletionState settingsstate.ObjectDeletionState
provider SpaceIdsProvider
treeGetter treegetter.TreeGetter
spaceId string
settingsId string
isResponsible bool
onSpaceDelete func()
}
func (d *deletionManager) UpdateState(ctx context.Context, state *settingsstate.State) error {
log := log.With(zap.String("spaceId", d.spaceId))
err := d.deletionState.Add(state.DeletedIds)
if err != nil {
log.Debug("failed to add deleted ids to deletion state")
}
if state.DeleterId == "" {
return nil
}
log.Debug("deleting space")
err = d.treeGetter.DeleteSpace(ctx, d.spaceId)
if err != nil {
log.Debug("failed to notify on space deletion", zap.Error(err))
}
if d.isResponsible {
allIds := slice.DiscardFromSlice(d.provider.AllIds(), func(id string) bool {
return id == d.settingsId
})
err := d.deletionState.Add(allIds)
if err != nil {
log.Debug("failed to add all ids to deletion state")
}
}
d.onSpaceDelete()
return nil
}

View File

@ -0,0 +1,81 @@
package settings
import (
"context"
"github.com/anytypeio/any-sync/commonspace/object/treegetter/mock_treegetter"
"github.com/anytypeio/any-sync/commonspace/settings/mock_settings"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate/mock_settingsstate"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"testing"
)
func TestDeletionManager_UpdateState_NotResponsible(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
spaceId := "spaceId"
settingsId := "settingsId"
state := &settingsstate.State{
DeletedIds: []string{"id"},
DeleterId: "deleterId",
}
deleted := false
onDeleted := func() {
deleted = true
}
delState := mock_settingsstate.NewMockObjectDeletionState(ctrl)
treeGetter := mock_treegetter.NewMockTreeGetter(ctrl)
delState.EXPECT().Add(state.DeletedIds).Return(nil)
treeGetter.EXPECT().DeleteSpace(ctx, spaceId).Return(nil)
delManager := newDeletionManager(spaceId,
settingsId,
false,
treeGetter,
delState,
nil,
onDeleted)
err := delManager.UpdateState(ctx, state)
require.NoError(t, err)
require.True(t, deleted)
}
func TestDeletionManager_UpdateState_Responsible(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.Background()
spaceId := "spaceId"
settingsId := "settingsId"
state := &settingsstate.State{
DeletedIds: []string{"id"},
DeleterId: "deleterId",
}
deleted := false
onDeleted := func() {
deleted = true
}
delState := mock_settingsstate.NewMockObjectDeletionState(ctrl)
treeGetter := mock_treegetter.NewMockTreeGetter(ctrl)
provider := mock_settings.NewMockSpaceIdsProvider(ctrl)
delState.EXPECT().Add(state.DeletedIds).Return(nil)
treeGetter.EXPECT().DeleteSpace(ctx, spaceId).Return(nil)
provider.EXPECT().AllIds().Return([]string{"id", "otherId", settingsId})
delState.EXPECT().Add([]string{"id", "otherId"}).Return(nil)
delManager := newDeletionManager(spaceId,
settingsId,
true,
treeGetter,
delState,
provider,
onDeleted)
err := delManager.UpdateState(ctx, state)
require.NoError(t, err)
require.True(t, deleted)
}

View File

@ -1,136 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/anytypeio/any-sync/commonspace/settings/deletionstate (interfaces: DeletionState)
// Package mock_deletionstate is a generated GoMock package.
package mock_deletionstate
import (
reflect "reflect"
deletionstate "github.com/anytypeio/any-sync/commonspace/settings/deletionstate"
gomock "github.com/golang/mock/gomock"
)
// MockDeletionState is a mock of DeletionState interface.
type MockDeletionState struct {
ctrl *gomock.Controller
recorder *MockDeletionStateMockRecorder
}
// MockDeletionStateMockRecorder is the mock recorder for MockDeletionState.
type MockDeletionStateMockRecorder struct {
mock *MockDeletionState
}
// NewMockDeletionState creates a new mock instance.
func NewMockDeletionState(ctrl *gomock.Controller) *MockDeletionState {
mock := &MockDeletionState{ctrl: ctrl}
mock.recorder = &MockDeletionStateMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDeletionState) EXPECT() *MockDeletionStateMockRecorder {
return m.recorder
}
// Add mocks base method.
func (m *MockDeletionState) Add(arg0 []string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Add", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Add indicates an expected call of Add.
func (mr *MockDeletionStateMockRecorder) Add(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockDeletionState)(nil).Add), arg0)
}
// AddObserver mocks base method.
func (m *MockDeletionState) AddObserver(arg0 deletionstate.StateUpdateObserver) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "AddObserver", arg0)
}
// AddObserver indicates an expected call of AddObserver.
func (mr *MockDeletionStateMockRecorder) AddObserver(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddObserver", reflect.TypeOf((*MockDeletionState)(nil).AddObserver), arg0)
}
// CreateDeleteChange mocks base method.
func (m *MockDeletionState) CreateDeleteChange(arg0 string, arg1 bool) ([]byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CreateDeleteChange", arg0, arg1)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// CreateDeleteChange indicates an expected call of CreateDeleteChange.
func (mr *MockDeletionStateMockRecorder) CreateDeleteChange(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateDeleteChange", reflect.TypeOf((*MockDeletionState)(nil).CreateDeleteChange), arg0, arg1)
}
// Delete mocks base method.
func (m *MockDeletionState) Delete(arg0 string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delete", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Delete indicates an expected call of Delete.
func (mr *MockDeletionStateMockRecorder) Delete(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockDeletionState)(nil).Delete), arg0)
}
// Exists mocks base method.
func (m *MockDeletionState) Exists(arg0 string) bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Exists", arg0)
ret0, _ := ret[0].(bool)
return ret0
}
// Exists indicates an expected call of Exists.
func (mr *MockDeletionStateMockRecorder) Exists(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exists", reflect.TypeOf((*MockDeletionState)(nil).Exists), arg0)
}
// FilterJoin mocks base method.
func (m *MockDeletionState) FilterJoin(arg0 ...[]string) []string {
m.ctrl.T.Helper()
varargs := []interface{}{}
for _, a := range arg0 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "FilterJoin", varargs...)
ret0, _ := ret[0].([]string)
return ret0
}
// FilterJoin indicates an expected call of FilterJoin.
func (mr *MockDeletionStateMockRecorder) FilterJoin(arg0 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FilterJoin", reflect.TypeOf((*MockDeletionState)(nil).FilterJoin), arg0...)
}
// GetQueued mocks base method.
func (m *MockDeletionState) GetQueued() []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetQueued")
ret0, _ := ret[0].([]string)
return ret0
}
// GetQueued indicates an expected call of GetQueued.
func (mr *MockDeletionStateMockRecorder) GetQueued() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetQueued", reflect.TypeOf((*MockDeletionState)(nil).GetQueued))
}

View File

@ -1,58 +0,0 @@
package settings
import (
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/gogo/protobuf/proto"
)
type DeletedIdsProvider interface {
ProvideIds(tr objecttree.ObjectTree, startId string) (ids []string, lastId string, err error)
}
type provider struct{}
func (p *provider) processChange(change *objecttree.Change, rootId, startId string, ids []string) []string {
// ignoring root change which has empty model or startId change
if change.Model == nil || (change.Id == startId && startId != "") {
return ids
}
deleteChange := change.Model.(*spacesyncproto.SettingsData)
// getting data from snapshot if we start from it
if change.Id == rootId {
ids = deleteChange.Snapshot.DeletedIds
return ids
}
// otherwise getting data from content
for _, cnt := range deleteChange.Content {
if cnt.GetObjectDelete() != nil {
ids = append(ids, cnt.GetObjectDelete().GetId())
}
}
return ids
}
func (p *provider) ProvideIds(tr objecttree.ObjectTree, startId string) (ids []string, lastId string, err error) {
rootId := tr.Root().Id
process := func(change *objecttree.Change) bool {
lastId = change.Id
ids = p.processChange(change, rootId, startId, ids)
return true
}
convert := func(decrypted []byte) (res any, err error) {
deleteChange := &spacesyncproto.SettingsData{}
err = proto.Unmarshal(decrypted, deleteChange)
if err != nil {
return nil, err
}
return deleteChange, nil
}
if startId == "" {
startId = rootId
}
err = tr.IterateFrom(startId, convert, process)
return
}

View File

@ -1,93 +0,0 @@
package settings
import (
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree/mock_objecttree"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"testing"
)
func TestProvider_ProcessChange(t *testing.T) {
//ctrl := gomock.NewController(t)
//objTree := mock_tree.NewMockObjectTree(ctrl)
prov := &provider{}
//defer ctrl.Finish()
t.Run("empty model", func(t *testing.T) {
ch := &objecttree.Change{}
startId := "startId"
rootId := "rootId"
ids := []string{startId}
otherIds := prov.processChange(ch, rootId, startId, ids)
require.Equal(t, []string{startId}, otherIds)
})
t.Run("changeId is equal to startId", func(t *testing.T) {
ch := &objecttree.Change{}
ch.Model = &spacesyncproto.SettingsData{}
ch.Id = "startId"
startId := "startId"
rootId := "rootId"
ids := []string{startId}
otherIds := prov.processChange(ch, rootId, startId, ids)
require.Equal(t, []string{startId}, otherIds)
})
t.Run("changeId is equal to rootId, startId is empty", func(t *testing.T) {
ch := &objecttree.Change{}
ch.Model = &spacesyncproto.SettingsData{
Snapshot: &spacesyncproto.SpaceSettingsSnapshot{
DeletedIds: []string{"id1", "id2"},
},
}
ch.Id = "rootId"
startId := ""
rootId := "rootId"
otherIds := prov.processChange(ch, rootId, startId, nil)
require.Equal(t, []string{"id1", "id2"}, otherIds)
})
t.Run("changeId is equal to rootId, startId is empty", func(t *testing.T) {
ch := &objecttree.Change{}
ch.Model = &spacesyncproto.SettingsData{
Content: []*spacesyncproto.SpaceSettingsContent{
{Value: &spacesyncproto.SpaceSettingsContent_ObjectDelete{
ObjectDelete: &spacesyncproto.ObjectDelete{Id: "id1"},
}},
},
}
ch.Id = "someId"
startId := "startId"
rootId := "rootId"
otherIds := prov.processChange(ch, rootId, startId, nil)
require.Equal(t, []string{"id1"}, otherIds)
})
}
func TestProvider_ProvideIds(t *testing.T) {
ctrl := gomock.NewController(t)
objTree := mock_objecttree.NewMockObjectTree(ctrl)
prov := &provider{}
defer ctrl.Finish()
t.Run("startId is empty", func(t *testing.T) {
ch := &objecttree.Change{Id: "rootId"}
objTree.EXPECT().Root().Return(ch)
objTree.EXPECT().IterateFrom("rootId", gomock.Any(), gomock.Any()).Return(nil)
_, _, err := prov.ProvideIds(objTree, "")
require.NoError(t, err)
})
t.Run("startId is not empty", func(t *testing.T) {
ch := &objecttree.Change{Id: "rootId"}
objTree.EXPECT().Root().Return(ch)
objTree.EXPECT().IterateFrom("startId", gomock.Any(), gomock.Any()).Return(nil)
_, _, err := prov.ProvideIds(objTree, "startId")
require.NoError(t, err)
})
}

View File

@ -1,53 +1,52 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/anytypeio/any-sync/commonspace/settings (interfaces: DeletedIdsProvider,Deleter)
// Source: github.com/anytypeio/any-sync/commonspace/settings (interfaces: DeletionManager,Deleter,SpaceIdsProvider)
// Package mock_settings is a generated GoMock package.
package mock_settings
import (
context "context"
reflect "reflect"
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
settingsstate "github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
gomock "github.com/golang/mock/gomock"
)
// MockDeletedIdsProvider is a mock of DeletedIdsProvider interface.
type MockDeletedIdsProvider struct {
// MockDeletionManager is a mock of DeletionManager interface.
type MockDeletionManager struct {
ctrl *gomock.Controller
recorder *MockDeletedIdsProviderMockRecorder
recorder *MockDeletionManagerMockRecorder
}
// MockDeletedIdsProviderMockRecorder is the mock recorder for MockDeletedIdsProvider.
type MockDeletedIdsProviderMockRecorder struct {
mock *MockDeletedIdsProvider
// MockDeletionManagerMockRecorder is the mock recorder for MockDeletionManager.
type MockDeletionManagerMockRecorder struct {
mock *MockDeletionManager
}
// NewMockDeletedIdsProvider creates a new mock instance.
func NewMockDeletedIdsProvider(ctrl *gomock.Controller) *MockDeletedIdsProvider {
mock := &MockDeletedIdsProvider{ctrl: ctrl}
mock.recorder = &MockDeletedIdsProviderMockRecorder{mock}
// NewMockDeletionManager creates a new mock instance.
func NewMockDeletionManager(ctrl *gomock.Controller) *MockDeletionManager {
mock := &MockDeletionManager{ctrl: ctrl}
mock.recorder = &MockDeletionManagerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDeletedIdsProvider) EXPECT() *MockDeletedIdsProviderMockRecorder {
func (m *MockDeletionManager) EXPECT() *MockDeletionManagerMockRecorder {
return m.recorder
}
// ProvideIds mocks base method.
func (m *MockDeletedIdsProvider) ProvideIds(arg0 objecttree.ObjectTree, arg1 string) ([]string, string, error) {
// UpdateState mocks base method.
func (m *MockDeletionManager) UpdateState(arg0 context.Context, arg1 *settingsstate.State) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ProvideIds", arg0, arg1)
ret0, _ := ret[0].([]string)
ret1, _ := ret[1].(string)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
ret := m.ctrl.Call(m, "UpdateState", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// ProvideIds indicates an expected call of ProvideIds.
func (mr *MockDeletedIdsProviderMockRecorder) ProvideIds(arg0, arg1 interface{}) *gomock.Call {
// UpdateState indicates an expected call of UpdateState.
func (mr *MockDeletionManagerMockRecorder) UpdateState(arg0, arg1 interface{}) *gomock.Call {
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, "UpdateState", reflect.TypeOf((*MockDeletionManager)(nil).UpdateState), arg0, arg1)
}
// MockDeleter is a mock of Deleter interface.
@ -84,3 +83,40 @@ func (mr *MockDeleterMockRecorder) Delete() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockDeleter)(nil).Delete))
}
// MockSpaceIdsProvider is a mock of SpaceIdsProvider interface.
type MockSpaceIdsProvider struct {
ctrl *gomock.Controller
recorder *MockSpaceIdsProviderMockRecorder
}
// MockSpaceIdsProviderMockRecorder is the mock recorder for MockSpaceIdsProvider.
type MockSpaceIdsProviderMockRecorder struct {
mock *MockSpaceIdsProvider
}
// NewMockSpaceIdsProvider creates a new mock instance.
func NewMockSpaceIdsProvider(ctrl *gomock.Controller) *MockSpaceIdsProvider {
mock := &MockSpaceIdsProvider{ctrl: ctrl}
mock.recorder = &MockSpaceIdsProviderMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockSpaceIdsProvider) EXPECT() *MockSpaceIdsProviderMockRecorder {
return m.recorder
}
// AllIds mocks base method.
func (m *MockSpaceIdsProvider) AllIds() []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AllIds")
ret0, _ := ret[0].([]string)
return ret0
}
// AllIds indicates an expected call of AllIds.
func (mr *MockSpaceIdsProviderMockRecorder) AllIds() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllIds", reflect.TypeOf((*MockSpaceIdsProvider)(nil).AllIds))
}

View File

@ -1,18 +1,24 @@
//go:generate mockgen -destination mock_settings/mock_settings.go github.com/anytypeio/any-sync/commonspace/settings DeletedIdsProvider,Deleter
//go:generate mockgen -destination mock_settings/mock_settings.go github.com/anytypeio/any-sync/commonspace/settings DeletionManager,Deleter,SpaceIdsProvider
package settings
import (
"context"
"errors"
"fmt"
"github.com/anytypeio/any-sync/accountservice"
"github.com/anytypeio/any-sync/app/logger"
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/object/tree/synctree"
"github.com/anytypeio/any-sync/commonspace/object/tree/synctree/updatelistener"
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
"github.com/anytypeio/any-sync/commonspace/object/treegetter"
"github.com/anytypeio/any-sync/commonspace/settings/deletionstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
spacestorage "github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/nodeconf"
"github.com/gogo/protobuf/proto"
"go.uber.org/zap"
"golang.org/x/exp/slices"
)
var log = logger.NewNamed("common.commonspace.settings")
@ -21,12 +27,15 @@ type SettingsObject interface {
synctree.SyncTree
Init(ctx context.Context) (err error)
DeleteObject(id string) (err error)
DeleteSpace(ctx context.Context, raw *treechangeproto.RawTreeChangeWithId) (err error)
SpaceDeleteRawChange() (raw *treechangeproto.RawTreeChangeWithId, err error)
}
var (
ErrDeleteSelf = errors.New("cannot delete self")
ErrAlreadyDeleted = errors.New("the object is already deleted")
ErrObjDoesNotExist = errors.New("the object does not exist")
ErrCantDeleteSpace = errors.New("not able to delete space")
)
type BuildTreeFunc func(ctx context.Context, id string, listener updatelistener.UpdateListener) (t synctree.SyncTree, err error)
@ -36,10 +45,15 @@ type Deps struct {
Account accountservice.Service
TreeGetter treegetter.TreeGetter
Store spacestorage.SpaceStorage
DeletionState deletionstate.DeletionState
Configuration nodeconf.Configuration
DeletionState settingsstate.ObjectDeletionState
Provider SpaceIdsProvider
OnSpaceDelete func()
// testing dependencies
prov DeletedIdsProvider
del Deleter
builder settingsstate.StateBuilder
del Deleter
delManager DeletionManager
changeFactory settingsstate.ChangeFactory
}
type settingsObject struct {
@ -48,21 +62,50 @@ type settingsObject struct {
spaceId string
treeGetter treegetter.TreeGetter
store spacestorage.SpaceStorage
prov DeletedIdsProvider
builder settingsstate.StateBuilder
buildFunc BuildTreeFunc
loop *deleteLoop
deletionState deletionstate.DeletionState
lastChangeId string
state *settingsstate.State
deletionState settingsstate.ObjectDeletionState
deletionManager DeletionManager
changeFactory settingsstate.ChangeFactory
}
func NewSettingsObject(deps Deps, spaceId string) (obj SettingsObject) {
var deleter Deleter
var (
deleter Deleter
deletionManager DeletionManager
builder settingsstate.StateBuilder
changeFactory settingsstate.ChangeFactory
)
if deps.del == nil {
deleter = newDeleter(deps.Store, deps.DeletionState, deps.TreeGetter)
} else {
deleter = deps.del
}
if deps.delManager == nil {
deletionManager = newDeletionManager(
spaceId,
deps.Store.SpaceSettingsId(),
deps.Configuration.IsResponsible(spaceId),
deps.TreeGetter,
deps.DeletionState,
deps.Provider,
deps.OnSpaceDelete)
} else {
deletionManager = deps.delManager
}
if deps.builder == nil {
builder = settingsstate.NewStateBuilder()
} else {
builder = deps.builder
}
if deps.changeFactory == nil {
changeFactory = settingsstate.NewChangeFactory()
} else {
changeFactory = deps.changeFactory
}
loop := newDeleteLoop(func() {
deleter.Delete()
@ -72,48 +115,44 @@ func NewSettingsObject(deps Deps, spaceId string) (obj SettingsObject) {
})
s := &settingsObject{
loop: loop,
spaceId: spaceId,
account: deps.Account,
deletionState: deps.DeletionState,
treeGetter: deps.TreeGetter,
store: deps.Store,
buildFunc: deps.BuildFunc,
loop: loop,
spaceId: spaceId,
account: deps.Account,
deletionState: deps.DeletionState,
treeGetter: deps.TreeGetter,
store: deps.Store,
buildFunc: deps.BuildFunc,
builder: builder,
deletionManager: deletionManager,
changeFactory: changeFactory,
}
// this is needed mainly for testing
if deps.prov == nil {
s.prov = &provider{}
} else {
s.prov = deps.prov
}
obj = s
return
}
func (s *settingsObject) updateIds(tr objecttree.ObjectTree, lastChangeId string) {
s.lastChangeId = lastChangeId
ids, lastId, err := s.prov.ProvideIds(tr, s.lastChangeId)
func (s *settingsObject) updateIds(tr objecttree.ObjectTree) {
var err error
s.state, err = s.builder.Build(tr, s.state)
if err != nil {
log.With(zap.Strings("ids", ids), zap.Error(err)).Error("failed to update state")
log.Error("failed to build state", zap.Error(err))
return
}
s.lastChangeId = lastId
if err = s.deletionState.Add(ids); err != nil {
log.With(zap.Strings("ids", ids), zap.Error(err)).Error("failed to queue ids to delete")
log.Debug("updating object state", zap.String("deleted by", s.state.DeleterId))
if err = s.deletionManager.UpdateState(context.Background(), s.state); err != nil {
log.Error("failed to update state", zap.Error(err))
}
}
// Update is called as part of UpdateListener interface
func (s *settingsObject) Update(tr objecttree.ObjectTree) {
s.updateIds(tr, s.lastChangeId)
s.updateIds(tr)
}
// 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 *settingsObject) Rebuild(tr objecttree.ObjectTree) {
// 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.state = nil
s.updateIds(tr)
}
func (s *settingsObject) Init(ctx context.Context) (err error) {
@ -133,6 +172,45 @@ func (s *settingsObject) Close() error {
return s.SyncTree.Close()
}
func (s *settingsObject) DeleteSpace(ctx context.Context, raw *treechangeproto.RawTreeChangeWithId) (err error) {
s.Lock()
defer s.Unlock()
defer func() {
log.Debug("finished adding delete change", zap.Error(err))
}()
err = s.verifyDeleteSpace(raw)
if err != nil {
return
}
res, err := s.AddRawChanges(ctx, objecttree.RawChangesPayload{
NewHeads: []string{raw.Id},
RawChanges: []*treechangeproto.RawTreeChangeWithId{raw},
})
if err != nil {
return
}
if !slices.Contains(res.Heads, raw.Id) {
err = ErrCantDeleteSpace
return
}
return
}
func (s *settingsObject) SpaceDeleteRawChange() (raw *treechangeproto.RawTreeChangeWithId, err error) {
accountData := s.account.Account()
data, err := s.changeFactory.CreateSpaceDeleteChange(accountData.PeerId, s.state, false)
if err != nil {
return
}
return s.PrepareChange(objecttree.SignableChangeContent{
Data: data,
Key: accountData.SignKey,
Identity: accountData.Identity,
IsSnapshot: false,
IsEncrypted: false,
})
}
func (s *settingsObject) DeleteObject(id string) (err error) {
s.Lock()
defer s.Unlock()
@ -151,14 +229,36 @@ func (s *settingsObject) DeleteObject(id string) (err error) {
}
// TODO: add snapshot logic
res, err := s.deletionState.CreateDeleteChange(id, false)
res, err := s.changeFactory.CreateObjectDeleteChange(id, s.state, false)
if err != nil {
return
}
return s.addContent(res)
}
func (s *settingsObject) verifyDeleteSpace(raw *treechangeproto.RawTreeChangeWithId) (err error) {
data, err := s.UnpackChange(raw)
if err != nil {
return
}
content := &spacesyncproto.SettingsData{}
err = proto.Unmarshal(data, content)
if err != nil {
return
}
if len(content.GetContent()) != 1 ||
content.GetContent()[0].GetSpaceDelete() == nil ||
content.GetContent()[0].GetSpaceDelete().GetDeleterPeerId() == "" {
return fmt.Errorf("incorrect delete change payload")
}
return
}
func (s *settingsObject) addContent(data []byte) (err error) {
accountData := s.account.Account()
_, err = s.AddContent(context.Background(), objecttree.SignableChangeContent{
Data: res,
Data: data,
Key: accountData.SignKey,
Identity: accountData.Identity,
IsSnapshot: false,

View File

@ -8,9 +8,11 @@ import (
"github.com/anytypeio/any-sync/commonspace/object/tree/synctree"
"github.com/anytypeio/any-sync/commonspace/object/tree/synctree/mock_synctree"
"github.com/anytypeio/any-sync/commonspace/object/tree/synctree/updatelistener"
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
"github.com/anytypeio/any-sync/commonspace/object/treegetter/mock_treegetter"
"github.com/anytypeio/any-sync/commonspace/settings/deletionstate/mock_deletionstate"
"github.com/anytypeio/any-sync/commonspace/settings/mock_settings"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate/mock_settingsstate"
"github.com/anytypeio/any-sync/commonspace/spacestorage/mock_spacestorage"
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
"github.com/golang/mock/gomock"
@ -40,17 +42,19 @@ func (t *testSyncTreeMock) Unlock() {
}
type settingsFixture struct {
spaceId string
docId string
doc *settingsObject
ctrl *gomock.Controller
treeGetter *mock_treegetter.MockTreeGetter
spaceStorage *mock_spacestorage.MockSpaceStorage
provider *mock_settings.MockDeletedIdsProvider
deleter *mock_settings.MockDeleter
syncTree *mock_synctree.MockSyncTree
delState *mock_deletionstate.MockDeletionState
account *mock_accountservice.MockService
spaceId string
docId string
doc *settingsObject
ctrl *gomock.Controller
treeGetter *mock_treegetter.MockTreeGetter
spaceStorage *mock_spacestorage.MockSpaceStorage
stateBuilder *mock_settingsstate.MockStateBuilder
deletionManager *mock_settings.MockDeletionManager
changeFactory *mock_settingsstate.MockChangeFactory
deleter *mock_settings.MockDeleter
syncTree *mock_synctree.MockSyncTree
delState *mock_settingsstate.MockObjectDeletionState
account *mock_accountservice.MockService
}
func newSettingsFixture(t *testing.T) *settingsFixture {
@ -61,8 +65,10 @@ func newSettingsFixture(t *testing.T) *settingsFixture {
acc := mock_accountservice.NewMockService(ctrl)
treeGetter := mock_treegetter.NewMockTreeGetter(ctrl)
st := mock_spacestorage.NewMockSpaceStorage(ctrl)
delState := mock_deletionstate.NewMockDeletionState(ctrl)
prov := mock_settings.NewMockDeletedIdsProvider(ctrl)
delState := mock_settingsstate.NewMockObjectDeletionState(ctrl)
delManager := mock_settings.NewMockDeletionManager(ctrl)
stateBuilder := mock_settingsstate.NewMockStateBuilder(ctrl)
changeFactory := mock_settingsstate.NewMockChangeFactory(ctrl)
syncTree := mock_synctree.NewMockSyncTree(ctrl)
del := mock_settings.NewMockDeleter(ctrl)
@ -79,22 +85,26 @@ func newSettingsFixture(t *testing.T) *settingsFixture {
TreeGetter: treeGetter,
Store: st,
DeletionState: delState,
prov: prov,
delManager: delManager,
changeFactory: changeFactory,
builder: stateBuilder,
del: del,
}
doc := NewSettingsObject(deps, spaceId).(*settingsObject)
return &settingsFixture{
spaceId: spaceId,
docId: objectId,
doc: doc,
ctrl: ctrl,
treeGetter: treeGetter,
spaceStorage: st,
provider: prov,
deleter: del,
syncTree: syncTree,
account: acc,
delState: delState,
spaceId: spaceId,
docId: objectId,
doc: doc,
ctrl: ctrl,
treeGetter: treeGetter,
spaceStorage: st,
stateBuilder: stateBuilder,
changeFactory: changeFactory,
deletionManager: delManager,
deleter: del,
syncTree: syncTree,
account: acc,
delState: delState,
}
}
@ -133,7 +143,8 @@ func TestSettingsObject_DeleteObject(t *testing.T) {
fx.delState.EXPECT().Exists(delId).Return(false)
fx.spaceStorage.EXPECT().TreeStorage(delId).Return(nil, nil)
res := []byte("settingsData")
fx.delState.EXPECT().CreateDeleteChange(delId, false).Return(res, nil)
fx.doc.state = &settingsstate.State{LastIteratedId: "someId"}
fx.changeFactory.EXPECT().CreateObjectDeleteChange(delId, fx.doc.state, false).Return(res, nil)
accountData := &accountdata.AccountData{
Identity: []byte("id"),
@ -150,14 +161,10 @@ func TestSettingsObject_DeleteObject(t *testing.T) {
IsEncrypted: false,
}).Return(objecttree.AddResult{}, nil)
lastChangeId := "someId"
retIds := []string{"id1", "id2"}
fx.doc.lastChangeId = lastChangeId
fx.provider.EXPECT().ProvideIds(gomock.Not(nil), lastChangeId).Return(retIds, retIds[len(retIds)-1], nil)
fx.delState.EXPECT().Add(retIds).Return(nil)
fx.stateBuilder.EXPECT().Build(fx.doc, fx.doc.state).Return(fx.doc.state, nil)
fx.deletionManager.EXPECT().UpdateState(gomock.Any(), fx.doc.state).Return(nil)
err = fx.doc.DeleteObject(delId)
require.NoError(t, err)
require.Equal(t, retIds[len(retIds)-1], fx.doc.lastChangeId)
fx.syncTree.EXPECT().Close().Return(nil)
err = fx.doc.Close()
@ -175,16 +182,97 @@ func TestSettingsObject_Rebuild(t *testing.T) {
require.NoError(t, err)
time.Sleep(100 * time.Millisecond)
lastChangeId := "someId"
retIds := []string{"id1", "id2"}
fx.doc.lastChangeId = lastChangeId
fx.provider.EXPECT().ProvideIds(gomock.Not(nil), "").Return(retIds, retIds[len(retIds)-1], nil)
fx.delState.EXPECT().Add(retIds).Return(nil)
newSt := &settingsstate.State{}
fx.doc.state = &settingsstate.State{}
fx.stateBuilder.EXPECT().Build(fx.doc, nil).Return(newSt, nil)
fx.deletionManager.EXPECT().UpdateState(gomock.Any(), newSt).Return(nil)
fx.doc.Rebuild(fx.doc)
require.Equal(t, retIds[len(retIds)-1], fx.doc.lastChangeId)
}
fx.syncTree.EXPECT().Close().Return(nil)
err = fx.doc.Close()
func TestSettingsObject_Update(t *testing.T) {
fx := newSettingsFixture(t)
defer fx.stop()
fx.spaceStorage.EXPECT().SpaceSettingsId().Return(fx.docId)
fx.deleter.EXPECT().Delete()
err := fx.doc.Init(context.Background())
require.NoError(t, err)
time.Sleep(100 * time.Millisecond)
fx.doc.state = &settingsstate.State{}
fx.stateBuilder.EXPECT().Build(fx.doc, fx.doc.state).Return(fx.doc.state, nil)
fx.deletionManager.EXPECT().UpdateState(gomock.Any(), fx.doc.state).Return(nil)
fx.doc.Update(fx.doc)
}
func TestSettingsObject_DeleteSpace(t *testing.T) {
fx := newSettingsFixture(t)
defer fx.stop()
fx.spaceStorage.EXPECT().SpaceSettingsId().Return(fx.docId)
fx.deleter.EXPECT().Delete()
err := fx.doc.Init(context.Background())
require.NoError(t, err)
time.Sleep(100 * time.Millisecond)
deleterId := "delId"
rawCh := &treechangeproto.RawTreeChangeWithId{
RawChange: []byte{1},
Id: "id",
}
changeFactory := settingsstate.NewChangeFactory()
delChange, _ := changeFactory.CreateSpaceDeleteChange(deleterId, &settingsstate.State{}, false)
fx.syncTree.EXPECT().UnpackChange(rawCh).Return(delChange, nil)
fx.syncTree.EXPECT().AddRawChanges(gomock.Any(), objecttree.RawChangesPayload{
NewHeads: []string{rawCh.Id},
RawChanges: []*treechangeproto.RawTreeChangeWithId{rawCh},
}).Return(objecttree.AddResult{
Heads: []string{rawCh.Id},
}, nil)
err = fx.doc.DeleteSpace(context.Background(), rawCh)
require.NoError(t, err)
}
func TestSettingsObject_DeleteSpaceIncorrectChange(t *testing.T) {
fx := newSettingsFixture(t)
defer fx.stop()
fx.spaceStorage.EXPECT().SpaceSettingsId().Return(fx.docId)
fx.deleter.EXPECT().Delete()
err := fx.doc.Init(context.Background())
require.NoError(t, err)
time.Sleep(100 * time.Millisecond)
t.Run("incorrect change type", func(t *testing.T) {
rawCh := &treechangeproto.RawTreeChangeWithId{
RawChange: []byte{1},
Id: "id",
}
changeFactory := settingsstate.NewChangeFactory()
delChange, _ := changeFactory.CreateObjectDeleteChange("otherId", &settingsstate.State{}, false)
fx.syncTree.EXPECT().UnpackChange(rawCh).Return(delChange, nil)
err = fx.doc.DeleteSpace(context.Background(), rawCh)
require.NotNil(t, err)
})
t.Run("empty peer", func(t *testing.T) {
rawCh := &treechangeproto.RawTreeChangeWithId{
RawChange: []byte{1},
Id: "id",
}
changeFactory := settingsstate.NewChangeFactory()
delChange, _ := changeFactory.CreateSpaceDeleteChange("", &settingsstate.State{}, false)
fx.syncTree.EXPECT().UnpackChange(rawCh).Return(delChange, nil)
err = fx.doc.DeleteSpace(context.Background(), rawCh)
require.NotNil(t, err)
})
}

View File

@ -0,0 +1,47 @@
package settingsstate
import (
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
)
type ChangeFactory interface {
CreateObjectDeleteChange(id string, state *State, isSnapshot bool) (res []byte, err error)
CreateSpaceDeleteChange(peerId string, state *State, isSnapshot bool) (res []byte, err error)
}
func NewChangeFactory() ChangeFactory {
return &changeFactory{}
}
type changeFactory struct {
}
func (c *changeFactory) CreateObjectDeleteChange(id string, state *State, isSnapshot bool) (res []byte, err error) {
content := &spacesyncproto.SpaceSettingsContent_ObjectDelete{
ObjectDelete: &spacesyncproto.ObjectDelete{Id: id},
}
change := &spacesyncproto.SettingsData{
Content: []*spacesyncproto.SpaceSettingsContent{
{Value: content},
},
Snapshot: nil,
}
// TODO: add snapshot logic
res, err = change.Marshal()
return
}
func (c *changeFactory) CreateSpaceDeleteChange(peerId string, state *State, isSnapshot bool) (res []byte, err error) {
content := &spacesyncproto.SpaceSettingsContent_SpaceDelete{
SpaceDelete: &spacesyncproto.SpaceDelete{DeleterPeerId: peerId},
}
change := &spacesyncproto.SettingsData{
Content: []*spacesyncproto.SpaceSettingsContent{
{Value: content},
},
Snapshot: nil,
}
// TODO: add snapshot logic
res, err = change.Marshal()
return
}

View File

@ -1,25 +1,23 @@
//go:generate mockgen -destination mock_deletionstate/mock_deletionstate.go github.com/anytypeio/any-sync/commonspace/settings/deletionstate DeletionState
package deletionstate
//go:generate mockgen -destination mock_settingsstate/mock_settingsstate.go github.com/anytypeio/any-sync/commonspace/settings/settingsstate ObjectDeletionState,StateBuilder,ChangeFactory
package settingsstate
import (
"github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"sync"
)
type StateUpdateObserver func(ids []string)
type DeletionState interface {
type ObjectDeletionState 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)
CreateDeleteChange(id string, isSnapshot bool) (res []byte, err error)
}
type deletionState struct {
type objectDeletionState struct {
sync.RWMutex
queued map[string]struct{}
deleted map[string]struct{}
@ -27,21 +25,21 @@ type deletionState struct {
storage spacestorage.SpaceStorage
}
func NewDeletionState(storage spacestorage.SpaceStorage) DeletionState {
return &deletionState{
func NewObjectDeletionState(storage spacestorage.SpaceStorage) ObjectDeletionState {
return &objectDeletionState{
queued: map[string]struct{}{},
deleted: map[string]struct{}{},
storage: storage,
}
}
func (st *deletionState) AddObserver(observer StateUpdateObserver) {
func (st *objectDeletionState) AddObserver(observer StateUpdateObserver) {
st.Lock()
defer st.Unlock()
st.stateUpdateObservers = append(st.stateUpdateObservers, observer)
}
func (st *deletionState) Add(ids []string) (err error) {
func (st *objectDeletionState) Add(ids []string) (err error) {
st.Lock()
defer func() {
st.Unlock()
@ -83,7 +81,7 @@ func (st *deletionState) Add(ids []string) (err error) {
return
}
func (st *deletionState) GetQueued() (ids []string) {
func (st *objectDeletionState) GetQueued() (ids []string) {
st.RLock()
defer st.RUnlock()
ids = make([]string, 0, len(st.queued))
@ -93,7 +91,7 @@ func (st *deletionState) GetQueued() (ids []string) {
return
}
func (st *deletionState) Delete(id string) (err error) {
func (st *objectDeletionState) Delete(id string) (err error) {
st.Lock()
defer st.Unlock()
delete(st.queued, id)
@ -105,13 +103,13 @@ func (st *deletionState) Delete(id string) (err error) {
return
}
func (st *deletionState) Exists(id string) bool {
func (st *objectDeletionState) Exists(id string) bool {
st.RLock()
defer st.RUnlock()
return st.exists(id)
}
func (st *deletionState) FilterJoin(ids ...[]string) (filtered []string) {
func (st *objectDeletionState) FilterJoin(ids ...[]string) (filtered []string) {
st.RLock()
defer st.RUnlock()
filter := func(ids []string) {
@ -127,22 +125,7 @@ func (st *deletionState) FilterJoin(ids ...[]string) (filtered []string) {
return
}
func (st *deletionState) CreateDeleteChange(id string, isSnapshot bool) (res []byte, err error) {
content := &spacesyncproto.SpaceSettingsContent_ObjectDelete{
ObjectDelete: &spacesyncproto.ObjectDelete{Id: id},
}
change := &spacesyncproto.SettingsData{
Content: []*spacesyncproto.SpaceSettingsContent{
{Value: content},
},
Snapshot: nil,
}
// TODO: add snapshot logic
res, err = change.Marshal()
return
}
func (st *deletionState) exists(id string) bool {
func (st *objectDeletionState) exists(id string) bool {
if _, exists := st.deleted[id]; exists {
return true
}

View File

@ -1,4 +1,4 @@
package deletionstate
package settingsstate
import (
"github.com/anytypeio/any-sync/commonspace/spacestorage"
@ -11,14 +11,14 @@ import (
type fixture struct {
ctrl *gomock.Controller
delState *deletionState
delState *objectDeletionState
spaceStorage *mock_spacestorage.MockSpaceStorage
}
func newFixture(t *testing.T) *fixture {
ctrl := gomock.NewController(t)
spaceStorage := mock_spacestorage.NewMockSpaceStorage(ctrl)
delState := NewDeletionState(spaceStorage).(*deletionState)
delState := NewObjectDeletionState(spaceStorage).(*objectDeletionState)
return &fixture{
ctrl: ctrl,
delState: delState,

View File

@ -0,0 +1,213 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/anytypeio/any-sync/commonspace/settings/settingsstate (interfaces: ObjectDeletionState,StateBuilder,ChangeFactory)
// Package mock_settingsstate is a generated GoMock package.
package mock_settingsstate
import (
reflect "reflect"
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
settingsstate "github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
gomock "github.com/golang/mock/gomock"
)
// MockObjectDeletionState is a mock of ObjectDeletionState interface.
type MockObjectDeletionState struct {
ctrl *gomock.Controller
recorder *MockObjectDeletionStateMockRecorder
}
// MockObjectDeletionStateMockRecorder is the mock recorder for MockObjectDeletionState.
type MockObjectDeletionStateMockRecorder struct {
mock *MockObjectDeletionState
}
// NewMockObjectDeletionState creates a new mock instance.
func NewMockObjectDeletionState(ctrl *gomock.Controller) *MockObjectDeletionState {
mock := &MockObjectDeletionState{ctrl: ctrl}
mock.recorder = &MockObjectDeletionStateMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockObjectDeletionState) EXPECT() *MockObjectDeletionStateMockRecorder {
return m.recorder
}
// Add mocks base method.
func (m *MockObjectDeletionState) Add(arg0 []string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Add", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Add indicates an expected call of Add.
func (mr *MockObjectDeletionStateMockRecorder) Add(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockObjectDeletionState)(nil).Add), arg0)
}
// AddObserver mocks base method.
func (m *MockObjectDeletionState) AddObserver(arg0 settingsstate.StateUpdateObserver) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "AddObserver", arg0)
}
// AddObserver indicates an expected call of AddObserver.
func (mr *MockObjectDeletionStateMockRecorder) AddObserver(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddObserver", reflect.TypeOf((*MockObjectDeletionState)(nil).AddObserver), arg0)
}
// Delete mocks base method.
func (m *MockObjectDeletionState) Delete(arg0 string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Delete", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Delete indicates an expected call of Delete.
func (mr *MockObjectDeletionStateMockRecorder) Delete(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockObjectDeletionState)(nil).Delete), arg0)
}
// Exists mocks base method.
func (m *MockObjectDeletionState) Exists(arg0 string) bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Exists", arg0)
ret0, _ := ret[0].(bool)
return ret0
}
// Exists indicates an expected call of Exists.
func (mr *MockObjectDeletionStateMockRecorder) Exists(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exists", reflect.TypeOf((*MockObjectDeletionState)(nil).Exists), arg0)
}
// FilterJoin mocks base method.
func (m *MockObjectDeletionState) FilterJoin(arg0 ...[]string) []string {
m.ctrl.T.Helper()
varargs := []interface{}{}
for _, a := range arg0 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "FilterJoin", varargs...)
ret0, _ := ret[0].([]string)
return ret0
}
// FilterJoin indicates an expected call of FilterJoin.
func (mr *MockObjectDeletionStateMockRecorder) FilterJoin(arg0 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FilterJoin", reflect.TypeOf((*MockObjectDeletionState)(nil).FilterJoin), arg0...)
}
// GetQueued mocks base method.
func (m *MockObjectDeletionState) GetQueued() []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetQueued")
ret0, _ := ret[0].([]string)
return ret0
}
// GetQueued indicates an expected call of GetQueued.
func (mr *MockObjectDeletionStateMockRecorder) GetQueued() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetQueued", reflect.TypeOf((*MockObjectDeletionState)(nil).GetQueued))
}
// MockStateBuilder is a mock of StateBuilder interface.
type MockStateBuilder struct {
ctrl *gomock.Controller
recorder *MockStateBuilderMockRecorder
}
// MockStateBuilderMockRecorder is the mock recorder for MockStateBuilder.
type MockStateBuilderMockRecorder struct {
mock *MockStateBuilder
}
// NewMockStateBuilder creates a new mock instance.
func NewMockStateBuilder(ctrl *gomock.Controller) *MockStateBuilder {
mock := &MockStateBuilder{ctrl: ctrl}
mock.recorder = &MockStateBuilderMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockStateBuilder) EXPECT() *MockStateBuilderMockRecorder {
return m.recorder
}
// Build mocks base method.
func (m *MockStateBuilder) Build(arg0 objecttree.ObjectTree, arg1 *settingsstate.State) (*settingsstate.State, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Build", arg0, arg1)
ret0, _ := ret[0].(*settingsstate.State)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Build indicates an expected call of Build.
func (mr *MockStateBuilderMockRecorder) Build(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Build", reflect.TypeOf((*MockStateBuilder)(nil).Build), arg0, arg1)
}
// MockChangeFactory is a mock of ChangeFactory interface.
type MockChangeFactory struct {
ctrl *gomock.Controller
recorder *MockChangeFactoryMockRecorder
}
// MockChangeFactoryMockRecorder is the mock recorder for MockChangeFactory.
type MockChangeFactoryMockRecorder struct {
mock *MockChangeFactory
}
// NewMockChangeFactory creates a new mock instance.
func NewMockChangeFactory(ctrl *gomock.Controller) *MockChangeFactory {
mock := &MockChangeFactory{ctrl: ctrl}
mock.recorder = &MockChangeFactoryMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockChangeFactory) EXPECT() *MockChangeFactoryMockRecorder {
return m.recorder
}
// CreateObjectDeleteChange mocks base method.
func (m *MockChangeFactory) CreateObjectDeleteChange(arg0 string, arg1 *settingsstate.State, arg2 bool) ([]byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CreateObjectDeleteChange", arg0, arg1, arg2)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// CreateObjectDeleteChange indicates an expected call of CreateObjectDeleteChange.
func (mr *MockChangeFactoryMockRecorder) CreateObjectDeleteChange(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateObjectDeleteChange", reflect.TypeOf((*MockChangeFactory)(nil).CreateObjectDeleteChange), arg0, arg1, arg2)
}
// CreateSpaceDeleteChange mocks base method.
func (m *MockChangeFactory) CreateSpaceDeleteChange(arg0 string, arg1 *settingsstate.State, arg2 bool) ([]byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CreateSpaceDeleteChange", arg0, arg1, arg2)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// CreateSpaceDeleteChange indicates an expected call of CreateSpaceDeleteChange.
func (mr *MockChangeFactoryMockRecorder) CreateSpaceDeleteChange(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSpaceDeleteChange", reflect.TypeOf((*MockChangeFactory)(nil).CreateSpaceDeleteChange), arg0, arg1, arg2)
}

View File

@ -0,0 +1,7 @@
package settingsstate
type State struct {
DeletedIds []string
DeleterId string
LastIteratedId string
}

View File

@ -0,0 +1,76 @@
package settingsstate
import (
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/gogo/protobuf/proto"
)
type StateBuilder interface {
Build(tree objecttree.ObjectTree, state *State) (*State, error)
}
func NewStateBuilder() StateBuilder {
return &stateBuilder{}
}
type stateBuilder struct {
}
func (s *stateBuilder) Build(tr objecttree.ObjectTree, oldState *State) (state *State, err error) {
var (
rootId = tr.Root().Id
startId = rootId
)
state = oldState
if state == nil {
state = &State{}
} else if state.LastIteratedId != "" {
startId = state.LastIteratedId
}
process := func(change *objecttree.Change) bool {
state = s.processChange(change, rootId, state)
state.LastIteratedId = change.Id
return true
}
convert := func(decrypted []byte) (res any, err error) {
deleteChange := &spacesyncproto.SettingsData{}
err = proto.Unmarshal(decrypted, deleteChange)
if err != nil {
return nil, err
}
return deleteChange, nil
}
err = tr.IterateFrom(startId, convert, process)
return
}
func (s *stateBuilder) processChange(change *objecttree.Change, rootId string, state *State) *State {
// ignoring root change which has empty model or startId change
if change.Model == nil || state.LastIteratedId == change.Id {
return state
}
deleteChange := change.Model.(*spacesyncproto.SettingsData)
// getting data from snapshot if we start from it
if change.Id == rootId {
state = &State{
DeletedIds: deleteChange.Snapshot.DeletedIds,
DeleterId: deleteChange.Snapshot.DeleterPeerId,
LastIteratedId: rootId,
}
return state
}
// otherwise getting data from content
for _, cnt := range deleteChange.Content {
switch {
case cnt.GetObjectDelete() != nil:
state.DeletedIds = append(state.DeletedIds, cnt.GetObjectDelete().GetId())
case cnt.GetSpaceDelete() != nil:
state.DeleterId = cnt.GetSpaceDelete().GetDeleterPeerId()
}
}
return state
}

View File

@ -0,0 +1,93 @@
package settingsstate
import (
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree/mock_objecttree"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"testing"
)
func TestStateBuilder_ProcessChange(t *testing.T) {
sb := &stateBuilder{}
rootId := "rootId"
deletedId := "deletedId"
t.Run("empty model", func(t *testing.T) {
ch := &objecttree.Change{}
newSt := sb.processChange(ch, rootId, &State{
DeletedIds: []string{deletedId},
})
require.Equal(t, []string{deletedId}, newSt.DeletedIds)
})
t.Run("changeId is equal to startId, LastIteratedId is equal to startId", func(t *testing.T) {
ch := &objecttree.Change{}
ch.Model = &spacesyncproto.SettingsData{
Content: []*spacesyncproto.SpaceSettingsContent{
{Value: &spacesyncproto.SpaceSettingsContent_ObjectDelete{
ObjectDelete: &spacesyncproto.ObjectDelete{Id: deletedId},
}},
},
}
ch.Id = "startId"
startId := "startId"
newSt := sb.processChange(ch, rootId, &State{
DeletedIds: []string{deletedId},
LastIteratedId: startId,
})
require.Equal(t, []string{deletedId}, newSt.DeletedIds)
})
t.Run("changeId is equal to rootId", func(t *testing.T) {
ch := &objecttree.Change{}
ch.Model = &spacesyncproto.SettingsData{
Snapshot: &spacesyncproto.SpaceSettingsSnapshot{
DeletedIds: []string{"id1", "id2"},
DeleterPeerId: "peerId",
},
}
ch.Id = "rootId"
newSt := sb.processChange(ch, rootId, &State{})
require.Equal(t, []string{"id1", "id2"}, newSt.DeletedIds)
require.Equal(t, "peerId", newSt.DeleterId)
})
t.Run("changeId is not equal to lastIteratedId or rootId", func(t *testing.T) {
ch := &objecttree.Change{}
ch.Model = &spacesyncproto.SettingsData{
Content: []*spacesyncproto.SpaceSettingsContent{
{Value: &spacesyncproto.SpaceSettingsContent_ObjectDelete{
ObjectDelete: &spacesyncproto.ObjectDelete{Id: deletedId},
}},
},
}
ch.Id = "someId"
newSt := sb.processChange(ch, rootId, &State{})
require.Equal(t, []string{deletedId}, newSt.DeletedIds)
})
}
func TestStateBuilder_Build(t *testing.T) {
ctrl := gomock.NewController(t)
objTree := mock_objecttree.NewMockObjectTree(ctrl)
sb := &stateBuilder{}
defer ctrl.Finish()
t.Run("state is nil", func(t *testing.T) {
ch := &objecttree.Change{Id: "rootId"}
objTree.EXPECT().Root().Return(ch)
objTree.EXPECT().IterateFrom("rootId", gomock.Any(), gomock.Any()).Return(nil)
_, err := sb.Build(objTree, nil)
require.NoError(t, err)
})
t.Run("state is non-empty", func(t *testing.T) {
ch := &objecttree.Change{Id: "rootId"}
objTree.EXPECT().Root().Return(ch)
objTree.EXPECT().IterateFrom("someId", gomock.Any(), gomock.Any()).Return(nil)
_, err := sb.Build(objTree, &State{LastIteratedId: "someId"})
require.NoError(t, err)
})
}

View File

@ -18,7 +18,7 @@ import (
"github.com/anytypeio/any-sync/commonspace/objectsync"
"github.com/anytypeio/any-sync/commonspace/peermanager"
"github.com/anytypeio/any-sync/commonspace/settings"
"github.com/anytypeio/any-sync/commonspace/settings/deletionstate"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
"github.com/anytypeio/any-sync/commonspace/spacestorage"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/anytypeio/any-sync/commonspace/syncstatus"
@ -38,8 +38,7 @@ import (
)
var (
ErrSpaceClosed = errors.New("space is closed")
ErrPutNotImplemented = errors.New("put tree is not implemented")
ErrSpaceClosed = errors.New("space is closed")
)
type SpaceCreatePayload struct {
@ -99,6 +98,9 @@ type Space interface {
DeleteTree(ctx context.Context, id string) (err error)
BuildHistoryTree(ctx context.Context, id string, opts HistoryTreeOpts) (t objecttree.HistoryTree, err error)
SpaceDeleteRawChange(ctx context.Context) (raw *treechangeproto.RawTreeChangeWithId, err error)
DeleteSpace(ctx context.Context, deleteChange *treechangeproto.RawTreeChangeWithId) (err error)
HeadSync() headsync.HeadSync
ObjectSync() objectsync.ObjectSync
SyncStatus() syncstatus.StatusUpdater
@ -128,6 +130,7 @@ type space struct {
handleQueue multiqueue.MultiQueue[HandleMessage]
isClosed *atomic.Bool
isDeleted *atomic.Bool
treesUsed *atomic.Int32
}
@ -190,7 +193,7 @@ func (s *space) Init(ctx context.Context) (err error) {
s.aclList = syncacl.NewSyncAcl(aclList, s.objectSync.MessagePool())
s.cache.AddObject(s.aclList)
deletionState := deletionstate.NewDeletionState(s.storage)
deletionState := settingsstate.NewObjectDeletionState(s.storage)
deps := settings.Deps{
BuildFunc: func(ctx context.Context, id string, listener updatelistener.UpdateListener) (t synctree.SyncTree, err error) {
res, err := s.BuildTree(ctx, id, BuildTreeOpts{
@ -208,6 +211,9 @@ func (s *space) Init(ctx context.Context) (err error) {
TreeGetter: s.cache,
Store: s.storage,
DeletionState: deletionState,
Provider: s.headSync,
Configuration: s.configuration,
OnSpaceDelete: s.onSpaceDelete,
}
s.settingsObject = settings.NewSettingsObject(deps, s.id)
s.objectSync.Init()
@ -362,6 +368,14 @@ func (s *space) DeleteTree(ctx context.Context, id string) (err error) {
return s.settingsObject.DeleteObject(id)
}
func (s *space) SpaceDeleteRawChange(ctx context.Context) (raw *treechangeproto.RawTreeChangeWithId, err error) {
return s.settingsObject.SpaceDeleteRawChange()
}
func (s *space) DeleteSpace(ctx context.Context, deleteChange *treechangeproto.RawTreeChangeWithId) (err error) {
return s.settingsObject.DeleteSpace(ctx, deleteChange)
}
func (s *space) HandleMessage(ctx context.Context, hm HandleMessage) (err error) {
threadId := hm.Message.ObjectId
if hm.Message.ReplyId != "" {
@ -408,6 +422,14 @@ func (s *space) onObjectClose(id string) {
_ = s.handleQueue.CloseThread(id)
}
func (s *space) onSpaceDelete() {
err := s.storage.SetSpaceDeleted()
if err != nil {
log.Debug("failed to set space deleted")
}
s.isDeleted.Swap(true)
}
func (s *space) Close() error {
if s.isClosed.Swap(true) {
log.Warn("call space.Close on closed space", zap.String("id", s.id))

View File

@ -117,7 +117,15 @@ func (s *spaceService) NewSpace(ctx context.Context, id string) (Space, error) {
}
lastConfiguration := s.configurationService.GetLast()
var spaceIsClosed = &atomic.Bool{}
var (
spaceIsClosed = &atomic.Bool{}
spaceIsDeleted = &atomic.Bool{}
)
isDeleted, err := st.IsSpaceDeleted()
if err != nil {
return nil, err
}
spaceIsDeleted.Swap(isDeleted)
getter := newCommonGetter(st.Id(), s.treeGetter, spaceIsClosed)
syncStatus := syncstatus.NewNoOpSyncStatus()
// this will work only for clients, not the best solution, but...
@ -131,8 +139,8 @@ func (s *spaceService) NewSpace(ctx context.Context, id string) (Space, error) {
return nil, err
}
headSync := headsync.NewHeadSync(id, s.config.SyncPeriod, st, peerManager, getter, syncStatus, log)
objectSync := objectsync.NewObjectSync(id, peerManager, getter)
headSync := headsync.NewHeadSync(id, spaceIsDeleted, s.config.SyncPeriod, lastConfiguration, st, peerManager, getter, syncStatus, log)
objectSync := objectsync.NewObjectSync(id, spaceIsDeleted, lastConfiguration, peerManager, getter)
sp := &space{
id: id,
objectSync: objectSync,
@ -145,6 +153,7 @@ func (s *spaceService) NewSpace(ctx context.Context, id string) (Space, error) {
storage: st,
treesUsed: &atomic.Int32{},
isClosed: spaceIsClosed,
isDeleted: spaceIsDeleted,
}
return sp, nil
}

View File

@ -95,6 +95,21 @@ func (mr *MockSpaceStorageMockRecorder) Id() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Id", reflect.TypeOf((*MockSpaceStorage)(nil).Id))
}
// IsSpaceDeleted mocks base method.
func (m *MockSpaceStorage) IsSpaceDeleted() (bool, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IsSpaceDeleted")
ret0, _ := ret[0].(bool)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// IsSpaceDeleted indicates an expected call of IsSpaceDeleted.
func (mr *MockSpaceStorageMockRecorder) IsSpaceDeleted() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSpaceDeleted", reflect.TypeOf((*MockSpaceStorage)(nil).IsSpaceDeleted))
}
// ReadSpaceHash mocks base method.
func (m *MockSpaceStorage) ReadSpaceHash() (string, error) {
m.ctrl.T.Helper()
@ -110,6 +125,20 @@ func (mr *MockSpaceStorageMockRecorder) ReadSpaceHash() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadSpaceHash", reflect.TypeOf((*MockSpaceStorage)(nil).ReadSpaceHash))
}
// SetSpaceDeleted mocks base method.
func (m *MockSpaceStorage) SetSpaceDeleted() error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetSpaceDeleted")
ret0, _ := ret[0].(error)
return ret0
}
// SetSpaceDeleted indicates an expected call of SetSpaceDeleted.
func (mr *MockSpaceStorageMockRecorder) SetSpaceDeleted() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSpaceDeleted", reflect.TypeOf((*MockSpaceStorage)(nil).SetSpaceDeleted))
}
// SetTreeDeletedStatus mocks base method.
func (m *MockSpaceStorage) SetTreeDeletedStatus(arg0, arg1 string) error {
m.ctrl.T.Helper()

View File

@ -29,6 +29,8 @@ const (
// TODO: consider moving to some file with all common interfaces etc
type SpaceStorage interface {
Id() string
SetSpaceDeleted() error
IsSpaceDeleted() (bool, error)
SetTreeDeletedStatus(id, state string) error
TreeDeletedStatus(id string) (string, error)
SpaceSettingsId() string

View File

@ -12,4 +12,5 @@ var (
ErrSpaceMissing = errGroup.Register(errors.New("space is missing"), uint64(ErrCodes_SpaceMissing))
ErrSpaceExists = errGroup.Register(errors.New("space exists"), uint64(ErrCodes_SpaceExists))
ErrSpaceNotInCache = errGroup.Register(errors.New("space not in cache"), uint64(ErrCodes_SpaceNotInCache))
ErrSpaceIsDeleted = errGroup.Register(errors.New("space is deleted"), uint64(ErrCodes_SpaceIsDeleted))
)

View File

@ -8,6 +8,7 @@ enum ErrCodes {
SpaceMissing = 1;
SpaceExists = 2;
SpaceNotInCache = 3;
SpaceIsDeleted = 4;
ErrorOffset = 100;
}
@ -60,8 +61,6 @@ message ObjectSyncMessage {
string replyId = 3;
bytes payload = 4;
string objectId = 5;
// string identity = 5;
// string peerSignature = 6;
}
// SpacePushRequest is a request to add space on a node containing only one acl record
@ -116,6 +115,7 @@ message RawSpaceHeaderWithId {
message SpaceSettingsContent {
oneof value {
ObjectDelete objectDelete = 1;
SpaceDelete spaceDelete = 2;
}
}
@ -124,9 +124,15 @@ message ObjectDelete {
string id = 1;
}
// SpaceDelete is a message containing deleter peer id
message SpaceDelete {
string deleterPeerId = 1;
}
// SpaceSettingsSnapshot contains all the deleted ids in a snapshot
message SpaceSettingsSnapshot {
repeated string deletedIds = 1;
string deleterPeerId = 2;
}
// SettingsData contains ObjectTree change payload

View File

@ -29,6 +29,7 @@ const (
ErrCodes_SpaceMissing ErrCodes = 1
ErrCodes_SpaceExists ErrCodes = 2
ErrCodes_SpaceNotInCache ErrCodes = 3
ErrCodes_SpaceIsDeleted ErrCodes = 4
ErrCodes_ErrorOffset ErrCodes = 100
)
@ -37,6 +38,7 @@ var ErrCodes_name = map[int32]string{
1: "SpaceMissing",
2: "SpaceExists",
3: "SpaceNotInCache",
4: "SpaceIsDeleted",
100: "ErrorOffset",
}
@ -45,6 +47,7 @@ var ErrCodes_value = map[string]int32{
"SpaceMissing": 1,
"SpaceExists": 2,
"SpaceNotInCache": 3,
"SpaceIsDeleted": 4,
"ErrorOffset": 100,
}
@ -869,6 +872,7 @@ type SpaceSettingsContent struct {
// Types that are valid to be assigned to Value:
//
// *SpaceSettingsContent_ObjectDelete
// *SpaceSettingsContent_SpaceDelete
Value isSpaceSettingsContent_Value `protobuf_oneof:"value"`
}
@ -914,8 +918,12 @@ type isSpaceSettingsContent_Value interface {
type SpaceSettingsContent_ObjectDelete struct {
ObjectDelete *ObjectDelete `protobuf:"bytes,1,opt,name=objectDelete,proto3,oneof" json:"objectDelete,omitempty"`
}
type SpaceSettingsContent_SpaceDelete struct {
SpaceDelete *SpaceDelete `protobuf:"bytes,2,opt,name=spaceDelete,proto3,oneof" json:"spaceDelete,omitempty"`
}
func (*SpaceSettingsContent_ObjectDelete) isSpaceSettingsContent_Value() {}
func (*SpaceSettingsContent_SpaceDelete) isSpaceSettingsContent_Value() {}
func (m *SpaceSettingsContent) GetValue() isSpaceSettingsContent_Value {
if m != nil {
@ -931,10 +939,18 @@ func (m *SpaceSettingsContent) GetObjectDelete() *ObjectDelete {
return nil
}
func (m *SpaceSettingsContent) GetSpaceDelete() *SpaceDelete {
if x, ok := m.GetValue().(*SpaceSettingsContent_SpaceDelete); ok {
return x.SpaceDelete
}
return nil
}
// XXX_OneofWrappers is for the internal use of the proto package.
func (*SpaceSettingsContent) XXX_OneofWrappers() []interface{} {
return []interface{}{
(*SpaceSettingsContent_ObjectDelete)(nil),
(*SpaceSettingsContent_SpaceDelete)(nil),
}
}
@ -983,16 +999,62 @@ func (m *ObjectDelete) GetId() string {
return ""
}
// SpaceDelete is a message containing deleter peer id
type SpaceDelete struct {
DeleterPeerId string `protobuf:"bytes,1,opt,name=deleterPeerId,proto3" json:"deleterPeerId,omitempty"`
}
func (m *SpaceDelete) Reset() { *m = SpaceDelete{} }
func (m *SpaceDelete) String() string { return proto.CompactTextString(m) }
func (*SpaceDelete) ProtoMessage() {}
func (*SpaceDelete) Descriptor() ([]byte, []int) {
return fileDescriptor_80e49f1f4ac27799, []int{16}
}
func (m *SpaceDelete) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *SpaceDelete) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_SpaceDelete.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *SpaceDelete) XXX_Merge(src proto.Message) {
xxx_messageInfo_SpaceDelete.Merge(m, src)
}
func (m *SpaceDelete) XXX_Size() int {
return m.Size()
}
func (m *SpaceDelete) XXX_DiscardUnknown() {
xxx_messageInfo_SpaceDelete.DiscardUnknown(m)
}
var xxx_messageInfo_SpaceDelete proto.InternalMessageInfo
func (m *SpaceDelete) GetDeleterPeerId() string {
if m != nil {
return m.DeleterPeerId
}
return ""
}
// SpaceSettingsSnapshot contains all the deleted ids in a snapshot
type SpaceSettingsSnapshot struct {
DeletedIds []string `protobuf:"bytes,1,rep,name=deletedIds,proto3" json:"deletedIds,omitempty"`
DeletedIds []string `protobuf:"bytes,1,rep,name=deletedIds,proto3" json:"deletedIds,omitempty"`
DeleterPeerId string `protobuf:"bytes,2,opt,name=deleterPeerId,proto3" json:"deleterPeerId,omitempty"`
}
func (m *SpaceSettingsSnapshot) Reset() { *m = SpaceSettingsSnapshot{} }
func (m *SpaceSettingsSnapshot) String() string { return proto.CompactTextString(m) }
func (*SpaceSettingsSnapshot) ProtoMessage() {}
func (*SpaceSettingsSnapshot) Descriptor() ([]byte, []int) {
return fileDescriptor_80e49f1f4ac27799, []int{16}
return fileDescriptor_80e49f1f4ac27799, []int{17}
}
func (m *SpaceSettingsSnapshot) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1028,6 +1090,13 @@ func (m *SpaceSettingsSnapshot) GetDeletedIds() []string {
return nil
}
func (m *SpaceSettingsSnapshot) GetDeleterPeerId() string {
if m != nil {
return m.DeleterPeerId
}
return ""
}
// SettingsData contains ObjectTree change payload
type SettingsData struct {
Content []*SpaceSettingsContent `protobuf:"bytes,1,rep,name=content,proto3" json:"content,omitempty"`
@ -1038,7 +1107,7 @@ func (m *SettingsData) Reset() { *m = SettingsData{} }
func (m *SettingsData) String() string { return proto.CompactTextString(m) }
func (*SettingsData) ProtoMessage() {}
func (*SettingsData) Descriptor() ([]byte, []int) {
return fileDescriptor_80e49f1f4ac27799, []int{17}
return fileDescriptor_80e49f1f4ac27799, []int{18}
}
func (m *SettingsData) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1090,7 +1159,7 @@ func (m *SpaceSubscription) Reset() { *m = SpaceSubscription{} }
func (m *SpaceSubscription) String() string { return proto.CompactTextString(m) }
func (*SpaceSubscription) ProtoMessage() {}
func (*SpaceSubscription) Descriptor() ([]byte, []int) {
return fileDescriptor_80e49f1f4ac27799, []int{18}
return fileDescriptor_80e49f1f4ac27799, []int{19}
}
func (m *SpaceSubscription) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -1152,6 +1221,7 @@ func init() {
proto.RegisterType((*RawSpaceHeaderWithId)(nil), "spacesync.RawSpaceHeaderWithId")
proto.RegisterType((*SpaceSettingsContent)(nil), "spacesync.SpaceSettingsContent")
proto.RegisterType((*ObjectDelete)(nil), "spacesync.ObjectDelete")
proto.RegisterType((*SpaceDelete)(nil), "spacesync.SpaceDelete")
proto.RegisterType((*SpaceSettingsSnapshot)(nil), "spacesync.SpaceSettingsSnapshot")
proto.RegisterType((*SettingsData)(nil), "spacesync.SettingsData")
proto.RegisterType((*SpaceSubscription)(nil), "spacesync.SpaceSubscription")
@ -1162,68 +1232,71 @@ func init() {
}
var fileDescriptor_80e49f1f4ac27799 = []byte{
// 971 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x4b, 0x6f, 0xdb, 0xc6,
0x13, 0x17, 0xe5, 0xa7, 0xc6, 0xb4, 0xcc, 0x6c, 0x9c, 0x7f, 0xf8, 0x57, 0x0c, 0x45, 0xd8, 0x43,
0x61, 0xe4, 0x90, 0x87, 0x52, 0xb4, 0x48, 0x1f, 0x87, 0xc4, 0x56, 0x1a, 0xa1, 0x48, 0x6d, 0xac,
0x1a, 0x14, 0x28, 0xd0, 0x02, 0x6b, 0x72, 0x2c, 0xb1, 0xa5, 0x96, 0x2c, 0x77, 0xd5, 0x58, 0xc7,
0x9e, 0x7a, 0xed, 0xbd, 0xa7, 0x7e, 0x87, 0x7e, 0x88, 0x1e, 0x73, 0xec, 0xb1, 0xb0, 0xbf, 0x48,
0xb1, 0xcb, 0xb7, 0x45, 0xe7, 0xd0, 0x8b, 0xcc, 0x9d, 0xc7, 0x6f, 0x7e, 0x33, 0xb3, 0x33, 0x6b,
0x78, 0xe2, 0x45, 0xf3, 0x79, 0x24, 0x64, 0xcc, 0x3d, 0x7c, 0x64, 0x7e, 0xe5, 0x52, 0x78, 0x71,
0x12, 0xa9, 0xe8, 0x91, 0xf9, 0x95, 0xa5, 0xf4, 0xa1, 0x11, 0x90, 0x4e, 0x21, 0xa0, 0x63, 0xd8,
0x7d, 0x85, 0xdc, 0x9f, 0x2c, 0x85, 0xc7, 0xb8, 0x98, 0x22, 0x21, 0xb0, 0x7e, 0x9e, 0x44, 0x73,
0xd7, 0x1a, 0x58, 0x87, 0xeb, 0xcc, 0x7c, 0x93, 0x2e, 0xb4, 0x55, 0xe4, 0xb6, 0x8d, 0xa4, 0xad,
0x22, 0xb2, 0x0f, 0x1b, 0x61, 0x30, 0x0f, 0x94, 0xbb, 0x36, 0xb0, 0x0e, 0x77, 0x59, 0x7a, 0xa0,
0x17, 0xd0, 0x2d, 0xa0, 0x50, 0x2e, 0x42, 0xa5, 0xb1, 0x66, 0x5c, 0xce, 0x0c, 0x96, 0xcd, 0xcc,
0x37, 0xf9, 0x0c, 0xb6, 0x31, 0xc4, 0x39, 0x0a, 0x25, 0xdd, 0xf6, 0x60, 0xed, 0x70, 0x67, 0x38,
0x78, 0x58, 0xf2, 0xab, 0x03, 0x8c, 0x52, 0x43, 0x56, 0x78, 0xe8, 0xc8, 0x5e, 0xb4, 0x10, 0x45,
0x64, 0x73, 0xa0, 0x9f, 0xc2, 0x9d, 0x46, 0x47, 0x4d, 0x3c, 0xf0, 0x4d, 0xf8, 0x0e, 0x6b, 0x07,
0xbe, 0x21, 0x84, 0xdc, 0x37, 0xa9, 0x74, 0x98, 0xf9, 0xa6, 0xdf, 0xc1, 0x5e, 0xe9, 0xfc, 0xd3,
0x02, 0xa5, 0x22, 0x2e, 0x6c, 0x19, 0x4a, 0xe3, 0xdc, 0x37, 0x3f, 0x92, 0xc7, 0xb0, 0x99, 0xe8,
0x32, 0xe5, 0xdc, 0xdd, 0x26, 0xee, 0xda, 0x80, 0x65, 0x76, 0xf4, 0x0b, 0x70, 0x2a, 0xdc, 0xe2,
0x48, 0x48, 0x24, 0x4f, 0x61, 0x2b, 0x31, 0x3c, 0xa5, 0x6b, 0x19, 0x98, 0xff, 0xdf, 0x58, 0x02,
0x96, 0x5b, 0xd2, 0xdf, 0x2d, 0xb8, 0x75, 0x72, 0xf6, 0x03, 0x7a, 0x4a, 0x6b, 0x5f, 0xa3, 0x94,
0x7c, 0x8a, 0xef, 0xa1, 0x7a, 0x00, 0x9d, 0x24, 0xcd, 0x67, 0x9c, 0x27, 0x5c, 0x0a, 0xb4, 0x5f,
0x82, 0x71, 0xb8, 0x1c, 0xfb, 0xa6, 0x94, 0x1d, 0x96, 0x1f, 0xb5, 0x26, 0xe6, 0xcb, 0x30, 0xe2,
0xbe, 0xbb, 0x6e, 0xfa, 0x96, 0x1f, 0x49, 0x0f, 0xb6, 0x23, 0x43, 0x60, 0xec, 0xbb, 0x1b, 0xc6,
0xa9, 0x38, 0xd3, 0x11, 0x38, 0x13, 0x1d, 0xf8, 0x74, 0x21, 0x67, 0x79, 0x19, 0x9f, 0x94, 0x48,
0x9a, 0xdb, 0xce, 0xf0, 0x6e, 0x25, 0xcd, 0xd4, 0x3a, 0x55, 0x17, 0x21, 0xe8, 0x6d, 0xb8, 0x55,
0x81, 0x49, 0xcb, 0x45, 0x69, 0x81, 0x1d, 0x86, 0x39, 0xf6, 0xb5, 0xce, 0xd2, 0x97, 0x85, 0xa3,
0xb6, 0xc9, 0xea, 0xfc, 0x1f, 0x08, 0xfc, 0xd2, 0x06, 0xbb, 0xaa, 0x21, 0xcf, 0x61, 0xc7, 0xf8,
0xe8, 0xb6, 0x60, 0x92, 0xe1, 0xdc, 0xaf, 0xe0, 0x30, 0xfe, 0x76, 0x52, 0x1a, 0x7c, 0x13, 0xa8,
0xd9, 0xd8, 0x67, 0x55, 0x1f, 0xd2, 0x07, 0xe0, 0x5e, 0x98, 0x01, 0x9a, 0x56, 0xd8, 0xac, 0x22,
0x21, 0x14, 0xec, 0xf2, 0x54, 0x34, 0xa4, 0x26, 0x23, 0x43, 0xd8, 0x37, 0x90, 0x13, 0x54, 0x2a,
0x10, 0x53, 0x79, 0x5a, 0x6b, 0x51, 0xa3, 0x8e, 0x7c, 0x04, 0xff, 0x6b, 0x92, 0x17, 0xdd, 0xbb,
0x41, 0x4b, 0xff, 0xb0, 0x60, 0xa7, 0x92, 0x92, 0xee, 0x7b, 0xe0, 0xa3, 0x50, 0x81, 0x5a, 0x66,
0xa3, 0x5c, 0x9c, 0xf5, 0x2d, 0x53, 0xc1, 0x1c, 0xa5, 0xe2, 0xf3, 0xd8, 0xa4, 0xb6, 0xc6, 0x4a,
0x81, 0xd6, 0x9a, 0x18, 0x5f, 0x2f, 0x63, 0xcc, 0xd2, 0x2a, 0x05, 0xe4, 0x03, 0xe8, 0xea, 0x4b,
0x17, 0x78, 0x5c, 0x05, 0x91, 0xf8, 0x12, 0x97, 0x26, 0x9b, 0x75, 0x76, 0x4d, 0xaa, 0xa7, 0x56,
0x22, 0xa6, 0xac, 0x6d, 0x66, 0xbe, 0xe9, 0x29, 0x74, 0xeb, 0x85, 0x27, 0x83, 0xd5, 0x46, 0xd9,
0xf5, 0x3e, 0x68, 0x36, 0xc1, 0x54, 0x70, 0xb5, 0x48, 0x30, 0x6b, 0x43, 0x29, 0xa0, 0xc7, 0xb0,
0xdf, 0xd4, 0x4a, 0x33, 0x47, 0xfc, 0x6d, 0x0d, 0xb5, 0x14, 0x64, 0xf7, 0xb0, 0x5d, 0xdc, 0xc3,
0xef, 0x61, 0x7f, 0x52, 0xad, 0xea, 0x51, 0x24, 0x94, 0xde, 0x44, 0x9f, 0x83, 0x9d, 0xce, 0xca,
0x31, 0x86, 0xa8, 0xb0, 0xe1, 0x3e, 0x9e, 0x54, 0xd4, 0xaf, 0x5a, 0xac, 0x66, 0xfe, 0x62, 0x0b,
0x36, 0x7e, 0xe6, 0xe1, 0x02, 0x69, 0x1f, 0xec, 0xaa, 0xe1, 0xca, 0x1c, 0x7c, 0x0c, 0x77, 0x6a,
0xf1, 0x27, 0x82, 0xc7, 0x72, 0x16, 0x29, 0x7d, 0x09, 0x7d, 0xe3, 0xe2, 0x8f, 0xfd, 0x74, 0xed,
0x74, 0x58, 0x45, 0x42, 0x7f, 0xb5, 0xc0, 0xce, 0x9d, 0x8e, 0xb9, 0xe2, 0xe4, 0x19, 0x6c, 0x79,
0x29, 0xf9, 0x6c, 0x49, 0xdd, 0xbf, 0x3e, 0x3c, 0xd7, 0x72, 0x64, 0xb9, 0xbd, 0xde, 0xf1, 0x32,
0x8b, 0x6b, 0x4a, 0x53, 0xdf, 0xf1, 0x8d, 0xfc, 0x58, 0xe1, 0x41, 0x7f, 0xcc, 0x46, 0x79, 0xb2,
0x38, 0x93, 0x5e, 0x12, 0xc4, 0xfa, 0x1a, 0xe8, 0x3b, 0x98, 0x2d, 0xb6, 0x9c, 0x7c, 0x71, 0x26,
0x9f, 0xc0, 0x26, 0xf7, 0xb4, 0x95, 0x09, 0xd6, 0x1d, 0xd2, 0x95, 0x60, 0x15, 0xa4, 0xe7, 0xc6,
0x92, 0x65, 0x1e, 0x0f, 0x3c, 0xd8, 0x1e, 0x25, 0xc9, 0x51, 0xe4, 0xa3, 0x24, 0x5d, 0x80, 0x37,
0x02, 0x2f, 0x62, 0xf4, 0x14, 0xfa, 0x4e, 0x8b, 0x38, 0xd9, 0x2a, 0x78, 0x1d, 0x48, 0x19, 0x88,
0xa9, 0x63, 0x91, 0xbd, 0x6c, 0x30, 0x46, 0x17, 0x81, 0x54, 0xd2, 0x69, 0x93, 0xdb, 0xb0, 0x67,
0x04, 0x5f, 0x45, 0x6a, 0x2c, 0x8e, 0xb8, 0x37, 0x43, 0x67, 0x4d, 0x5b, 0x8d, 0x92, 0x24, 0x4a,
0x4e, 0xce, 0xcf, 0x25, 0x2a, 0xc7, 0x7f, 0xf0, 0x0c, 0xee, 0xde, 0xc0, 0x83, 0xec, 0x42, 0x27,
0x93, 0x9e, 0xa1, 0xd3, 0xd2, 0xae, 0x6f, 0x84, 0x2c, 0x04, 0xd6, 0xf0, 0xcf, 0x36, 0x74, 0x52,
0xdf, 0xa5, 0xf0, 0xc8, 0x11, 0x6c, 0xe7, 0xcf, 0x03, 0xe9, 0x35, 0xbe, 0x19, 0x66, 0x3b, 0xf6,
0xee, 0x35, 0xbf, 0x27, 0xe9, 0x56, 0x7c, 0x99, 0x21, 0xea, 0x1d, 0x4b, 0xee, 0xad, 0x6c, 0xc4,
0x72, 0x81, 0xf7, 0x0e, 0x9a, 0x95, 0x2b, 0x38, 0x61, 0xd8, 0x84, 0x53, 0x2c, 0xeb, 0x26, 0x9c,
0xca, 0x96, 0x66, 0xe0, 0x94, 0xef, 0xda, 0x44, 0x25, 0xc8, 0xe7, 0xe4, 0x60, 0x65, 0x30, 0x2a,
0x8f, 0x5e, 0xef, 0xbd, 0xda, 0x43, 0xeb, 0xb1, 0xf5, 0xe2, 0xc3, 0xbf, 0x2e, 0xfb, 0xd6, 0xbb,
0xcb, 0xbe, 0xf5, 0xcf, 0x65, 0xdf, 0xfa, 0xed, 0xaa, 0xdf, 0x7a, 0x77, 0xd5, 0x6f, 0xfd, 0x7d,
0xd5, 0x6f, 0x7d, 0xdb, 0xbb, 0xf9, 0xdf, 0xa5, 0xb3, 0x4d, 0xf3, 0xe7, 0xe9, 0xbf, 0x01, 0x00,
0x00, 0xff, 0xff, 0x23, 0x56, 0x6f, 0xd6, 0x53, 0x09, 0x00, 0x00,
// 1019 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0x4b, 0x6f, 0xdb, 0x46,
0x10, 0x16, 0xe9, 0xa7, 0xc6, 0xb2, 0xcc, 0x6c, 0x9c, 0x44, 0x55, 0x0c, 0x45, 0x58, 0x14, 0x85,
0x91, 0x43, 0x1e, 0x72, 0x51, 0x20, 0x69, 0x7b, 0x48, 0x6c, 0xa5, 0x11, 0x8a, 0xd4, 0xc6, 0xaa,
0x41, 0x81, 0x02, 0x39, 0xac, 0xc9, 0xb1, 0xc4, 0x96, 0x22, 0x59, 0xee, 0xaa, 0xb6, 0x8e, 0x3d,
0xf5, 0xda, 0x73, 0x7b, 0xea, 0x7f, 0xe8, 0x8f, 0xe8, 0x31, 0xc7, 0x1e, 0x0b, 0xfb, 0x8f, 0x14,
0xbb, 0x5c, 0x3e, 0x24, 0x51, 0x39, 0xf4, 0x22, 0x73, 0xbf, 0x99, 0xf9, 0xe6, 0xb5, 0x3b, 0x63,
0x78, 0xea, 0x46, 0x93, 0x49, 0x14, 0x8a, 0x98, 0xbb, 0xf8, 0x58, 0xff, 0x8a, 0x59, 0xe8, 0xc6,
0x49, 0x24, 0xa3, 0xc7, 0xfa, 0x57, 0x14, 0xe8, 0x23, 0x0d, 0x90, 0x7a, 0x0e, 0xd0, 0x01, 0xec,
0xbe, 0x46, 0xee, 0x0d, 0x67, 0xa1, 0xcb, 0x78, 0x38, 0x42, 0x42, 0x60, 0xfd, 0x22, 0x89, 0x26,
0x2d, 0xab, 0x6b, 0x1d, 0xae, 0x33, 0xfd, 0x4d, 0x9a, 0x60, 0xcb, 0xa8, 0x65, 0x6b, 0xc4, 0x96,
0x11, 0xd9, 0x87, 0x8d, 0xc0, 0x9f, 0xf8, 0xb2, 0xb5, 0xd6, 0xb5, 0x0e, 0x77, 0x59, 0x7a, 0xa0,
0x57, 0xd0, 0xcc, 0xa9, 0x50, 0x4c, 0x03, 0xa9, 0xb8, 0xc6, 0x5c, 0x8c, 0x35, 0x57, 0x83, 0xe9,
0x6f, 0xf2, 0x05, 0x6c, 0x63, 0x80, 0x13, 0x0c, 0xa5, 0x68, 0xd9, 0xdd, 0xb5, 0xc3, 0x9d, 0x5e,
0xf7, 0x51, 0x11, 0xdf, 0x3c, 0x41, 0x3f, 0x55, 0x64, 0xb9, 0x85, 0xf2, 0xec, 0x46, 0xd3, 0x30,
0xf7, 0xac, 0x0f, 0xf4, 0x73, 0xb8, 0x53, 0x69, 0xa8, 0x02, 0xf7, 0x3d, 0xed, 0xbe, 0xce, 0x6c,
0xdf, 0xd3, 0x01, 0x21, 0xf7, 0x74, 0x2a, 0x75, 0xa6, 0xbf, 0xe9, 0x3b, 0xd8, 0x2b, 0x8c, 0x7f,
0x9a, 0xa2, 0x90, 0xa4, 0x05, 0x5b, 0x3a, 0xa4, 0x41, 0x66, 0x9b, 0x1d, 0xc9, 0x13, 0xd8, 0x4c,
0x54, 0x99, 0xb2, 0xd8, 0x5b, 0x55, 0xb1, 0x2b, 0x05, 0x66, 0xf4, 0xe8, 0x57, 0xe0, 0x94, 0x62,
0x8b, 0xa3, 0x50, 0x20, 0x39, 0x82, 0xad, 0x44, 0xc7, 0x29, 0x5a, 0x96, 0xa6, 0xf9, 0x68, 0x65,
0x09, 0x58, 0xa6, 0x49, 0xff, 0xb0, 0xe0, 0xd6, 0xe9, 0xf9, 0x0f, 0xe8, 0x4a, 0x25, 0x7d, 0x83,
0x42, 0xf0, 0x11, 0x7e, 0x20, 0xd4, 0x03, 0xa8, 0x27, 0x69, 0x3e, 0x83, 0x2c, 0xe1, 0x02, 0x50,
0x76, 0x09, 0xc6, 0xc1, 0x6c, 0xe0, 0xe9, 0x52, 0xd6, 0x59, 0x76, 0x54, 0x92, 0x98, 0xcf, 0x82,
0x88, 0x7b, 0xad, 0x75, 0xdd, 0xb7, 0xec, 0x48, 0xda, 0xb0, 0x1d, 0xe9, 0x00, 0x06, 0x5e, 0x6b,
0x43, 0x1b, 0xe5, 0x67, 0xda, 0x07, 0x67, 0xa8, 0x1c, 0x9f, 0x4d, 0xc5, 0x38, 0x2b, 0xe3, 0xd3,
0x82, 0x49, 0xc5, 0xb6, 0xd3, 0xbb, 0x57, 0x4a, 0x33, 0xd5, 0x4e, 0xc5, 0xb9, 0x0b, 0x7a, 0x1b,
0x6e, 0x95, 0x68, 0xd2, 0x72, 0x51, 0x9a, 0x73, 0x07, 0x41, 0xc6, 0xbd, 0xd0, 0x59, 0xfa, 0x2a,
0x37, 0x54, 0x3a, 0xa6, 0xce, 0xff, 0x23, 0x80, 0x5f, 0x6c, 0x68, 0x94, 0x25, 0xe4, 0x05, 0xec,
0x68, 0x1b, 0xd5, 0x16, 0x4c, 0x0c, 0xcf, 0x83, 0x12, 0x0f, 0xe3, 0x97, 0xc3, 0x42, 0xe1, 0x3b,
0x5f, 0x8e, 0x07, 0x1e, 0x2b, 0xdb, 0x90, 0x0e, 0x00, 0x77, 0x03, 0x43, 0xa8, 0x5b, 0xd1, 0x60,
0x25, 0x84, 0x50, 0x68, 0x14, 0xa7, 0xbc, 0x21, 0x73, 0x18, 0xe9, 0xc1, 0xbe, 0xa6, 0x1c, 0xa2,
0x94, 0x7e, 0x38, 0x12, 0x67, 0x73, 0x2d, 0xaa, 0x94, 0x91, 0xcf, 0xe0, 0x6e, 0x15, 0x9e, 0x77,
0x6f, 0x85, 0x94, 0xfe, 0x69, 0xc1, 0x4e, 0x29, 0x25, 0xd5, 0x77, 0xdf, 0xc3, 0x50, 0xfa, 0x72,
0x66, 0x9e, 0x72, 0x7e, 0x56, 0xb7, 0x4c, 0xfa, 0x13, 0x14, 0x92, 0x4f, 0x62, 0x9d, 0xda, 0x1a,
0x2b, 0x00, 0x25, 0xd5, 0x3e, 0xbe, 0x9d, 0xc5, 0x68, 0xd2, 0x2a, 0x00, 0xf2, 0x09, 0x34, 0xd5,
0xa5, 0xf3, 0x5d, 0x2e, 0xfd, 0x28, 0xfc, 0x1a, 0x67, 0x3a, 0x9b, 0x75, 0xb6, 0x80, 0xaa, 0x57,
0x2b, 0x10, 0xd3, 0xa8, 0x1b, 0x4c, 0x7f, 0xd3, 0x33, 0x68, 0xce, 0x17, 0x9e, 0x74, 0x97, 0x1b,
0xd5, 0x98, 0xef, 0x83, 0x8a, 0xc6, 0x1f, 0x85, 0x5c, 0x4e, 0x13, 0x34, 0x6d, 0x28, 0x00, 0x7a,
0x02, 0xfb, 0x55, 0xad, 0xd4, 0xef, 0x88, 0x5f, 0xce, 0xb1, 0x16, 0x80, 0xb9, 0x87, 0x76, 0x7e,
0x0f, 0x7f, 0xb7, 0x60, 0x7f, 0x58, 0x2e, 0xeb, 0x71, 0x14, 0x4a, 0x35, 0x8a, 0xbe, 0x84, 0x46,
0xfa, 0x58, 0x4e, 0x30, 0x40, 0x89, 0x15, 0x17, 0xf2, 0xb4, 0x24, 0x7e, 0x5d, 0x63, 0x73, 0xea,
0xe4, 0xb9, 0xc9, 0xce, 0x58, 0xdb, 0xda, 0xfa, 0xee, 0xe2, 0x75, 0xce, 0x8d, 0xcb, 0xca, 0x2f,
0xb7, 0x60, 0xe3, 0x67, 0x1e, 0x4c, 0x91, 0x76, 0xa0, 0x51, 0x76, 0xb2, 0xf4, 0x88, 0x8e, 0x4c,
0xdf, 0x8d, 0xf8, 0x63, 0xd8, 0xf5, 0xf4, 0x57, 0x72, 0x86, 0x98, 0xe4, 0x13, 0x66, 0x1e, 0xa4,
0xef, 0xe0, 0xce, 0x5c, 0xc2, 0xc3, 0x90, 0xc7, 0x62, 0x1c, 0x49, 0x75, 0xed, 0x53, 0x4d, 0x6f,
0xe0, 0xa5, 0x83, 0xae, 0xce, 0x4a, 0xc8, 0x32, 0xbd, 0x5d, 0x45, 0xff, 0xab, 0x05, 0x8d, 0x8c,
0xfa, 0x84, 0x4b, 0x4e, 0x9e, 0xc1, 0x96, 0x9b, 0xd6, 0xd4, 0x0c, 0xcf, 0x07, 0x8b, 0x55, 0x58,
0x28, 0x3d, 0xcb, 0xf4, 0xd5, 0xee, 0x11, 0x26, 0x3a, 0x53, 0xc1, 0xee, 0x2a, 0xdb, 0x2c, 0x0b,
0x96, 0x5b, 0xd0, 0x1f, 0xcd, 0x88, 0x19, 0x4e, 0xcf, 0x85, 0x9b, 0xf8, 0xb1, 0xba, 0x9e, 0xea,
0x6d, 0x98, 0x81, 0x9b, 0xa5, 0x98, 0x9f, 0xc9, 0x73, 0xd8, 0xe4, 0xae, 0xd2, 0xd2, 0xce, 0x9a,
0x3d, 0xba, 0xe4, 0xac, 0xc4, 0xf4, 0x42, 0x6b, 0x32, 0x63, 0xf1, 0xf0, 0x12, 0xb6, 0xfb, 0x49,
0x72, 0x1c, 0x79, 0x28, 0x48, 0x13, 0xe0, 0x6d, 0x88, 0x57, 0x31, 0xba, 0x12, 0x3d, 0xa7, 0x46,
0x1c, 0x33, 0xa2, 0xde, 0xf8, 0x42, 0xf8, 0xe1, 0xc8, 0xb1, 0xc8, 0x9e, 0x69, 0x5c, 0xff, 0xca,
0x17, 0x52, 0x38, 0x36, 0xb9, 0x0d, 0x7b, 0x1a, 0xf8, 0x26, 0x92, 0x83, 0xf0, 0x98, 0xbb, 0x63,
0x74, 0xd6, 0x08, 0x81, 0xa6, 0x06, 0x07, 0x22, 0x6d, 0xb0, 0xe7, 0xac, 0x2b, 0xcb, 0x7e, 0x92,
0x44, 0xc9, 0xe9, 0xc5, 0x85, 0x40, 0xe9, 0x78, 0x0f, 0x9f, 0xc1, 0xbd, 0x15, 0xb1, 0x91, 0x5d,
0xa8, 0x1b, 0xf4, 0x1c, 0x9d, 0x9a, 0x32, 0x7d, 0x1b, 0x8a, 0x1c, 0xb0, 0x7a, 0x7f, 0xd9, 0x50,
0x4f, 0x6d, 0x67, 0xa1, 0x4b, 0x8e, 0x61, 0x3b, 0x5b, 0x65, 0xa4, 0x5d, 0xb9, 0xdf, 0xf4, 0x24,
0x6f, 0xdf, 0xaf, 0xde, 0x7d, 0xe9, 0x04, 0x7f, 0x65, 0x18, 0xd5, 0x3e, 0x20, 0xf7, 0x97, 0xa6,
0x77, 0xb1, 0x6c, 0xda, 0x07, 0xd5, 0xc2, 0x25, 0x9e, 0x20, 0xa8, 0xe2, 0xc9, 0x17, 0x4b, 0x15,
0x4f, 0x69, 0xa3, 0x30, 0x70, 0x8a, 0x1d, 0x3c, 0x94, 0x09, 0xf2, 0x09, 0x39, 0x58, 0x7a, 0xc3,
0xa5, 0x05, 0xdd, 0xfe, 0xa0, 0xf4, 0xd0, 0x7a, 0x62, 0xbd, 0xfc, 0xf4, 0xef, 0xeb, 0x8e, 0xf5,
0xfe, 0xba, 0x63, 0xfd, 0x7b, 0xdd, 0xb1, 0x7e, 0xbb, 0xe9, 0xd4, 0xde, 0xdf, 0x74, 0x6a, 0xff,
0xdc, 0x74, 0x6a, 0xdf, 0xb7, 0x57, 0xff, 0x6b, 0x77, 0xbe, 0xa9, 0xff, 0x1c, 0xfd, 0x17, 0x00,
0x00, 0xff, 0xff, 0xa1, 0xe4, 0x04, 0x3d, 0xff, 0x09, 0x00, 0x00,
}
func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) {
@ -1856,6 +1929,27 @@ func (m *SpaceSettingsContent_ObjectDelete) MarshalToSizedBuffer(dAtA []byte) (i
}
return len(dAtA) - i, nil
}
func (m *SpaceSettingsContent_SpaceDelete) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *SpaceSettingsContent_SpaceDelete) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
if m.SpaceDelete != nil {
{
size, err := m.SpaceDelete.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintSpacesync(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
return len(dAtA) - i, nil
}
func (m *ObjectDelete) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -1886,6 +1980,36 @@ func (m *ObjectDelete) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *SpaceDelete) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *SpaceDelete) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *SpaceDelete) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.DeleterPeerId) > 0 {
i -= len(m.DeleterPeerId)
copy(dAtA[i:], m.DeleterPeerId)
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.DeleterPeerId)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *SpaceSettingsSnapshot) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -1906,6 +2030,13 @@ func (m *SpaceSettingsSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.DeleterPeerId) > 0 {
i -= len(m.DeleterPeerId)
copy(dAtA[i:], m.DeleterPeerId)
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.DeleterPeerId)))
i--
dAtA[i] = 0x12
}
if len(m.DeletedIds) > 0 {
for iNdEx := len(m.DeletedIds) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.DeletedIds[iNdEx])
@ -2297,6 +2428,18 @@ func (m *SpaceSettingsContent_ObjectDelete) Size() (n int) {
}
return n
}
func (m *SpaceSettingsContent_SpaceDelete) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.SpaceDelete != nil {
l = m.SpaceDelete.Size()
n += 1 + l + sovSpacesync(uint64(l))
}
return n
}
func (m *ObjectDelete) Size() (n int) {
if m == nil {
return 0
@ -2310,6 +2453,19 @@ func (m *ObjectDelete) Size() (n int) {
return n
}
func (m *SpaceDelete) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.DeleterPeerId)
if l > 0 {
n += 1 + l + sovSpacesync(uint64(l))
}
return n
}
func (m *SpaceSettingsSnapshot) Size() (n int) {
if m == nil {
return 0
@ -2322,6 +2478,10 @@ func (m *SpaceSettingsSnapshot) Size() (n int) {
n += 1 + l + sovSpacesync(uint64(l))
}
}
l = len(m.DeleterPeerId)
if l > 0 {
n += 1 + l + sovSpacesync(uint64(l))
}
return n
}
@ -4146,6 +4306,41 @@ func (m *SpaceSettingsContent) Unmarshal(dAtA []byte) error {
}
m.Value = &SpaceSettingsContent_ObjectDelete{v}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SpaceDelete", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
v := &SpaceDelete{}
if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
m.Value = &SpaceSettingsContent_SpaceDelete{v}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSpacesync(dAtA[iNdEx:])
@ -4249,6 +4444,88 @@ func (m *ObjectDelete) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *SpaceDelete) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: SpaceDelete: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: SpaceDelete: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field DeleterPeerId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.DeleterPeerId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSpacesync(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthSpacesync
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *SpaceSettingsSnapshot) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@ -4310,6 +4587,38 @@ func (m *SpaceSettingsSnapshot) Unmarshal(dAtA []byte) error {
}
m.DeletedIds = append(m.DeletedIds, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field DeleterPeerId", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSpacesync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthSpacesync
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthSpacesync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.DeleterPeerId = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSpacesync(dAtA[iNdEx:])

View File

@ -213,6 +213,20 @@ func (mr *MockConfigurationMockRecorder) NodeIds(arg0 interface{}) *gomock.Call
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeIds", reflect.TypeOf((*MockConfiguration)(nil).NodeIds), arg0)
}
// NodeTypes mocks base method.
func (m *MockConfiguration) NodeTypes(arg0 string) []nodeconf.NodeType {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NodeTypes", arg0)
ret0, _ := ret[0].([]nodeconf.NodeType)
return ret0
}
// NodeTypes indicates an expected call of NodeTypes.
func (mr *MockConfigurationMockRecorder) NodeTypes(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeTypes", reflect.TypeOf((*MockConfiguration)(nil).NodeTypes), arg0)
}
// Partition mocks base method.
func (m *MockConfiguration) Partition(arg0 string) int {
m.ctrl.T.Helper()