WIP new document logic
This commit is contained in:
parent
d120da8000
commit
d9452509b5
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user