WIP more deletion checks

This commit is contained in:
mcrakhman 2022-11-12 17:49:25 +01:00 committed by Mikhail Iudin
parent 676976e7d3
commit a5fe46e50e
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0
6 changed files with 63 additions and 22 deletions

View File

@ -23,6 +23,8 @@ type Controller interface {
// CreateDocument creates new document in space // CreateDocument creates new document in space
CreateDocument(spaceId string) (id string, err error) CreateDocument(spaceId string) (id string, err error)
// DeleteDocument deletes a document from space
DeleteDocument(spaceId, documentId string) (err error)
// AllDocumentIds gets all ids of documents in space // AllDocumentIds gets all ids of documents in space
AllDocumentIds(spaceId string) (ids []string, err error) AllDocumentIds(spaceId string) (ids []string, err error)
// AddText adds text to space document // AddText adds text to space document
@ -97,6 +99,10 @@ func (c *controller) CreateDocument(spaceId string) (id string, err error) {
return c.docService.CreateDocument(spaceId) return c.docService.CreateDocument(spaceId)
} }
func (c *controller) DeleteDocument(spaceId, documentId string) (err error) {
return c.docService.DeleteDocument(spaceId, documentId)
}
func (c *controller) AllDocumentIds(spaceId string) (ids []string, err error) { func (c *controller) AllDocumentIds(spaceId string) (ids []string, err error) {
return c.docService.AllDocumentIds(spaceId) return c.docService.AllDocumentIds(spaceId)
} }

View File

@ -53,10 +53,18 @@ func (s *service) CreateDocument(spaceId string) (id string, err error) {
if err != nil { if err != nil {
return return
} }
id = doc.Tree().ID() id = doc.ID()
return return
} }
func (s *service) DeleteDocument(spaceId, documentId string) (err error) {
space, err := s.spaceService.GetSpace(context.Background(), spaceId)
if err != nil {
return
}
return space.DeleteTree(context.Background(), documentId)
}
func (s *service) AllDocumentIds(spaceId string) (ids []string, err error) { func (s *service) AllDocumentIds(spaceId string) (ids []string, err error) {
space, err := s.spaceService.GetSpace(context.Background(), spaceId) space, err := s.spaceService.GetSpace(context.Background(), spaceId)
if err != nil { if err != nil {
@ -79,5 +87,5 @@ func (s *service) DumpDocumentTree(spaceId, documentId string) (dump string, err
if err != nil { if err != nil {
return return
} }
return doc.Tree().DebugDump() return doc.DebugDump()
} }

View File

@ -69,10 +69,7 @@ func (d *diffService) HandleRangeRequest(ctx context.Context, req *spacesyncprot
} }
func (d *diffService) UpdateHeads(id string, heads []string) { func (d *diffService) UpdateHeads(id string, heads []string) {
d.diff.Set(ldiff.Element{ d.syncer.UpdateHeads(id, heads)
Id: id,
Head: concatStrings(heads),
})
} }
func (d *diffService) AllIds() []string { func (d *diffService) AllIds() []string {
@ -80,9 +77,6 @@ func (d *diffService) AllIds() []string {
} }
func (d *diffService) RemoveObjects(ids []string) { func (d *diffService) RemoveObjects(ids []string) {
for _, id := range ids {
d.diff.RemoveId(id)
}
d.syncer.RemoveObjects(ids) d.syncer.RemoveObjects(ids)
} }

View File

@ -18,6 +18,7 @@ import (
type DiffSyncer interface { type DiffSyncer interface {
Sync(ctx context.Context) error Sync(ctx context.Context) error
RemoveObjects(ids []string) RemoveObjects(ids []string)
UpdateHeads(id string, heads []string)
} }
func newDiffSyncer( func newDiffSyncer(
@ -56,10 +57,23 @@ func (d *diffSyncer) RemoveObjects(ids []string) {
d.Lock() d.Lock()
defer d.Unlock() defer d.Unlock()
for _, id := range ids { for _, id := range ids {
d.diff.RemoveId(id)
d.removedIds[id] = struct{}{} d.removedIds[id] = struct{}{}
} }
} }
func (d *diffSyncer) UpdateHeads(id string, heads []string) {
d.Lock()
defer d.Unlock()
if _, exists := d.removedIds[id]; exists {
return
}
d.diff.Set(ldiff.Element{
Id: id,
Head: concatStrings(heads),
})
}
func (d *diffSyncer) Sync(ctx context.Context) error { func (d *diffSyncer) Sync(ctx context.Context) error {
st := time.Now() st := time.Now()
// diffing with responsible peers according to configuration // diffing with responsible peers according to configuration

View File

@ -8,6 +8,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
"sync"
) )
type DeletionState int type DeletionState int
@ -19,7 +20,7 @@ const (
type SettingsDocument interface { type SettingsDocument interface {
tree.ObjectTree tree.ObjectTree
Init() Refresh()
DeleteObject(id string) (err error) DeleteObject(id string) (err error)
} }
@ -37,14 +38,15 @@ type Deps struct {
type settingsDocument struct { type settingsDocument struct {
tree.ObjectTree tree.ObjectTree
account account.Service account account.Service
spaceId string spaceId string
deletionState map[string]DeletionState deletionState map[string]DeletionState
treeGetter treegetter.TreeGetter treeGetter treegetter.TreeGetter
store spacestorage.SpaceStorage store spacestorage.SpaceStorage
lastChangeId string lastChangeId string
prov deletedIdsProvider prov deletedIdsProvider
removeNotifyFunc RemoveObjectsFunc removeNotifyFunc RemoveObjectsFunc
deletionStateLock sync.Mutex
} }
func NewSettingsDocument(ctx context.Context, deps Deps, spaceId string) (doc SettingsDocument, err error) { func NewSettingsDocument(ctx context.Context, deps Deps, spaceId string) (doc SettingsDocument, err error) {
@ -68,6 +70,14 @@ func NewSettingsDocument(ctx context.Context, deps Deps, spaceId string) (doc Se
return return
} }
func (s *settingsDocument) NotifyHeadsUpdate(id string) {
s.deletionStateLock.Lock()
if _, exists := s.deletionState[id]; exists {
s.deletionState[id] = DeletionStateQueued
}
s.deletionStateLock.Unlock()
}
func (s *settingsDocument) Update(tr tree.ObjectTree) { func (s *settingsDocument) Update(tr tree.ObjectTree) {
ids, lastId, err := s.prov.ProvideIds(tr, s.lastChangeId) ids, lastId, err := s.prov.ProvideIds(tr, s.lastChangeId)
if err != nil { if err != nil {
@ -86,7 +96,7 @@ func (s *settingsDocument) Rebuild(tr tree.ObjectTree) {
s.toBeDeleted(ids) s.toBeDeleted(ids)
} }
func (s *settingsDocument) Init() { func (s *settingsDocument) Refresh() {
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
s.Rebuild(s) s.Rebuild(s)
@ -94,26 +104,37 @@ func (s *settingsDocument) Init() {
func (s *settingsDocument) toBeDeleted(ids []string) { func (s *settingsDocument) toBeDeleted(ids []string) {
for _, id := range ids { for _, id := range ids {
s.deletionStateLock.Lock()
if state, exists := s.deletionState[id]; exists && state == DeletionStateDeleted { if state, exists := s.deletionState[id]; exists && state == DeletionStateDeleted {
s.deletionStateLock.Unlock()
continue continue
} }
// if not already deleted // if not already deleted
// TODO: here we can possibly have problems if the document is synced later, maybe we should block syncing with deleted documents
if _, err := s.store.TreeStorage(id); err == nil { if _, err := s.store.TreeStorage(id); err == nil {
s.deletionState[id] = DeletionStateQueued s.deletionState[id] = DeletionStateQueued
s.deletionStateLock.Unlock()
// doing this without lock
err := s.treeGetter.DeleteTree(context.Background(), s.spaceId, id) err := s.treeGetter.DeleteTree(context.Background(), s.spaceId, id)
if err != nil { if err != nil {
// TODO: some errors may tell us that the tree is actually deleted, so we should have more checks here // TODO: some errors may tell us that the tree is actually deleted, so we should have more checks here
// TODO: add logging // TODO: add logging
continue continue
} }
// TODO: add loop to double check that everything that should be deleted is actually deleted
s.deletionStateLock.Lock()
} }
s.deletionState[id] = DeletionStateDeleted s.deletionState[id] = DeletionStateDeleted
s.deletionStateLock.Unlock()
} }
// notifying about removal // notifying about removal
s.removeNotifyFunc(ids) s.removeNotifyFunc(ids)
} }
func (s *settingsDocument) DeleteObject(id string) (err error) { func (s *settingsDocument) DeleteObject(id string) (err error) {
s.Lock()
defer s.Unlock()
content := &spacesyncproto.SpaceSettingsContent_ObjectDelete{ content := &spacesyncproto.SpaceSettingsContent_ObjectDelete{
ObjectDelete: &spacesyncproto.ObjectDelete{Id: id}, ObjectDelete: &spacesyncproto.ObjectDelete{Id: id},
} }
@ -127,8 +148,6 @@ func (s *settingsDocument) DeleteObject(id string) (err error) {
if err != nil { if err != nil {
return return
} }
s.Lock()
defer s.Unlock()
_, err = s.AddContent(context.Background(), tree.SignableChangeContent{ _, err = s.AddContent(context.Background(), tree.SignableChangeContent{
Data: res, Data: res,
Key: s.account.Account().SignKey, Key: s.account.Account().SignKey,

View File

@ -156,7 +156,7 @@ func (s *space) Init(ctx context.Context) (err error) {
if err != nil { if err != nil {
return return
} }
s.settingsDocument.Init() s.settingsDocument.Refresh()
s.aclList = syncacl.NewSyncACL(aclList, s.syncService.StreamPool()) s.aclList = syncacl.NewSyncACL(aclList, s.syncService.StreamPool())
objectGetter := newCommonSpaceGetter(s.id, s.aclList, s.cache, s.settingsDocument) objectGetter := newCommonSpaceGetter(s.id, s.aclList, s.cache, s.settingsDocument)
s.syncService.Init(objectGetter) s.syncService.Init(objectGetter)