1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-10 18:10:54 +09:00

Update any-sync new deletion logic

This commit is contained in:
mcrakhman 2023-02-23 21:08:31 +01:00 committed by Mikhail Iudin
parent 8a38d54192
commit 73b27c7dac
No known key found for this signature in database
GPG key ID: FAAAA8BAABDFF1C0
9 changed files with 243 additions and 165 deletions

View file

@ -3,6 +3,7 @@ package settings
import (
"github.com/anytypeio/any-sync/commonspace/object/treegetter"
"github.com/anytypeio/any-sync/commonspace/settings/settingsstate"
"github.com/anytypeio/any-sync/util/slice"
"time"
)
@ -20,12 +21,16 @@ type DeletionManager interface {
func newDeletionManager(
spaceId string,
settingsId string,
isResponsible bool,
deletionInterval time.Duration,
deletionState settingsstate.ObjectDeletionState,
provider SpaceIdsProvider,
onSpaceDelete func()) DeletionManager {
return &deletionManager{
isResponsible: isResponsible,
spaceId: spaceId,
settingsId: settingsId,
deletionState: deletionState,
provider: provider,
deletionInterval: deletionInterval,
@ -39,6 +44,8 @@ type deletionManager struct {
treeGetter treegetter.TreeGetter
deletionInterval time.Duration
spaceId string
settingsId string
isResponsible bool
onSpaceDelete func()
}
@ -47,15 +54,18 @@ func (d *deletionManager) UpdateState(state *settingsstate.State) (err error) {
if err != nil {
log.Warn("failed to add deleted ids to deletion state")
}
if !state.SpaceDeletionDate.IsZero() {
if state.DeleterId != "" {
spaceDeleter, ok := d.treeGetter.(SpaceDeleter)
if ok {
spaceDeleter.DeleteSpace(d.spaceId)
}
if state.SpaceDeletionDate.Add(d.deletionInterval).Before(time.Now()) {
err = d.deletionState.Add(d.provider.AllIds()) // todo: except deletion tree
// todo: compaction in pogreb
d.onSpaceDelete()
d.onSpaceDelete()
if d.isResponsible {
allIds := slice.DiscardFromSlice(d.provider.AllIds(), func(s string) bool {
return s == d.settingsId
})
err = d.deletionState.Add(allIds)
}
}
return

View file

@ -9,10 +9,15 @@ import (
"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/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"
"time"
)
@ -24,16 +29,16 @@ type SettingsObject interface {
synctree.SyncTree
Init(ctx context.Context) (err error)
DeleteObject(id string) (err error)
DeleteSpace(t time.Time) (err error)
RestoreSpace() (err error)
DeleteSpace(ctx context.Context, deleterId string, raw *treechangeproto.RawTreeChangeWithId) (err error)
SpaceDeleteRawChange(deleterId string) (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")
ErrMarkedDeleted = errors.New("this space is already marked deleted")
ErrMarkedNotDeleted = errors.New("this space is not marked not deleted")
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")
ErrIncorrectDeleteChange = errors.New("incorrect delete change")
)
type BuildTreeFunc func(ctx context.Context, id string, listener updatelistener.UpdateListener) (t synctree.SyncTree, err error)
@ -43,6 +48,7 @@ type Deps struct {
Account accountservice.Service
TreeGetter treegetter.TreeGetter
Store spacestorage.SpaceStorage
Configuration nodeconf.Configuration
DeletionState settingsstate.ObjectDeletionState
Provider SpaceIdsProvider
OnSpaceDelete func()
@ -82,7 +88,14 @@ func NewSettingsObject(deps Deps, spaceId string) (obj SettingsObject) {
deleter = deps.del
}
if deps.delManager == nil {
deletionManager = newDeletionManager(spaceId, spaceDeletionInterval, deps.DeletionState, deps.Provider, deps.OnSpaceDelete)
deletionManager = newDeletionManager(
spaceId,
deps.Store.SpaceSettingsId(),
deps.Configuration.IsResponsible(spaceId),
spaceDeletionInterval,
deps.DeletionState,
deps.Provider,
deps.OnSpaceDelete)
} else {
deletionManager = deps.delManager
}
@ -160,36 +173,39 @@ func (s *settingsObject) Close() error {
return s.SyncTree.Close()
}
func (s *settingsObject) DeleteSpace(t time.Time) (err error) {
func (s *settingsObject) DeleteSpace(ctx context.Context, deleterId string, raw *treechangeproto.RawTreeChangeWithId) (err error) {
s.Lock()
defer s.Unlock()
if !s.state.SpaceDeletionDate.IsZero() {
return ErrMarkedDeleted
}
// TODO: add snapshot logic
res, err := s.changeFactory.CreateSpaceDeleteChange(t, s.state, false)
err = s.verifyDeleteSpace(deleterId, raw)
if err != nil {
return
}
return s.addContent(res)
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) {
return ErrCantDeleteSpace
}
return
}
func (s *settingsObject) RestoreSpace() (err error) {
s.Lock()
defer s.Unlock()
if s.state.SpaceDeletionDate.IsZero() {
return ErrMarkedNotDeleted
}
// TODO: add snapshot logic
res, err := s.changeFactory.CreateSpaceRestoreChange(s.state, false)
func (s *settingsObject) SpaceDeleteRawChange(deleterId string) (raw *treechangeproto.RawTreeChangeWithId, err error) {
data, err := s.changeFactory.CreateSpaceDeleteChange(deleterId, s.state, false)
if err != nil {
return
}
return s.addContent(res)
accountData := s.account.Account()
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) {
@ -218,6 +234,24 @@ func (s *settingsObject) DeleteObject(id string) (err error) {
return s.addContent(res)
}
func (s *settingsObject) verifyDeleteSpace(peerId string, 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() != peerId {
return ErrIncorrectDeleteChange
}
return
}
func (s *settingsObject) addContent(data []byte) (err error) {
accountData := s.account.Account()
_, err = s.AddContent(context.Background(), objecttree.SignableChangeContent{

View file

@ -2,13 +2,11 @@ package settingsstate
import (
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"time"
)
type ChangeFactory interface {
CreateObjectDeleteChange(id string, state *State, isSnapshot bool) (res []byte, err error)
CreateSpaceDeleteChange(t time.Time, state *State, isSnapshot bool) (res []byte, err error)
CreateSpaceRestoreChange(state *State, isSnapshot bool) (res []byte, err error)
CreateSpaceDeleteChange(peerId string, state *State, isSnapshot bool) (res []byte, err error)
}
func NewChangeFactory() ChangeFactory {
@ -33,24 +31,9 @@ func (c *changeFactory) CreateObjectDeleteChange(id string, state *State, isSnap
return
}
func (c *changeFactory) CreateSpaceDeleteChange(t time.Time, state *State, isSnapshot bool) (res []byte, err error) {
func (c *changeFactory) CreateSpaceDeleteChange(peerId string, state *State, isSnapshot bool) (res []byte, err error) {
content := &spacesyncproto.SpaceSettingsContent_SpaceDelete{
SpaceDelete: &spacesyncproto.SpaceDelete{Timestamp: t.UnixNano()},
}
change := &spacesyncproto.SettingsData{
Content: []*spacesyncproto.SpaceSettingsContent{
{Value: content},
},
Snapshot: nil,
}
// TODO: add snapshot logic
res, err = change.Marshal()
return
}
func (c *changeFactory) CreateSpaceRestoreChange(state *State, isSnapshot bool) (res []byte, err error) {
content := &spacesyncproto.SpaceSettingsContent_SpaceDelete{
SpaceDelete: &spacesyncproto.SpaceDelete{},
SpaceDelete: &spacesyncproto.SpaceDelete{DeleterPeerId: peerId},
}
change := &spacesyncproto.SettingsData{
Content: []*spacesyncproto.SpaceSettingsContent{

View file

@ -1,9 +1,7 @@
package settingsstate
import "time"
type State struct {
DeletedIds []string
SpaceDeletionDate time.Time
LastIteratedId string
DeletedIds []string
DeleterId string
LastIteratedId string
}

View file

@ -4,7 +4,6 @@ import (
"github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
"github.com/gogo/protobuf/proto"
"time"
)
type StateBuilder interface {
@ -59,9 +58,9 @@ func (s *stateBuilder) processChange(change *objecttree.Change, rootId, startId
// getting data from snapshot if we start from it
if change.Id == rootId {
state = &State{
DeletedIds: deleteChange.Snapshot.DeletedIds,
SpaceDeletionDate: time.Unix(0, deleteChange.Snapshot.SpaceDeletionTimestamp),
LastIteratedId: rootId,
DeletedIds: deleteChange.Snapshot.DeletedIds,
DeleterId: deleteChange.Snapshot.DeleterPeerId,
LastIteratedId: rootId,
}
return state
}
@ -72,7 +71,7 @@ func (s *stateBuilder) processChange(change *objecttree.Change, rootId, startId
case cnt.GetObjectDelete() != nil:
state.DeletedIds = append(state.DeletedIds, cnt.GetObjectDelete().GetId())
case cnt.GetSpaceDelete() != nil:
state.SpaceDeletionDate = time.Unix(0, cnt.GetSpaceDelete().GetTimestamp())
state.DeleterId = cnt.GetSpaceDelete().GetDeleterPeerId()
}
}
return state