From 8729d069dcb69e34ca8bb07835073c611b92c9f0 Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Wed, 29 Mar 2023 23:06:51 +0200 Subject: [PATCH] Add settings snapshot logic --- .../mock_objecttree/mock_objecttree.go | 14 +++++++++++++ .../object/tree/objecttree/objecttree.go | 5 +++++ commonspace/object/tree/objecttree/util.go | 14 +++++++++++++ .../synctree/mock_synctree/mock_synctree.go | 14 +++++++++++++ commonspace/settings/settings.go | 13 ++++++------ .../settings/settingsstate/changefactory.go | 21 +++++++++++++++---- 6 files changed, 71 insertions(+), 10 deletions(-) diff --git a/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go b/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go index fb5ea6b1..e2ebe8e0 100644 --- a/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go +++ b/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go @@ -258,6 +258,20 @@ func (mr *MockObjectTreeMockRecorder) IterateRoot(arg0, arg1 interface{}) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateRoot", reflect.TypeOf((*MockObjectTree)(nil).IterateRoot), arg0, arg1) } +// Len mocks base method. +func (m *MockObjectTree) Len() int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Len") + ret0, _ := ret[0].(int) + return ret0 +} + +// Len indicates an expected call of Len. +func (mr *MockObjectTreeMockRecorder) Len() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Len", reflect.TypeOf((*MockObjectTree)(nil).Len)) +} + // Lock mocks base method. func (m *MockObjectTree) Lock() { m.ctrl.T.Helper() diff --git a/commonspace/object/tree/objecttree/objecttree.go b/commonspace/object/tree/objecttree/objecttree.go index f455b150..430329c2 100644 --- a/commonspace/object/tree/objecttree/objecttree.go +++ b/commonspace/object/tree/objecttree/objecttree.go @@ -57,6 +57,7 @@ type ReadableObjectTree interface { ChangeInfo() *treechangeproto.TreeChangeInfo Heads() []string Root() *Change + Len() int AclList() list.AclList @@ -135,6 +136,10 @@ func (ot *objectTree) Id() string { return ot.id } +func (ot *objectTree) Len() int { + return ot.tree.Len() +} + func (ot *objectTree) AclList() list.AclList { return ot.aclList } diff --git a/commonspace/object/tree/objecttree/util.go b/commonspace/object/tree/objecttree/util.go index 2e960233..70911364 100644 --- a/commonspace/object/tree/objecttree/util.go +++ b/commonspace/object/tree/objecttree/util.go @@ -3,6 +3,7 @@ package objecttree import ( "fmt" "github.com/anytypeio/any-sync/util/crypto" + "math/rand" ) func commonSnapshotForTwoPaths(ourPath []string, theirPath []string) (string, error) { @@ -40,3 +41,16 @@ func deriveTreeKey(key crypto.SymKey, cid string) (crypto.SymKey, error) { } return crypto.DeriveSymmetricKey(raw, fmt.Sprintf(crypto.AnysyncTreePath, cid)) } + +func DoSnapshot(treeLen int) bool { + if treeLen <= 100 { + return false + } + + var ( + delta = treeLen/50 + 1 + midPoint = 1000 + val = rand.Intn(midPoint * 2) + ) + return midPoint-delta <= val && val <= midPoint+delta +} diff --git a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go index 1dee0ce3..3ab6cf1b 100644 --- a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go +++ b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go @@ -383,6 +383,20 @@ func (mr *MockSyncTreeMockRecorder) IterateRoot(arg0, arg1 interface{}) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IterateRoot", reflect.TypeOf((*MockSyncTree)(nil).IterateRoot), arg0, arg1) } +// Len mocks base method. +func (m *MockSyncTree) Len() int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Len") + ret0, _ := ret[0].(int) + return ret0 +} + +// Len indicates an expected call of Len. +func (mr *MockSyncTreeMockRecorder) Len() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Len", reflect.TypeOf((*MockSyncTree)(nil).Len)) +} + // Lock mocks base method. func (m *MockSyncTree) Lock() { m.ctrl.T.Helper() diff --git a/commonspace/settings/settings.go b/commonspace/settings/settings.go index 42bd88ed..1455faff 100644 --- a/commonspace/settings/settings.go +++ b/commonspace/settings/settings.go @@ -40,6 +40,8 @@ var ( ErrCantDeleteSpace = errors.New("not able to delete space") ) +var doSnapshot = objecttree.DoSnapshot + type BuildTreeFunc func(ctx context.Context, id string, listener updatelistener.UpdateListener) (t synctree.SyncTree, err error) type Deps struct { @@ -228,14 +230,13 @@ func (s *settingsObject) DeleteObject(id string) (err error) { err = ErrObjDoesNotExist return } - - // TODO: add snapshot logic - res, err := s.changeFactory.CreateObjectDeleteChange(id, s.state, false) + isSnapshot := doSnapshot(s.Len()) + res, err := s.changeFactory.CreateObjectDeleteChange(id, s.state, isSnapshot) if err != nil { return } - return s.addContent(res) + return s.addContent(res, isSnapshot) } func (s *settingsObject) verifyDeleteSpace(raw *treechangeproto.RawTreeChangeWithId) (err error) { @@ -246,12 +247,12 @@ func (s *settingsObject) verifyDeleteSpace(raw *treechangeproto.RawTreeChangeWit return verifyDeleteContent(data, "") } -func (s *settingsObject) addContent(data []byte) (err error) { +func (s *settingsObject) addContent(data []byte, isSnapshot bool) (err error) { accountData := s.account.Account() _, err = s.AddContent(context.Background(), objecttree.SignableChangeContent{ Data: data, Key: accountData.SignKey, - IsSnapshot: false, + IsSnapshot: isSnapshot, IsEncrypted: false, }) if err != nil { diff --git a/commonspace/settings/settingsstate/changefactory.go b/commonspace/settings/settingsstate/changefactory.go index df3da76b..fc379097 100644 --- a/commonspace/settings/settingsstate/changefactory.go +++ b/commonspace/settings/settingsstate/changefactory.go @@ -24,9 +24,10 @@ func (c *changeFactory) CreateObjectDeleteChange(id string, state *State, isSnap Content: []*spacesyncproto.SpaceSettingsContent{ {Value: content}, }, - Snapshot: nil, } - // TODO: add snapshot logic + if isSnapshot { + change.Snapshot = c.makeSnapshot(state, id, "") + } res, err = change.Marshal() return } @@ -39,9 +40,21 @@ func (c *changeFactory) CreateSpaceDeleteChange(peerId string, state *State, isS Content: []*spacesyncproto.SpaceSettingsContent{ {Value: content}, }, - Snapshot: nil, } - // TODO: add snapshot logic + if isSnapshot { + change.Snapshot = c.makeSnapshot(state, "", peerId) + } res, err = change.Marshal() return } + +func (c *changeFactory) makeSnapshot(state *State, objectId, deleterPeer string) *spacesyncproto.SpaceSettingsSnapshot { + deletedIds := state.DeletedIds + if objectId != "" { + deletedIds = append(deletedIds, objectId) + } + return &spacesyncproto.SpaceSettingsSnapshot{ + DeletedIds: deletedIds, + DeleterPeerId: deleterPeer, + } +}