143 lines
3.8 KiB
Go

package synctree
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
)
type UpdateListener interface {
Update(tree tree.ObjectTree)
Rebuild(tree tree.ObjectTree)
}
// SyncTree sends head updates to sync service and also sends new changes to update listener
type SyncTree struct {
tree.ObjectTree
syncService syncservice.SyncService
listener UpdateListener
}
func DeriveSyncTree(
ctx context.Context,
payload tree.ObjectTreeCreatePayload,
syncService syncservice.SyncService,
listener UpdateListener,
aclList list.ACLList,
createStorage storage.TreeStorageCreatorFunc) (t tree.ObjectTree, err error) {
t, err = tree.CreateDerivedObjectTree(payload, aclList, createStorage)
if err != nil {
return
}
t = &SyncTree{
ObjectTree: t,
syncService: syncService,
listener: listener,
}
err = syncService.NotifyHeadUpdate(ctx, t.ID(), t.Header(), &spacesyncproto.ObjectHeadUpdate{
Heads: t.Heads(),
SnapshotPath: t.SnapshotPath(),
})
return
}
func CreateSyncTree(
ctx context.Context,
payload tree.ObjectTreeCreatePayload,
syncService syncservice.SyncService,
listener UpdateListener,
aclList list.ACLList,
createStorage storage.TreeStorageCreatorFunc) (t tree.ObjectTree, err error) {
t, err = tree.CreateObjectTree(payload, aclList, createStorage)
if err != nil {
return
}
t = &SyncTree{
ObjectTree: t,
syncService: syncService,
listener: listener,
}
err = syncService.NotifyHeadUpdate(ctx, t.ID(), t.Header(), &spacesyncproto.ObjectHeadUpdate{
Heads: t.Heads(),
SnapshotPath: t.SnapshotPath(),
})
return
}
func BuildSyncTree(
ctx context.Context,
syncService syncservice.SyncService,
treeStorage storage.TreeStorage,
listener UpdateListener,
aclList list.ACLList) (t tree.ObjectTree, err error) {
return buildSyncTree(ctx, syncService, treeStorage, listener, aclList)
}
func buildSyncTree(
ctx context.Context,
syncService syncservice.SyncService,
treeStorage storage.TreeStorage,
listener UpdateListener,
aclList list.ACLList) (t tree.ObjectTree, err error) {
t, err = tree.BuildObjectTree(treeStorage, aclList)
if err != nil {
return
}
t = &SyncTree{
ObjectTree: t,
syncService: syncService,
listener: listener,
}
err = syncService.NotifyHeadUpdate(ctx, t.ID(), t.Header(), &spacesyncproto.ObjectHeadUpdate{
Heads: t.Heads(),
SnapshotPath: t.SnapshotPath(),
})
return
}
func (s *SyncTree) AddContent(ctx context.Context, content tree.SignableChangeContent) (res tree.AddResult, err error) {
res, err = s.AddContent(ctx, content)
if err != nil {
return
}
err = s.syncService.NotifyHeadUpdate(ctx, s.ID(), s.Header(), &spacesyncproto.ObjectHeadUpdate{
Heads: res.Heads,
Changes: res.Added,
SnapshotPath: s.SnapshotPath(),
})
return
}
func (s *SyncTree) AddRawChanges(ctx context.Context, changes ...*treechangeproto.RawTreeChangeWithId) (res tree.AddResult, err error) {
res, err = s.AddRawChanges(ctx, changes...)
if err != nil {
return
}
switch res.Mode {
case tree.Nothing:
return
case tree.Append:
s.listener.Update(s)
case tree.Rebuild:
s.listener.Rebuild(s)
}
err = s.syncService.NotifyHeadUpdate(ctx, s.ID(), s.Header(), &spacesyncproto.ObjectHeadUpdate{
Heads: res.Heads,
Changes: res.Added,
SnapshotPath: s.SnapshotPath(),
})
return
}
func (s *SyncTree) Tree() tree.ObjectTree {
return s
}