WIP new document logic

This commit is contained in:
mcrakhman 2022-07-16 14:24:27 +02:00
parent d120da8000
commit d9452509b5
No known key found for this signature in database
GPG Key ID: DED12CFEF5B8396B
3 changed files with 65 additions and 20 deletions

View File

@ -46,6 +46,7 @@ var ErrNoCommonSnapshot = errors.New("trees doesn't have a common snapshot")
type ACLTree interface { type ACLTree interface {
RWLocker RWLocker
ID() string
ACLState() *ACLState ACLState() *ACLState
AddContent(ctx context.Context, f func(builder ChangeBuilder) error) (*Change, error) AddContent(ctx context.Context, f func(builder ChangeBuilder) error) (*Change, error)
AddRawChanges(ctx context.Context, changes ...*aclpb.RawChange) (AddResult, error) AddRawChanges(ctx context.Context, changes ...*aclpb.RawChange) (AddResult, error)
@ -65,6 +66,7 @@ type aclTree struct {
accountData *account.AccountData accountData *account.AccountData
updateListener TreeUpdateListener updateListener TreeUpdateListener
id string
fullTree *Tree fullTree *Tree
aclTreeFromStart *Tree // TODO: right now we don't use it, we can probably have only local var for now. This tree is built from start of the document aclTreeFromStart *Tree // TODO: right now we don't use it, we can probably have only local var for now. This tree is built from start of the document
aclState *ACLState aclState *ACLState
@ -112,6 +114,10 @@ func BuildACLTree(
if err != nil { if err != nil {
return nil, err return nil, err
} }
aclTree.id, err = t.TreeID()
if err != nil {
return nil, err
}
listener.Rebuild(aclTree) listener.Rebuild(aclTree)
@ -214,6 +220,10 @@ func (a *aclTree) rebuildFromStorage(fromStart bool) error {
return nil return nil
} }
func (a *aclTree) ID() string {
return a.id
}
func (a *aclTree) ACLState() *ACLState { func (a *aclTree) ACLState() *ACLState {
return a.aclState return a.aclState
} }
@ -400,13 +410,25 @@ func (a *aclTree) SnapshotPath() []string {
func (a *aclTree) ChangesAfterCommonSnapshot(theirPath []string) ([]*aclpb.RawChange, error) { func (a *aclTree) ChangesAfterCommonSnapshot(theirPath []string) ([]*aclpb.RawChange, error) {
// TODO: think about when the clients will have their full acl tree and thus full snapshots // TODO: think about when the clients will have their full acl tree and thus full snapshots
// but no changes after some of the snapshots // but no changes after some of the snapshots
commonSnapshot, err := a.commonSnapshotForTwoPaths(a.SnapshotPath(), theirPath)
if err != nil { var (
return nil, err isNewDocument = len(theirPath) != 0
ourPath = a.SnapshotPath()
// by default returning everything we have
commonSnapshot = ourPath[len(ourPath)-1] // TODO: root snapshot, probably it is better to have a specific method in treestorage
err error
)
// if this is non-empty request
if !isNewDocument {
commonSnapshot, err = a.commonSnapshotForTwoPaths(ourPath, theirPath)
if err != nil {
return nil, err
}
} }
// we presume that we have everything after the common snapshot, though this may not be the case in case of clients and only ACL tree changes var rawChanges []*aclpb.RawChange
changes, err := a.treeBuilder.dfs(a.fullTree.Heads(), commonSnapshot, func(id string) (*Change, error) { // using custom load function to skip verification step and save raw changes
// using custom load function to skip verification step and save raw changes load := func(id string) (*Change, error) {
raw, err := a.treeStorage.GetChange(context.Background(), id) raw, err := a.treeStorage.GetChange(context.Background(), id)
if err != nil { if err != nil {
return nil, err return nil, err
@ -418,16 +440,21 @@ func (a *aclTree) ChangesAfterCommonSnapshot(theirPath []string) ([]*aclpb.RawCh
} }
ch := NewChange(id, aclChange) ch := NewChange(id, aclChange)
ch.Raw = raw rawChanges = append(rawChanges, raw)
return ch, nil return ch, nil
}) }
// we presume that we have everything after the common snapshot, though this may not be the case in case of clients and only ACL tree changes
_, err = a.treeBuilder.dfs(a.fullTree.Heads(), commonSnapshot, load)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var rawChanges []*aclpb.RawChange if isNewDocument {
for _, ch := range changes { _, err = load(commonSnapshot)
rawChanges = append(rawChanges, ch.Raw) if err != nil {
return nil, err
}
} }
return rawChanges, nil return rawChanges, nil
} }

View File

@ -6,6 +6,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/client" "github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/client"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/syncpb" "github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/syncpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache" "github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache"
@ -15,6 +16,7 @@ import (
type requestHandler struct { type requestHandler struct {
treeCache treecache.Service treeCache treecache.Service
client client.Client client client.Client
account account.Service
} }
func NewRequestHandler() app.Component { func NewRequestHandler() app.Component {
@ -31,6 +33,8 @@ const CName = "SyncRequestHandler"
func (r *requestHandler) Init(ctx context.Context, a *app.App) (err error) { func (r *requestHandler) Init(ctx context.Context, a *app.App) (err error) {
r.treeCache = a.MustComponent(treecache.CName).(treecache.Service) r.treeCache = a.MustComponent(treecache.CName).(treecache.Service)
r.client = a.MustComponent(client.CName).(client.Client)
r.account = a.MustComponent(account.CName).(account.Service)
return nil return nil
} }
@ -102,9 +106,12 @@ func (r *requestHandler) HandleFullSyncRequest(ctx context.Context, senderId str
err = r.treeCache.Do(ctx, request.TreeId, func(tree acltree.ACLTree) error { err = r.treeCache.Do(ctx, request.TreeId, func(tree acltree.ACLTree) error {
// TODO: check if we already have those changes // TODO: check if we already have those changes
result, err = tree.AddRawChanges(ctx, request.Changes...) // if we have non empty request
if err != nil { if len(request.Heads) != 0 {
return err result, err = tree.AddRawChanges(ctx, request.Changes...)
if err != nil {
return err
}
} }
snapshotPath = tree.SnapshotPath() snapshotPath = tree.SnapshotPath()
fullResponse, err = r.prepareFullSyncResponse(request.TreeId, request.SnapshotPath, request.Changes, tree) fullResponse, err = r.prepareFullSyncResponse(request.TreeId, request.SnapshotPath, request.Changes, tree)
@ -132,23 +139,24 @@ func (r *requestHandler) HandleFullSyncRequest(ctx context.Context, senderId str
return r.client.NotifyHeadsChanged(newUpdate) return r.client.NotifyHeadsChanged(newUpdate)
} }
func (r *requestHandler) HandleFullSyncResponse(ctx context.Context, senderId string, request *syncpb.SyncFullRequest) (err error) { func (r *requestHandler) HandleFullSyncResponse(ctx context.Context, senderId string, response *syncpb.SyncFullResponse) (err error) {
var ( var (
snapshotPath []string snapshotPath []string
result acltree.AddResult result acltree.AddResult
) )
err = r.treeCache.Do(ctx, request.TreeId, func(tree acltree.ACLTree) error { err = r.treeCache.Do(ctx, response.TreeId, func(tree acltree.ACLTree) error {
// TODO: check if we already have those changes // TODO: check if we already have those changes
result, err = tree.AddRawChanges(ctx, request.Changes...) result, err = tree.AddRawChanges(ctx, response.Changes...)
if err != nil { if err != nil {
return err return err
} }
snapshotPath = tree.SnapshotPath() snapshotPath = tree.SnapshotPath()
return nil return nil
}) })
if err != nil { if err == treestorage.ErrUnknownTreeId {
return err // TODO: probably sometimes we should notify about this (e.g. if client created new document)
return r.createTree(response)
} }
// if error or nothing has changed // if error or nothing has changed
if err != nil || len(result.Added) == 0 { if err != nil || len(result.Added) == 0 {
@ -161,7 +169,7 @@ func (r *requestHandler) HandleFullSyncResponse(ctx context.Context, senderId st
Heads: result.Heads, Heads: result.Heads,
Changes: result.Added, Changes: result.Added,
SnapshotPath: snapshotPath, SnapshotPath: snapshotPath,
TreeId: request.TreeId, TreeId: response.TreeId,
} }
return r.client.NotifyHeadsChanged(newUpdate) return r.client.NotifyHeadsChanged(newUpdate)
} }
@ -205,3 +213,8 @@ func (r *requestHandler) prepareFullSyncResponse(treeId string, theirPath []stri
SnapshotPath: tree.SnapshotPath(), SnapshotPath: tree.SnapshotPath(),
}, nil }, nil
} }
func (r *requestHandler) createTree(response *syncpb.SyncFullResponse) error {
// TODO: write create tree functionality
return nil
}

View File

@ -13,6 +13,7 @@ const CName = "treecache"
type Service interface { type Service interface {
Do(ctx context.Context, treeId string, f func(tree acltree.ACLTree) error) error Do(ctx context.Context, treeId string, f func(tree acltree.ACLTree) error) error
Add(ctx context.Context, treeId string, tree acltree.ACLTree) error
} }
type service struct { type service struct {
@ -37,6 +38,10 @@ func (s *service) Do(ctx context.Context, treeId string, f func(tree acltree.ACL
return f(tree.(acltree.ACLTree)) return f(tree.(acltree.ACLTree))
} }
func (s *service) Add(ctx context.Context, treeId string, tree acltree.ACLTree) error {
return s.cache.Add(treeId, tree)
}
func (s *service) Init(ctx context.Context, a *app.App) (err error) { func (s *service) Init(ctx context.Context, a *app.App) (err error) {
s.cache = ocache.New(s.loadTree) s.cache = ocache.New(s.loadTree)
s.account = a.MustComponent(account.CName).(account.Service) s.account = a.MustComponent(account.CName).(account.Service)