Create new tree logic

This commit is contained in:
mcrakhman 2022-07-17 13:34:07 +02:00 committed by Mikhail Iudin
parent 9d106fee5b
commit 65114e2ea9
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0
13 changed files with 335 additions and 92 deletions

View File

@ -25,12 +25,13 @@ protos-go:
@$(eval P_TIMESTAMP := Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types) @$(eval P_TIMESTAMP := Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types)
@$(eval P_STRUCT := Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types) @$(eval P_STRUCT := Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types)
@$(eval P_ACL_CHANGES := M$(P_ACL_CHANGES_PATH_PB)/protos/aclchanges.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_ACL_CHANGES_PATH_PB)) @$(eval P_ACL_CHANGES := M$(P_ACL_CHANGES_PATH_PB)/protos/aclchanges.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_ACL_CHANGES_PATH_PB))
@$(eval P_TREE_CHANGES := M$(P_TREE_STORAGE_PATH_PB)/protos/tree.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_TREE_STORAGE_PATH_PB))
# use if needed $(eval PKGMAP := $$(P_TIMESTAMP),$$(P_STRUCT)) # use if needed $(eval PKGMAP := $$(P_TIMESTAMP),$$(P_STRUCT))
$(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_CHANGES_PATH_PB)/protos/*.proto; mv $(P_ACL_CHANGES_PATH_PB)/protos/*.go $(P_ACL_CHANGES_PATH_PB) $(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_CHANGES_PATH_PB)/protos/*.proto; mv $(P_ACL_CHANGES_PATH_PB)/protos/*.go $(P_ACL_CHANGES_PATH_PB)
$(GOGO_START) protoc --gogofaster_out=:. $(P_TREE_STORAGE_PATH_PB)/protos/*.proto; mv $(P_TREE_STORAGE_PATH_PB)/protos/*.go $(P_TREE_STORAGE_PATH_PB) $(GOGO_START) protoc --gogofaster_out=:. $(P_TREE_STORAGE_PATH_PB)/protos/*.proto; mv $(P_TREE_STORAGE_PATH_PB)/protos/*.go $(P_TREE_STORAGE_PATH_PB)
$(GOGO_START) protoc --gogofaster_out=:. $(P_PLAINTEXT_CHANGES_PATH_PB)/protos/*.proto; mv $(P_PLAINTEXT_CHANGES_PATH_PB)/protos/*.go $(P_PLAINTEXT_CHANGES_PATH_PB) $(GOGO_START) protoc --gogofaster_out=:. $(P_PLAINTEXT_CHANGES_PATH_PB)/protos/*.proto; mv $(P_PLAINTEXT_CHANGES_PATH_PB)/protos/*.go $(P_PLAINTEXT_CHANGES_PATH_PB)
$(eval PKGMAP := $$(P_ACL_CHANGES)) $(eval PKGMAP := $$(P_ACL_CHANGES),$$(P_TREE_CHANGES))
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. $(P_SYNC_CHANGES_PATH_PB)/protos/*.proto; mv $(P_SYNC_CHANGES_PATH_PB)/protos/*.go $(P_SYNC_CHANGES_PATH_PB) $(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. $(P_SYNC_CHANGES_PATH_PB)/protos/*.proto; mv $(P_SYNC_CHANGES_PATH_PB)/protos/*.go $(P_SYNC_CHANGES_PATH_PB)
build: build:

View File

@ -6,6 +6,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
"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/treestorage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"sync" "sync"
) )
@ -47,6 +48,7 @@ var ErrNoCommonSnapshot = errors.New("trees doesn't have a common snapshot")
type ACLTree interface { type ACLTree interface {
RWLocker RWLocker
ID() string ID() string
Header() *treepb.TreeHeader
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)
@ -67,6 +69,7 @@ type aclTree struct {
updateListener TreeUpdateListener updateListener TreeUpdateListener
id string id string
header *treepb.TreeHeader
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
@ -118,6 +121,10 @@ func BuildACLTree(
if err != nil { if err != nil {
return nil, err return nil, err
} }
aclTree.header, err = t.Header()
if err != nil {
return nil, err
}
listener.Rebuild(aclTree) listener.Rebuild(aclTree)
@ -224,6 +231,10 @@ func (a *aclTree) ID() string {
return a.id return a.id
} }
func (a *aclTree) Header() *treepb.TreeHeader {
return a.header
}
func (a *aclTree) ACLState() *ACLState { func (a *aclTree) ACLState() *ACLState {
return a.aclState return a.aclState
} }

View File

@ -4,13 +4,16 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
"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/treestorage" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
"github.com/gogo/protobuf/proto"
) )
func BuildTreeStorageWithACL( func CreateNewTreeStorageWithACL(
acc *account.AccountData, acc *account.AccountData,
build func(builder ChangeBuilder) error, build func(builder ChangeBuilder) error,
create func(change *aclpb.RawChange) (treestorage.TreeStorage, error)) (treestorage.TreeStorage, error) { create treestorage.CreatorFunc) (treestorage.TreeStorage, error) {
bld := newChangeBuilder() bld := newChangeBuilder()
bld.Init( bld.Init(
newACLState(acc.Identity, acc.EncKey, signingkey.NewEd25519PubKeyDecoder()), newACLState(acc.Identity, acc.EncKey, signingkey.NewEd25519PubKeyDecoder()),
@ -32,8 +35,12 @@ func BuildTreeStorageWithACL(
Signature: change.Signature(), Signature: change.Signature(),
Id: change.CID(), Id: change.CID(),
} }
header, id, err := createTreeHeaderAndId(rawChange)
if err != nil {
return nil, err
}
thr, err := create(rawChange) thr, err := create(id, header, []*aclpb.RawChange{rawChange})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -44,3 +51,20 @@ func BuildTreeStorageWithACL(
} }
return thr, nil return thr, nil
} }
func createTreeHeaderAndId(change *aclpb.RawChange) (*treepb.TreeHeader, string, error) {
header := &treepb.TreeHeader{
FirstChangeId: change.Id,
IsWorkspace: false,
}
marshalledHeader, err := proto.Marshal(header)
if err != nil {
return nil, "", err
}
treeId, err := cid.NewCIDFromBytes(marshalledHeader)
if err != nil {
return nil, "", err
}
return header, treeId, nil
}

View File

@ -19,7 +19,7 @@ func Test_BuildTreeStorageWithACL(t *testing.T) {
SignKey: keychain.SigningKeys["A"], SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"], EncKey: keychain.EncryptionKeys["A"],
} }
thr, err := BuildTreeStorageWithACL( thr, err := CreateNewTreeStorageWithACL(
data, data,
func(builder ChangeBuilder) error { func(builder ChangeBuilder) error {
return builder.UserAdd( return builder.UserAdd(

View File

@ -118,7 +118,7 @@ func NewInMemoryPlainTextDocument(acc *account.AccountData, text string) (PlainT
func NewPlainTextDocument( func NewPlainTextDocument(
acc *account.AccountData, acc *account.AccountData,
create func(change *aclpb.RawChange) (treestorage.TreeStorage, error), create treestorage.CreatorFunc,
text string) (PlainTextDocument, error) { text string) (PlainTextDocument, error) {
changeBuilder := func(builder acltree.ChangeBuilder) error { changeBuilder := func(builder acltree.ChangeBuilder) error {
err := builder.UserAdd(acc.Identity, acc.EncKey.GetPublic(), aclpb.ACLChange_Admin) err := builder.UserAdd(acc.Identity, acc.EncKey.GetPublic(), aclpb.ACLChange_Admin)
@ -128,7 +128,7 @@ func NewPlainTextDocument(
builder.AddChangeContent(createInitialChangeContent(text)) builder.AddChangeContent(createInitialChangeContent(text))
return nil return nil
} }
t, err := acltree.BuildTreeStorageWithACL( t, err := acltree.CreateNewTreeStorageWithACL(
acc, acc,
changeBuilder, changeBuilder,
create) create)

View File

@ -6,7 +6,6 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges"
"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/treestorage/treepb" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"sync" "sync"
@ -22,29 +21,25 @@ type inMemoryTreeStorage struct {
sync.RWMutex sync.RWMutex
} }
func NewInMemoryTreeStorage(firstChange *aclpb.RawChange) (TreeStorage, error) { type CreatorFunc = func(string, *treepb.TreeHeader, []*aclpb.RawChange) (TreeStorage, error)
header := &treepb.TreeHeader{
FirstChangeId: firstChange.Id,
IsWorkspace: false,
}
marshalledHeader, err := proto.Marshal(header)
if err != nil {
return nil, err
}
treeId, err := cid.NewCIDFromBytes(marshalledHeader)
if err != nil {
return nil, err
}
changes := make(map[string]*aclpb.RawChange) func NewInMemoryTreeStorage(
changes[firstChange.Id] = firstChange treeId string,
header *treepb.TreeHeader,
changes []*aclpb.RawChange) (TreeStorage, error) {
allChanges := make(map[string]*aclpb.RawChange)
var orphans []string
for _, ch := range changes {
allChanges[ch.Id] = ch
orphans = append(orphans, ch.Id)
}
return &inMemoryTreeStorage{ return &inMemoryTreeStorage{
id: treeId, id: treeId,
header: header, header: header,
heads: []string{firstChange.Id}, heads: nil,
orphans: nil, orphans: orphans,
changes: changes, changes: allChanges,
RWMutex: sync.RWMutex{}, RWMutex: sync.RWMutex{},
}, nil }, nil
} }
@ -137,27 +132,28 @@ func (t *inMemoryTreeStorage) GetChange(ctx context.Context, changeId string) (*
type inMemoryTreeStorageProvider struct { type inMemoryTreeStorageProvider struct {
trees map[string]TreeStorage trees map[string]TreeStorage
sync.RWMutex
} }
func (i *inMemoryTreeStorageProvider) TreeStorage(treeId string) (TreeStorage, error) { func (i *inMemoryTreeStorageProvider) TreeStorage(treeId string) (TreeStorage, error) {
i.RLock()
defer i.RUnlock()
if tree, exists := i.trees[treeId]; exists { if tree, exists := i.trees[treeId]; exists {
return tree, nil return tree, nil
} }
return nil, ErrUnknownTreeId return nil, ErrUnknownTreeId
} }
func (i *inMemoryTreeStorageProvider) InsertTree(tree TreeStorage) error { func (i *inMemoryTreeStorageProvider) CreateTreeStorage(treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange) (TreeStorage, error) {
if tree == nil { i.Lock()
return fmt.Errorf("tree should not be nil") defer i.Unlock()
} res, err := NewInMemoryTreeStorage(treeId, header, changes)
id, err := tree.TreeID()
if err != nil { if err != nil {
return err return nil, err
} }
i.trees[id] = tree i.trees[treeId] = res
return nil return res, nil
} }
func NewInMemoryTreeStorageProvider() Provider { func NewInMemoryTreeStorageProvider() Provider {

View File

@ -1,10 +1,14 @@
package treestorage package treestorage
import "errors" import (
"errors"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
)
var ErrUnknownTreeId = errors.New("tree does not exist") var ErrUnknownTreeId = errors.New("tree does not exist")
type Provider interface { type Provider interface {
TreeStorage(treeId string) (TreeStorage, error) TreeStorage(treeId string) (TreeStorage, error)
InsertTree(tree TreeStorage) error CreateTreeStorage(treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange) (TreeStorage, error)
} }

View File

@ -1,5 +1,5 @@
syntax = "proto3"; syntax = "proto3";
package anytype; package tree;
option go_package = "treepb"; option go_package = "treepb";
message TreeHeader { message TreeHeader {

View File

@ -75,7 +75,7 @@ func (m *TreeHeader) GetIsWorkspace() bool {
} }
func init() { func init() {
proto.RegisterType((*TreeHeader)(nil), "anytype.TreeHeader") proto.RegisterType((*TreeHeader)(nil), "tree.TreeHeader")
} }
func init() { func init() {
@ -83,18 +83,18 @@ func init() {
} }
var fileDescriptor_e7d760b855878644 = []byte{ var fileDescriptor_e7d760b855878644 = []byte{
// 170 bytes of a gzipped FileDescriptorProto // 165 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x29, 0xc8, 0x4e, 0xd7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x29, 0xc8, 0x4e, 0xd7,
0x4f, 0x4c, 0xce, 0xd1, 0x2f, 0x29, 0x4a, 0x4d, 0x2d, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0x05, 0x4f, 0x4c, 0xce, 0xd1, 0x2f, 0x29, 0x4a, 0x4d, 0x2d, 0x2e, 0xc9, 0x2f, 0x4a, 0x4c, 0x4f, 0x05,
0xb3, 0x0b, 0x92, 0xf4, 0x0b, 0x8a, 0xf2, 0x4b, 0xf2, 0x8b, 0xc1, 0x3c, 0x3d, 0x30, 0x5b, 0x88, 0xb3, 0x0b, 0x92, 0xf4, 0x0b, 0x8a, 0xf2, 0x4b, 0xf2, 0x8b, 0xc1, 0x3c, 0x3d, 0x30, 0x5b, 0x88,
0x3d, 0x31, 0xaf, 0xb2, 0xa4, 0xb2, 0x20, 0x55, 0x29, 0x84, 0x8b, 0x2b, 0xa4, 0x28, 0x35, 0xd5, 0x05, 0xc4, 0x56, 0x0a, 0xe1, 0xe2, 0x0a, 0x29, 0x4a, 0x4d, 0xf5, 0x48, 0x4d, 0x4c, 0x49, 0x2d,
0x23, 0x35, 0x31, 0x25, 0xb5, 0x48, 0x48, 0x85, 0x8b, 0x37, 0x2d, 0xb3, 0xa8, 0xb8, 0xc4, 0x39, 0x12, 0x52, 0xe1, 0xe2, 0x4d, 0xcb, 0x2c, 0x2a, 0x2e, 0x71, 0xce, 0x48, 0xcc, 0x4b, 0x4f, 0xf5,
0x23, 0x31, 0x2f, 0x3d, 0xd5, 0x33, 0x45, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0x55, 0x50, 0x4c, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0x42, 0x15, 0x14, 0x52, 0xe0, 0xe2, 0xce, 0x2c,
0x48, 0x81, 0x8b, 0x3b, 0xb3, 0x38, 0x3c, 0xbf, 0x28, 0xbb, 0xb8, 0x20, 0x31, 0x39, 0x55, 0x82, 0x0e, 0xcf, 0x2f, 0xca, 0x2e, 0x2e, 0x48, 0x4c, 0x4e, 0x95, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0x08,
0x49, 0x81, 0x51, 0x83, 0x23, 0x08, 0x59, 0xc8, 0x49, 0xe1, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0x42, 0x16, 0x72, 0x52, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4,
0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0x36,
0x8f, 0xe5, 0x18, 0xa2, 0xd8, 0x20, 0x4e, 0x4a, 0x62, 0x03, 0xbb, 0xc3, 0x18, 0x10, 0x00, 0x00, 0x88, 0x7b, 0x92, 0xd8, 0xc0, 0x8e, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x09, 0x4f, 0xc6,
0xff, 0xff, 0xb1, 0x3f, 0x66, 0x17, 0xb7, 0x00, 0x00, 0x00, 0xec, 0xb4, 0x00, 0x00, 0x00,
} }
func (m *TreeHeader) Marshal() (dAtA []byte, err error) { func (m *TreeHeader) Marshal() (dAtA []byte, err error) {

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/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account" "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"
@ -66,7 +67,7 @@ func (r *requestHandler) HandleHeadUpdate(ctx context.Context, senderId string,
shouldFullSync := !slice.UnsortedEquals(update.Heads, tree.Heads()) shouldFullSync := !slice.UnsortedEquals(update.Heads, tree.Heads())
snapshotPath = tree.SnapshotPath() snapshotPath = tree.SnapshotPath()
if shouldFullSync { if shouldFullSync {
fullRequest, err = r.prepareFullSyncRequest(update.TreeId, update.SnapshotPath, tree) fullRequest, err = r.prepareFullSyncRequest(update.TreeId, update.TreeHeader, update.SnapshotPath, tree)
if err != nil { if err != nil {
return err return err
} }
@ -75,8 +76,10 @@ func (r *requestHandler) HandleHeadUpdate(ctx context.Context, senderId string,
}) })
// if there are no such tree // if there are no such tree
if err == treestorage.ErrUnknownTreeId { if err == treestorage.ErrUnknownTreeId {
// TODO: maybe we can optimize this by sending the header and stuff right away, so when the tree is created we are able to add it on first request
fullRequest = &syncpb.SyncFullRequest{ fullRequest = &syncpb.SyncFullRequest{
TreeId: update.TreeId, TreeId: update.TreeId,
TreeHeader: update.TreeHeader,
} }
} }
// if we have incompatible heads, or we haven't seen the tree at all // if we have incompatible heads, or we haven't seen the tree at all
@ -93,6 +96,7 @@ func (r *requestHandler) HandleHeadUpdate(ctx context.Context, senderId string,
Changes: result.Added, Changes: result.Added,
SnapshotPath: snapshotPath, SnapshotPath: snapshotPath,
TreeId: update.TreeId, TreeId: update.TreeId,
TreeHeader: update.TreeHeader,
} }
return r.client.NotifyHeadsChanged(newUpdate) return r.client.NotifyHeadsChanged(newUpdate)
} }
@ -106,7 +110,7 @@ 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
// if we have non empty request // if we have non-empty request
if len(request.Heads) != 0 { if len(request.Heads) != 0 {
result, err = tree.AddRawChanges(ctx, request.Changes...) result, err = tree.AddRawChanges(ctx, request.Changes...)
if err != nil { if err != nil {
@ -135,6 +139,7 @@ func (r *requestHandler) HandleFullSyncRequest(ctx context.Context, senderId str
Changes: result.Added, Changes: result.Added,
SnapshotPath: snapshotPath, SnapshotPath: snapshotPath,
TreeId: request.TreeId, TreeId: request.TreeId,
TreeHeader: request.TreeHeader,
} }
return r.client.NotifyHeadsChanged(newUpdate) return r.client.NotifyHeadsChanged(newUpdate)
} }
@ -154,17 +159,18 @@ func (r *requestHandler) HandleFullSyncResponse(ctx context.Context, senderId st
snapshotPath = tree.SnapshotPath() snapshotPath = tree.SnapshotPath()
return nil return nil
}) })
if err == treestorage.ErrUnknownTreeId {
// 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) && err != treestorage.ErrUnknownTreeId {
return err return err
} }
// if we have a new tree
// TODO: probably here we should not send an update message, because the other node had already sent it after updating with our data if err == treestorage.ErrUnknownTreeId {
// otherwise sending heads update message err = r.createTree(ctx, response)
if err != nil {
return err
}
}
// sending heads update message
newUpdate := &syncpb.SyncHeadUpdate{ newUpdate := &syncpb.SyncHeadUpdate{
Heads: result.Heads, Heads: result.Heads,
Changes: result.Added, Changes: result.Added,
@ -174,7 +180,7 @@ func (r *requestHandler) HandleFullSyncResponse(ctx context.Context, senderId st
return r.client.NotifyHeadsChanged(newUpdate) return r.client.NotifyHeadsChanged(newUpdate)
} }
func (r *requestHandler) prepareFullSyncRequest(treeId string, theirPath []string, tree acltree.ACLTree) (*syncpb.SyncFullRequest, error) { func (r *requestHandler) prepareFullSyncRequest(treeId string, header *treepb.TreeHeader, theirPath []string, tree acltree.ACLTree) (*syncpb.SyncFullRequest, error) {
ourChanges, err := tree.ChangesAfterCommonSnapshot(theirPath) ourChanges, err := tree.ChangesAfterCommonSnapshot(theirPath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -184,10 +190,15 @@ func (r *requestHandler) prepareFullSyncRequest(treeId string, theirPath []strin
Changes: ourChanges, Changes: ourChanges,
TreeId: treeId, TreeId: treeId,
SnapshotPath: tree.SnapshotPath(), SnapshotPath: tree.SnapshotPath(),
TreeHeader: header,
}, nil }, nil
} }
func (r *requestHandler) prepareFullSyncResponse(treeId string, theirPath []string, theirChanges []*aclpb.RawChange, tree acltree.ACLTree) (*syncpb.SyncFullResponse, error) { func (r *requestHandler) prepareFullSyncResponse(
treeId string,
theirPath []string,
theirChanges []*aclpb.RawChange,
tree acltree.ACLTree) (*syncpb.SyncFullResponse, error) {
// TODO: we can probably use the common snapshot calculated on the request step from previous peer // TODO: we can probably use the common snapshot calculated on the request step from previous peer
ourChanges, err := tree.ChangesAfterCommonSnapshot(theirPath) ourChanges, err := tree.ChangesAfterCommonSnapshot(theirPath)
if err != nil { if err != nil {
@ -211,10 +222,10 @@ func (r *requestHandler) prepareFullSyncResponse(treeId string, theirPath []stri
Changes: final, Changes: final,
TreeId: treeId, TreeId: treeId,
SnapshotPath: tree.SnapshotPath(), SnapshotPath: tree.SnapshotPath(),
TreeHeader: tree.Header(),
}, nil }, nil
} }
func (r *requestHandler) createTree(response *syncpb.SyncFullResponse) error { func (r *requestHandler) createTree(ctx context.Context, response *syncpb.SyncFullResponse) error {
// TODO: write create tree functionality return r.treeCache.Add(ctx, response.TreeId, response.TreeHeader, response.Changes)
return nil
} }

View File

@ -1,8 +1,9 @@
syntax = "proto3"; syntax = "proto3";
package anytype; package sync;
option go_package = "syncpb"; option go_package = "syncpb";
import "pkg/acl/aclchanges/aclpb/protos/aclchanges.proto"; import "pkg/acl/aclchanges/aclpb/protos/aclchanges.proto";
import "pkg/acl/treestorage/treepb/protos/tree.proto";
message Sync { message Sync {
message HeadUpdate { message HeadUpdate {
@ -10,6 +11,7 @@ message Sync {
repeated acl.RawChange changes = 2; repeated acl.RawChange changes = 2;
string treeId = 3; string treeId = 3;
repeated string snapshotPath = 4; repeated string snapshotPath = 4;
tree.TreeHeader treeHeader = 5;
} }
message Full { message Full {
@ -19,6 +21,7 @@ message Sync {
repeated acl.RawChange changes = 2; repeated acl.RawChange changes = 2;
string treeId = 3; string treeId = 3;
repeated string snapshotPath = 4; repeated string snapshotPath = 4;
tree.TreeHeader treeHeader = 5;
} }
message Response { message Response {
@ -26,6 +29,7 @@ message Sync {
repeated acl.RawChange changes = 2; repeated acl.RawChange changes = 2;
string treeId = 3; string treeId = 3;
repeated string snapshotPath = 4; repeated string snapshotPath = 4;
tree.TreeHeader treeHeader = 5;
} }
} }
} }

View File

@ -6,6 +6,7 @@ package syncpb
import ( import (
fmt "fmt" fmt "fmt"
aclpb "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb" aclpb "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
treepb "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
proto "github.com/gogo/protobuf/proto" proto "github.com/gogo/protobuf/proto"
io "io" io "io"
math "math" math "math"
@ -64,6 +65,7 @@ type SyncHeadUpdate struct {
Changes []*aclpb.RawChange `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"` Changes []*aclpb.RawChange `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
TreeId string `protobuf:"bytes,3,opt,name=treeId,proto3" json:"treeId,omitempty"` TreeId string `protobuf:"bytes,3,opt,name=treeId,proto3" json:"treeId,omitempty"`
SnapshotPath []string `protobuf:"bytes,4,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"` SnapshotPath []string `protobuf:"bytes,4,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
TreeHeader *treepb.TreeHeader `protobuf:"bytes,5,opt,name=treeHeader,proto3" json:"treeHeader,omitempty"`
} }
func (m *SyncHeadUpdate) Reset() { *m = SyncHeadUpdate{} } func (m *SyncHeadUpdate) Reset() { *m = SyncHeadUpdate{} }
@ -127,6 +129,13 @@ func (m *SyncHeadUpdate) GetSnapshotPath() []string {
return nil return nil
} }
func (m *SyncHeadUpdate) GetTreeHeader() *treepb.TreeHeader {
if m != nil {
return m.TreeHeader
}
return nil
}
type SyncFull struct { type SyncFull struct {
} }
@ -169,6 +178,7 @@ type SyncFullRequest struct {
Changes []*aclpb.RawChange `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"` Changes []*aclpb.RawChange `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
TreeId string `protobuf:"bytes,3,opt,name=treeId,proto3" json:"treeId,omitempty"` TreeId string `protobuf:"bytes,3,opt,name=treeId,proto3" json:"treeId,omitempty"`
SnapshotPath []string `protobuf:"bytes,4,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"` SnapshotPath []string `protobuf:"bytes,4,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
TreeHeader *treepb.TreeHeader `protobuf:"bytes,5,opt,name=treeHeader,proto3" json:"treeHeader,omitempty"`
} }
func (m *SyncFullRequest) Reset() { *m = SyncFullRequest{} } func (m *SyncFullRequest) Reset() { *m = SyncFullRequest{} }
@ -232,11 +242,19 @@ func (m *SyncFullRequest) GetSnapshotPath() []string {
return nil return nil
} }
func (m *SyncFullRequest) GetTreeHeader() *treepb.TreeHeader {
if m != nil {
return m.TreeHeader
}
return nil
}
type SyncFullResponse struct { type SyncFullResponse struct {
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"` Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
Changes []*aclpb.RawChange `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"` Changes []*aclpb.RawChange `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
TreeId string `protobuf:"bytes,3,opt,name=treeId,proto3" json:"treeId,omitempty"` TreeId string `protobuf:"bytes,3,opt,name=treeId,proto3" json:"treeId,omitempty"`
SnapshotPath []string `protobuf:"bytes,4,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"` SnapshotPath []string `protobuf:"bytes,4,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
TreeHeader *treepb.TreeHeader `protobuf:"bytes,5,opt,name=treeHeader,proto3" json:"treeHeader,omitempty"`
} }
func (m *SyncFullResponse) Reset() { *m = SyncFullResponse{} } func (m *SyncFullResponse) Reset() { *m = SyncFullResponse{} }
@ -300,12 +318,19 @@ func (m *SyncFullResponse) GetSnapshotPath() []string {
return nil return nil
} }
func (m *SyncFullResponse) GetTreeHeader() *treepb.TreeHeader {
if m != nil {
return m.TreeHeader
}
return nil
}
func init() { func init() {
proto.RegisterType((*Sync)(nil), "anytype.Sync") proto.RegisterType((*Sync)(nil), "sync.Sync")
proto.RegisterType((*SyncHeadUpdate)(nil), "anytype.Sync.HeadUpdate") proto.RegisterType((*SyncHeadUpdate)(nil), "sync.Sync.HeadUpdate")
proto.RegisterType((*SyncFull)(nil), "anytype.Sync.Full") proto.RegisterType((*SyncFull)(nil), "sync.Sync.Full")
proto.RegisterType((*SyncFullRequest)(nil), "anytype.Sync.Full.Request") proto.RegisterType((*SyncFullRequest)(nil), "sync.Sync.Full.Request")
proto.RegisterType((*SyncFullResponse)(nil), "anytype.Sync.Full.Response") proto.RegisterType((*SyncFullResponse)(nil), "sync.Sync.Full.Response")
} }
func init() { func init() {
@ -313,25 +338,27 @@ func init() {
} }
var fileDescriptor_5f66cdd599c6466f = []byte{ var fileDescriptor_5f66cdd599c6466f = []byte{
// 273 bytes of a gzipped FileDescriptorProto // 314 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2d, 0x4e, 0x2d, 0x2a, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x52, 0xc1, 0x4a, 0xc3, 0x30,
0xcb, 0x4c, 0x4e, 0xd5, 0x2f, 0xae, 0xcc, 0x4b, 0x06, 0x13, 0x05, 0x49, 0xfa, 0x05, 0x45, 0xf9, 0x18, 0x5e, 0xb6, 0x6e, 0x73, 0xff, 0x44, 0x24, 0x88, 0x94, 0x1e, 0x42, 0x19, 0x08, 0x3d, 0x48,
0x25, 0xf9, 0xc5, 0x60, 0x9e, 0x1e, 0x98, 0x2d, 0xc4, 0x9e, 0x98, 0x57, 0x59, 0x52, 0x59, 0x90, 0x37, 0xe6, 0x1b, 0x28, 0x88, 0xde, 0x24, 0xea, 0xc5, 0x5b, 0xd6, 0xfe, 0xac, 0x62, 0x69, 0x63,
0x2a, 0x65, 0x50, 0x90, 0x9d, 0xae, 0x9f, 0x98, 0x9c, 0x03, 0xc2, 0xc9, 0x19, 0x89, 0x79, 0xe9, 0x93, 0x29, 0xbe, 0x85, 0x6f, 0xa3, 0x78, 0xf3, 0xe6, 0x71, 0x47, 0x8f, 0xd2, 0x3e, 0x86, 0x17,
0xa9, 0xc5, 0x20, 0x26, 0x42, 0x13, 0x42, 0x1c, 0xa2, 0x55, 0x69, 0x35, 0x33, 0x17, 0x4b, 0x70, 0x49, 0xba, 0x59, 0x7d, 0x84, 0x1d, 0x12, 0xbe, 0xef, 0xcb, 0xff, 0xe5, 0xfb, 0x13, 0x7e, 0x38,
0x65, 0x5e, 0xb2, 0x54, 0x07, 0x23, 0x17, 0x97, 0x47, 0x6a, 0x62, 0x4a, 0x68, 0x41, 0x4a, 0x62, 0x50, 0x58, 0x3c, 0xdc, 0x46, 0x38, 0x56, 0x4f, 0x59, 0x64, 0x37, 0x39, 0x1b, 0xcb, 0x22, 0xd7,
0x49, 0xaa, 0x90, 0x08, 0x17, 0x6b, 0x46, 0x6a, 0x62, 0x4a, 0xb1, 0x04, 0xa3, 0x02, 0xb3, 0x06, 0xb9, 0xb2, 0x2c, 0xb4, 0x98, 0x3a, 0x06, 0x7b, 0x13, 0x79, 0x37, 0x1f, 0x8b, 0x28, 0x35, 0x2b,
0x67, 0x10, 0x84, 0x23, 0xa4, 0xc1, 0xc5, 0x0e, 0xd5, 0x2e, 0xc1, 0xa4, 0xc0, 0xac, 0xc1, 0x6d, 0x4a, 0x44, 0x36, 0x47, 0x65, 0x60, 0xe3, 0x68, 0xf4, 0xda, 0xe7, 0x1d, 0xae, 0x1d, 0xba, 0x40,
0xc4, 0xa7, 0x97, 0x98, 0x9c, 0xa3, 0x17, 0x94, 0x58, 0xee, 0x0c, 0x16, 0x0e, 0x82, 0x49, 0x0b, 0x54, 0x3a, 0x2f, 0xc4, 0x1c, 0x2d, 0x6e, 0x3c, 0x86, 0xd5, 0xd5, 0xa3, 0x77, 0x07, 0x9c, 0x4b,
0x89, 0x71, 0xb1, 0x95, 0x14, 0xa5, 0xa6, 0x7a, 0xa6, 0x48, 0x30, 0x2b, 0x30, 0x6a, 0x70, 0x06, 0x13, 0xf4, 0x46, 0x00, 0xce, 0x50, 0xc4, 0xd7, 0x32, 0x16, 0x1a, 0xe9, 0x1e, 0x74, 0x13, 0x14,
0x41, 0x79, 0x42, 0x4a, 0x5c, 0x3c, 0xc5, 0x79, 0x89, 0x05, 0xc5, 0x19, 0xf9, 0x25, 0x01, 0x89, 0xb1, 0x72, 0x89, 0xdf, 0x09, 0x06, 0xbc, 0x26, 0x34, 0x80, 0xfe, 0x2a, 0xcc, 0x6d, 0xfb, 0x9d,
0x25, 0x19, 0x12, 0x2c, 0x60, 0xe3, 0x51, 0xc4, 0xa4, 0xa6, 0x33, 0x71, 0xb1, 0xb8, 0x95, 0xe6, 0x60, 0x38, 0xdd, 0x09, 0x45, 0x94, 0x86, 0x5c, 0x3c, 0x9e, 0x58, 0x99, 0xaf, 0x8f, 0xe9, 0x3e,
0xe4, 0x48, 0xb5, 0x32, 0x72, 0xb1, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x0c, 0xa8, 0x83, 0xf4, 0x4c, 0xca, 0x79, 0xec, 0x76, 0x7c, 0x12, 0x0c, 0xf8, 0x8a, 0xd1, 0x11, 0x6c, 0xab, 0x4c,
0xda, 0x18, 0xb9, 0x38, 0x82, 0x52, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x07, 0x34, 0x64, 0x9c, 0x14, 0x48, 0x95, 0xe4, 0xfa, 0x42, 0xe8, 0xc4, 0x75, 0xec, 0xf5, 0xff, 0x34, 0x3a, 0x01, 0x30, 0xd5,
0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0xa6, 0x1b, 0x2c, 0xdc, 0xae, 0x4f, 0x82, 0xe1, 0x74, 0x37, 0xb4, 0x4d, 0x5f, 0xfd, 0xea, 0xfc,
0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x8a, 0x0d, 0x92, 0x38, 0x92, 0xd8, 0x4f, 0x8d, 0xf7, 0xdd, 0x06, 0xe7, 0x74, 0x91, 0xa6, 0xde, 0x0b, 0x81, 0x3e, 0xc7, 0xfb, 0x05,
0xc0, 0xd1, 0x6a, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x90, 0x29, 0xbc, 0x62, 0x3a, 0x02, 0x00, 0x2a, 0xbd, 0x61, 0x4f, 0x78, 0x25, 0xb0, 0xc5, 0x51, 0xc9, 0x3c, 0x53, 0x1b, 0xf6, 0xfb, 0xc7,
0x00, 0xfe, 0x47, 0xc9, 0xc8, 0xb2, 0x64, 0xe4, 0xab, 0x64, 0xe4, 0xb9, 0x62, 0xad, 0x65, 0xc5, 0x5a,
0x9f, 0x15, 0x6b, 0xdd, 0xf4, 0xea, 0xe9, 0x9e, 0xf5, 0xec, 0xb0, 0x1d, 0xfd, 0x04, 0x00, 0x00,
0xff, 0xff, 0x52, 0xcd, 0x15, 0xea, 0xfb, 0x02, 0x00, 0x00,
} }
func (m *Sync) Marshal() (dAtA []byte, err error) { func (m *Sync) Marshal() (dAtA []byte, err error) {
@ -377,6 +404,18 @@ func (m *SyncHeadUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.TreeHeader != nil {
{
size, err := m.TreeHeader.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintSync(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x2a
}
if len(m.SnapshotPath) > 0 { if len(m.SnapshotPath) > 0 {
for iNdEx := len(m.SnapshotPath) - 1; iNdEx >= 0; iNdEx-- { for iNdEx := len(m.SnapshotPath) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.SnapshotPath[iNdEx]) i -= len(m.SnapshotPath[iNdEx])
@ -462,6 +501,18 @@ func (m *SyncFullRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.TreeHeader != nil {
{
size, err := m.TreeHeader.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintSync(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x2a
}
if len(m.SnapshotPath) > 0 { if len(m.SnapshotPath) > 0 {
for iNdEx := len(m.SnapshotPath) - 1; iNdEx >= 0; iNdEx-- { for iNdEx := len(m.SnapshotPath) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.SnapshotPath[iNdEx]) i -= len(m.SnapshotPath[iNdEx])
@ -524,6 +575,18 @@ func (m *SyncFullResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.TreeHeader != nil {
{
size, err := m.TreeHeader.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintSync(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x2a
}
if len(m.SnapshotPath) > 0 { if len(m.SnapshotPath) > 0 {
for iNdEx := len(m.SnapshotPath) - 1; iNdEx >= 0; iNdEx-- { for iNdEx := len(m.SnapshotPath) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.SnapshotPath[iNdEx]) i -= len(m.SnapshotPath[iNdEx])
@ -614,6 +677,10 @@ func (m *SyncHeadUpdate) Size() (n int) {
n += 1 + l + sovSync(uint64(l)) n += 1 + l + sovSync(uint64(l))
} }
} }
if m.TreeHeader != nil {
l = m.TreeHeader.Size()
n += 1 + l + sovSync(uint64(l))
}
return n return n
} }
@ -654,6 +721,10 @@ func (m *SyncFullRequest) Size() (n int) {
n += 1 + l + sovSync(uint64(l)) n += 1 + l + sovSync(uint64(l))
} }
} }
if m.TreeHeader != nil {
l = m.TreeHeader.Size()
n += 1 + l + sovSync(uint64(l))
}
return n return n
} }
@ -685,6 +756,10 @@ func (m *SyncFullResponse) Size() (n int) {
n += 1 + l + sovSync(uint64(l)) n += 1 + l + sovSync(uint64(l))
} }
} }
if m.TreeHeader != nil {
l = m.TreeHeader.Size()
n += 1 + l + sovSync(uint64(l))
}
return n return n
} }
@ -903,6 +978,42 @@ func (m *SyncHeadUpdate) Unmarshal(dAtA []byte) error {
} }
m.SnapshotPath = append(m.SnapshotPath, string(dAtA[iNdEx:postIndex])) m.SnapshotPath = append(m.SnapshotPath, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TreeHeader", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthSync
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthSync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.TreeHeader == nil {
m.TreeHeader = &treepb.TreeHeader{}
}
if err := m.TreeHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipSync(dAtA[iNdEx:]) skippy, err := skipSync(dAtA[iNdEx:])
@ -1133,6 +1244,42 @@ func (m *SyncFullRequest) Unmarshal(dAtA []byte) error {
} }
m.SnapshotPath = append(m.SnapshotPath, string(dAtA[iNdEx:postIndex])) m.SnapshotPath = append(m.SnapshotPath, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TreeHeader", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthSync
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthSync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.TreeHeader == nil {
m.TreeHeader = &treepb.TreeHeader{}
}
if err := m.TreeHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipSync(dAtA[iNdEx:]) skippy, err := skipSync(dAtA[iNdEx:])
@ -1313,6 +1460,42 @@ func (m *SyncFullResponse) Unmarshal(dAtA []byte) error {
} }
m.SnapshotPath = append(m.SnapshotPath, string(dAtA[iNdEx:postIndex])) m.SnapshotPath = append(m.SnapshotPath, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TreeHeader", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSync
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthSync
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthSync
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.TreeHeader == nil {
m.TreeHeader = &treepb.TreeHeader{}
}
if err := m.TreeHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipSync(dAtA[iNdEx:]) skippy, err := skipSync(dAtA[iNdEx:])

View File

@ -3,8 +3,10 @@ package treecache
import ( import (
"context" "context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/app" "github.com/anytypeio/go-anytype-infrastructure-experiments/app"
"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/pkg/acl/treestorage/treepb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache" "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account" "github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
) )
@ -13,7 +15,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 Add(ctx context.Context, treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange) error
} }
type service struct { type service struct {
@ -38,13 +40,20 @@ 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 { func (s *service) Add(ctx context.Context, treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange) error {
return s.cache.Add(treeId, tree) _, err := s.treeProvider.CreateTreeStorage(treeId, header, changes)
if err != nil {
return err
}
// forcing the tree to build
_, err = s.cache.Get(ctx, treeId)
return err
} }
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)
s.treeProvider = treestorage.NewInMemoryTreeStorageProvider()
// TODO: for test we should load some predefined keys // TODO: for test we should load some predefined keys
return nil return nil
} }