Change deletion logic
This commit is contained in:
parent
035a2fc1e6
commit
cb2f64f0d5
@ -8,14 +8,6 @@ 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
|
|
||||||
|
|
||||||
const (
|
|
||||||
DeletionStateQueued DeletionState = iota
|
|
||||||
DeletionStateDeleted
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SettingsDocument interface {
|
type SettingsDocument interface {
|
||||||
@ -41,23 +33,24 @@ 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
|
treeGetter treegetter.TreeGetter
|
||||||
treeGetter treegetter.TreeGetter
|
store spacestorage.SpaceStorage
|
||||||
store spacestorage.SpaceStorage
|
prov deletedIdsProvider
|
||||||
lastChangeId string
|
removeNotifyFunc RemoveObjectsFunc
|
||||||
prov deletedIdsProvider
|
buildFunc BuildTreeFunc
|
||||||
removeNotifyFunc RemoveObjectsFunc
|
|
||||||
buildFunc BuildTreeFunc
|
queue *settingsQueue
|
||||||
deletionStateLock sync.Mutex
|
documentIds []string
|
||||||
|
lastChangeId string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSettingsDocument(deps Deps, spaceId string) (doc SettingsDocument, err error) {
|
func NewSettingsDocument(deps Deps, spaceId string) (doc SettingsDocument, err error) {
|
||||||
s := &settingsDocument{
|
s := &settingsDocument{
|
||||||
account: deps.Account,
|
account: deps.Account,
|
||||||
spaceId: spaceId,
|
spaceId: spaceId,
|
||||||
deletionState: map[string]DeletionState{},
|
queue: newSettingsQueue(),
|
||||||
treeGetter: deps.TreeGetter,
|
treeGetter: deps.TreeGetter,
|
||||||
store: deps.Store,
|
store: deps.Store,
|
||||||
removeNotifyFunc: deps.RemoveFunc,
|
removeNotifyFunc: deps.RemoveFunc,
|
||||||
@ -73,12 +66,7 @@ func NewSettingsDocument(deps Deps, spaceId string) (doc SettingsDocument, err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *settingsDocument) NotifyObjectUpdate(id string) {
|
func (s *settingsDocument) NotifyObjectUpdate(id string) {
|
||||||
s.deletionStateLock.Lock()
|
s.queue.queueIfDeleted(id)
|
||||||
if state, exists := s.deletionState[id]; exists && state == DeletionStateDeleted {
|
|
||||||
// marking the document as queued, that means that document appeared later than we checked the storage for deletion
|
|
||||||
s.deletionState[id] = DeletionStateQueued
|
|
||||||
}
|
|
||||||
s.deletionStateLock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *settingsDocument) Update(tr tree.ObjectTree) {
|
func (s *settingsDocument) Update(tr tree.ObjectTree) {
|
||||||
@ -86,8 +74,10 @@ func (s *settingsDocument) Update(tr tree.ObjectTree) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.documentIds = append(s.documentIds, ids...)
|
||||||
s.lastChangeId = lastId
|
s.lastChangeId = lastId
|
||||||
s.toBeDeleted(ids)
|
s.queue.add(ids)
|
||||||
|
s.deleteQueued()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *settingsDocument) Rebuild(tr tree.ObjectTree) {
|
func (s *settingsDocument) Rebuild(tr tree.ObjectTree) {
|
||||||
@ -95,8 +85,10 @@ func (s *settingsDocument) Rebuild(tr tree.ObjectTree) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.documentIds = ids
|
||||||
s.lastChangeId = lastId
|
s.lastChangeId = lastId
|
||||||
s.toBeDeleted(ids)
|
s.queue.add(ids)
|
||||||
|
s.deleteQueued()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *settingsDocument) Init(ctx context.Context) (err error) {
|
func (s *settingsDocument) Init(ctx context.Context) (err error) {
|
||||||
@ -107,40 +99,35 @@ func (s *settingsDocument) Init(ctx context.Context) (err error) {
|
|||||||
func (s *settingsDocument) Refresh() {
|
func (s *settingsDocument) Refresh() {
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
s.Rebuild(s)
|
if s.lastChangeId == "" {
|
||||||
|
s.Rebuild(s)
|
||||||
|
} else {
|
||||||
|
s.deleteQueued()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *settingsDocument) toBeDeleted(ids []string) {
|
func (s *settingsDocument) deleteQueued() {
|
||||||
for _, id := range ids {
|
allQueued := s.queue.getQueued()
|
||||||
s.deletionStateLock.Lock()
|
for _, id := range allQueued {
|
||||||
if state, exists := s.deletionState[id]; exists && state == DeletionStateDeleted {
|
|
||||||
s.deletionStateLock.Unlock()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// if the document is not in storage it can happen that it will appear later, for that we have NotifyObjectUpdate method
|
|
||||||
if _, err := s.store.TreeStorage(id); err == nil {
|
if _, err := s.store.TreeStorage(id); err == nil {
|
||||||
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
|
||||||
}
|
}
|
||||||
s.deletionStateLock.Lock()
|
|
||||||
}
|
}
|
||||||
|
s.queue.delete(id)
|
||||||
s.deletionState[id] = DeletionStateDeleted
|
|
||||||
s.deletionStateLock.Unlock()
|
|
||||||
}
|
}
|
||||||
// notifying diff service that the ids should not be synced anymore
|
|
||||||
s.removeNotifyFunc(ids)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *settingsDocument) DeleteObject(id string) (err error) {
|
func (s *settingsDocument) DeleteObject(id string) (err error) {
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
|
if s.queue.exists(id) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
content := &spacesyncproto.SpaceSettingsContent_ObjectDelete{
|
content := &spacesyncproto.SpaceSettingsContent_ObjectDelete{
|
||||||
ObjectDelete: &spacesyncproto.ObjectDelete{Id: id},
|
ObjectDelete: &spacesyncproto.ObjectDelete{Id: id},
|
||||||
}
|
}
|
||||||
|
|||||||
69
common/commonspace/settingsdocument/settingsqueue.go
Normal file
69
common/commonspace/settingsdocument/settingsqueue.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package settingsdocument
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type settingsQueue struct {
|
||||||
|
sync.Mutex
|
||||||
|
queued map[string]struct{}
|
||||||
|
deleted map[string]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSettingsQueue() *settingsQueue {
|
||||||
|
return &settingsQueue{
|
||||||
|
Mutex: sync.Mutex{},
|
||||||
|
queued: map[string]struct{}{},
|
||||||
|
deleted: map[string]struct{}{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *settingsQueue) add(ids []string) {
|
||||||
|
q.Lock()
|
||||||
|
defer q.Unlock()
|
||||||
|
for _, id := range ids {
|
||||||
|
if _, exists := q.deleted[id]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, exists := q.queued[id]; exists {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
q.queued[id] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *settingsQueue) getQueued() (ids []string) {
|
||||||
|
q.Lock()
|
||||||
|
defer q.Unlock()
|
||||||
|
ids = make([]string, 0, len(q.queued))
|
||||||
|
for id := range q.queued {
|
||||||
|
ids = append(ids, id)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *settingsQueue) delete(id string) {
|
||||||
|
q.Lock()
|
||||||
|
defer q.Unlock()
|
||||||
|
delete(q.queued, id)
|
||||||
|
q.deleted[id] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *settingsQueue) queueIfDeleted(id string) {
|
||||||
|
q.Lock()
|
||||||
|
defer q.Unlock()
|
||||||
|
if _, exists := q.deleted[id]; exists {
|
||||||
|
delete(q.deleted, id)
|
||||||
|
q.queued[id] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *settingsQueue) exists(id string) bool {
|
||||||
|
q.Lock()
|
||||||
|
defer q.Unlock()
|
||||||
|
if _, exists := q.deleted[id]; exists {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if _, exists := q.queued[id]; exists {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user