Change proto and generalise logic
This commit is contained in:
parent
69211dfe66
commit
6518a0f971
@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncacl"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncacl"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
@ -15,7 +14,6 @@ import (
|
|||||||
"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/nodeconf"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
||||||
aclstorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
|
||||||
tree "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
tree "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
|
||||||
@ -167,51 +165,6 @@ func (s *space) BuildTree(ctx context.Context, id string, listener updatelistene
|
|||||||
err = ErrSpaceClosed
|
err = ErrSpaceClosed
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
getTreeRemote := func() (*spacesyncproto.ObjectSyncMessage, error) {
|
|
||||||
// TODO: add empty context handling (when this is not happening due to head update)
|
|
||||||
peerId, err := syncservice.GetPeerIdFromStreamContext(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return s.syncService.StreamPool().SendSync(
|
|
||||||
peerId,
|
|
||||||
synctree.GetRequestFactory().CreateNewTreeRequest(id),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
store, err := s.storage.TreeStorage(id)
|
|
||||||
if err != nil && err != aclstorage.ErrUnknownTreeId {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
isFirstBuild := false
|
|
||||||
if err == aclstorage.ErrUnknownTreeId {
|
|
||||||
isFirstBuild = true
|
|
||||||
var resp *spacesyncproto.ObjectSyncMessage
|
|
||||||
resp, err = getTreeRemote()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fullSyncResp := resp.GetContent().GetFullSyncResponse()
|
|
||||||
|
|
||||||
payload := aclstorage.TreeStorageCreatePayload{
|
|
||||||
TreeId: resp.TreeId,
|
|
||||||
RootRawChange: resp.RootChange,
|
|
||||||
Changes: fullSyncResp.Changes,
|
|
||||||
Heads: fullSyncResp.Heads,
|
|
||||||
}
|
|
||||||
|
|
||||||
// basically building tree with inmemory storage and validating that it was without errors
|
|
||||||
err = tree.ValidateRawTree(payload, s.aclList)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// now we are sure that we can save it to the storage
|
|
||||||
store, err = s.storage.CreateTreeStorage(payload)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deps := synctree.BuildDeps{
|
deps := synctree.BuildDeps{
|
||||||
SpaceId: s.id,
|
SpaceId: s.id,
|
||||||
StreamPool: s.syncService.StreamPool(),
|
StreamPool: s.syncService.StreamPool(),
|
||||||
@ -219,9 +172,9 @@ func (s *space) BuildTree(ctx context.Context, id string, listener updatelistene
|
|||||||
HeadNotifiable: s.diffService,
|
HeadNotifiable: s.diffService,
|
||||||
Listener: listener,
|
Listener: listener,
|
||||||
AclList: s.aclList,
|
AclList: s.aclList,
|
||||||
Storage: store,
|
SpaceStorage: s.storage,
|
||||||
}
|
}
|
||||||
return synctree.BuildSyncTree(ctx, isFirstBuild, deps)
|
return synctree.BuildSyncTreeOrGetRemote(ctx, id, deps)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) Close() error {
|
func (s *space) Close() error {
|
||||||
|
|||||||
@ -2,7 +2,6 @@ syntax = "proto3";
|
|||||||
package anySpace;
|
package anySpace;
|
||||||
|
|
||||||
option go_package = "commonspace/spacesyncproto";
|
option go_package = "commonspace/spacesyncproto";
|
||||||
import "pkg/acl/treechangeproto/protos/treechange.proto";
|
|
||||||
import "pkg/acl/aclrecordproto/protos/aclrecord.proto";
|
import "pkg/acl/aclrecordproto/protos/aclrecord.proto";
|
||||||
|
|
||||||
enum ErrCodes {
|
enum ErrCodes {
|
||||||
@ -55,51 +54,13 @@ message HeadSyncResponse {
|
|||||||
// ObjectSyncMessage is a message sent on object sync
|
// ObjectSyncMessage is a message sent on object sync
|
||||||
message ObjectSyncMessage {
|
message ObjectSyncMessage {
|
||||||
string spaceId = 1;
|
string spaceId = 1;
|
||||||
ObjectSyncContentValue content = 2;
|
string replyId = 2;
|
||||||
treechange.RawTreeChangeWithId rootChange = 3;
|
bytes payload = 3;
|
||||||
string treeId = 4;
|
string objectId = 4;
|
||||||
string trackingId = 5;
|
|
||||||
|
|
||||||
// string identity = 5;
|
// string identity = 5;
|
||||||
// string peerSignature = 6;
|
// string peerSignature = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectSyncContentValue provides different types for object sync
|
|
||||||
message ObjectSyncContentValue {
|
|
||||||
oneof value {
|
|
||||||
ObjectHeadUpdate headUpdate = 1;
|
|
||||||
ObjectFullSyncRequest fullSyncRequest = 2;
|
|
||||||
ObjectFullSyncResponse fullSyncResponse = 3;
|
|
||||||
ObjectErrorResponse errorResponse = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectHeadUpdate is a message sent on document head update
|
|
||||||
message ObjectHeadUpdate {
|
|
||||||
repeated string heads = 1;
|
|
||||||
repeated treechange.RawTreeChangeWithId changes = 2;
|
|
||||||
repeated string snapshotPath = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectHeadUpdate is a message sent when document needs full sync
|
|
||||||
message ObjectFullSyncRequest {
|
|
||||||
repeated string heads = 1;
|
|
||||||
repeated treechange.RawTreeChangeWithId changes = 2;
|
|
||||||
repeated string snapshotPath = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectFullSyncResponse is a message sent as a response for a specific full sync
|
|
||||||
message ObjectFullSyncResponse {
|
|
||||||
repeated string heads = 1;
|
|
||||||
repeated treechange.RawTreeChangeWithId changes = 2;
|
|
||||||
repeated string snapshotPath = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectErrorResponse is an error sent as a response for a full sync request
|
|
||||||
message ObjectErrorResponse {
|
|
||||||
string error = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PushSpaceRequest is a request to add space on a node containing only one acl record
|
// PushSpaceRequest is a request to add space on a node containing only one acl record
|
||||||
message PushSpaceRequest {
|
message PushSpaceRequest {
|
||||||
RawSpaceHeaderWithId spaceHeader = 2;
|
RawSpaceHeaderWithId spaceHeader = 2;
|
||||||
|
|||||||
@ -2,8 +2,6 @@
|
|||||||
package spacesyncproto
|
package spacesyncproto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
|
||||||
"storj.io/drpc"
|
"storj.io/drpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,63 +16,3 @@ func (c ClientFactoryFunc) Client(cc drpc.Conn) DRPCSpaceClient {
|
|||||||
type ClientFactory interface {
|
type ClientFactory interface {
|
||||||
Client(cc drpc.Conn) DRPCSpaceClient
|
Client(cc drpc.Conn) DRPCSpaceClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func WrapHeadUpdate(update *ObjectHeadUpdate, rootChange *treechangeproto.RawTreeChangeWithId, treeId, trackingId string) *ObjectSyncMessage {
|
|
||||||
return &ObjectSyncMessage{
|
|
||||||
Content: &ObjectSyncContentValue{
|
|
||||||
Value: &ObjectSyncContentValue_HeadUpdate{HeadUpdate: update},
|
|
||||||
},
|
|
||||||
RootChange: rootChange,
|
|
||||||
TreeId: treeId,
|
|
||||||
TrackingId: trackingId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapFullRequest(request *ObjectFullSyncRequest, rootChange *treechangeproto.RawTreeChangeWithId, treeId, trackingId string) *ObjectSyncMessage {
|
|
||||||
return &ObjectSyncMessage{
|
|
||||||
Content: &ObjectSyncContentValue{
|
|
||||||
Value: &ObjectSyncContentValue_FullSyncRequest{FullSyncRequest: request},
|
|
||||||
},
|
|
||||||
RootChange: rootChange,
|
|
||||||
TreeId: treeId,
|
|
||||||
TrackingId: trackingId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapFullResponse(response *ObjectFullSyncResponse, rootChange *treechangeproto.RawTreeChangeWithId, treeId, trackingId string) *ObjectSyncMessage {
|
|
||||||
return &ObjectSyncMessage{
|
|
||||||
Content: &ObjectSyncContentValue{
|
|
||||||
Value: &ObjectSyncContentValue_FullSyncResponse{FullSyncResponse: response},
|
|
||||||
},
|
|
||||||
RootChange: rootChange,
|
|
||||||
TreeId: treeId,
|
|
||||||
TrackingId: trackingId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WrapError(err error, rootChange *treechangeproto.RawTreeChangeWithId, treeId, trackingId string) *ObjectSyncMessage {
|
|
||||||
return &ObjectSyncMessage{
|
|
||||||
Content: &ObjectSyncContentValue{
|
|
||||||
Value: &ObjectSyncContentValue_ErrorResponse{ErrorResponse: &ObjectErrorResponse{Error: err.Error()}},
|
|
||||||
},
|
|
||||||
RootChange: rootChange,
|
|
||||||
TreeId: treeId,
|
|
||||||
TrackingId: trackingId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MessageDescription(msg *ObjectSyncMessage) (res string) {
|
|
||||||
content := msg.GetContent()
|
|
||||||
switch {
|
|
||||||
case content.GetHeadUpdate() != nil:
|
|
||||||
res = fmt.Sprintf("head update/%v", content.GetHeadUpdate().Heads)
|
|
||||||
case content.GetFullSyncRequest() != nil:
|
|
||||||
res = fmt.Sprintf("fullsync request/%v", content.GetFullSyncRequest().Heads)
|
|
||||||
case content.GetFullSyncResponse() != nil:
|
|
||||||
res = fmt.Sprintf("fullsync response/%v", content.GetFullSyncResponse().Heads)
|
|
||||||
case content.GetErrorResponse() != nil:
|
|
||||||
res = fmt.Sprintf("error response/%v", content.GetErrorResponse().Error)
|
|
||||||
}
|
|
||||||
res = fmt.Sprintf("%s/tracking=[%s]", res, msg.TrackingId)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -78,13 +78,13 @@ func (s *streamPool) SendSync(
|
|||||||
peerId string,
|
peerId string,
|
||||||
msg *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error) {
|
msg *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error) {
|
||||||
newCounter := s.counter.Add(1)
|
newCounter := s.counter.Add(1)
|
||||||
msg.TrackingId = genStreamPoolKey(peerId, msg.TreeId, newCounter)
|
msg.ReplyId = genStreamPoolKey(peerId, msg.ObjectId, newCounter)
|
||||||
|
|
||||||
s.waitersMx.Lock()
|
s.waitersMx.Lock()
|
||||||
waiter := responseWaiter{
|
waiter := responseWaiter{
|
||||||
ch: make(chan *spacesyncproto.ObjectSyncMessage, 1),
|
ch: make(chan *spacesyncproto.ObjectSyncMessage, 1),
|
||||||
}
|
}
|
||||||
s.waiters[msg.TrackingId] = waiter
|
s.waiters[msg.ReplyId] = waiter
|
||||||
s.waitersMx.Unlock()
|
s.waitersMx.Unlock()
|
||||||
|
|
||||||
err = s.SendAsync([]string{peerId}, msg)
|
err = s.SendAsync([]string{peerId}, msg)
|
||||||
@ -95,10 +95,10 @@ func (s *streamPool) SendSync(
|
|||||||
select {
|
select {
|
||||||
case <-delay.C:
|
case <-delay.C:
|
||||||
s.waitersMx.Lock()
|
s.waitersMx.Lock()
|
||||||
delete(s.waiters, msg.TrackingId)
|
delete(s.waiters, msg.ReplyId)
|
||||||
s.waitersMx.Unlock()
|
s.waitersMx.Unlock()
|
||||||
|
|
||||||
log.With("trackingId", msg.TrackingId).Error("time elapsed when waiting")
|
log.With("trackingId", msg.ReplyId).Error("time elapsed when waiting")
|
||||||
err = ErrSyncTimeout
|
err = ErrSyncTimeout
|
||||||
case reply = <-waiter.ch:
|
case reply = <-waiter.ch:
|
||||||
if !delay.Stop() {
|
if !delay.Stop() {
|
||||||
@ -125,8 +125,7 @@ func (s *streamPool) SendAsync(peers []string, message *spacesyncproto.ObjectSyn
|
|||||||
streams := getStreams()
|
streams := getStreams()
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
|
|
||||||
log.With("description", spacesyncproto.MessageDescription(message)).
|
log.With("objectId", message.ObjectId).
|
||||||
With("treeId", message.TreeId).
|
|
||||||
Debugf("sending message to %d peers", len(streams))
|
Debugf("sending message to %d peers", len(streams))
|
||||||
for _, s := range streams {
|
for _, s := range streams {
|
||||||
err = s.Send(message)
|
err = s.Send(message)
|
||||||
@ -174,8 +173,7 @@ Loop:
|
|||||||
|
|
||||||
func (s *streamPool) BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error) {
|
func (s *streamPool) BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
streams := s.getAllStreams()
|
streams := s.getAllStreams()
|
||||||
log.With("description", spacesyncproto.MessageDescription(message)).
|
log.With("objectId", message.ObjectId).
|
||||||
With("treeId", message.TreeId).
|
|
||||||
Debugf("broadcasting message to %d peers", len(streams))
|
Debugf("broadcasting message to %d peers", len(streams))
|
||||||
for _, stream := range streams {
|
for _, stream := range streams {
|
||||||
if err = stream.Send(message); err != nil {
|
if err = stream.Send(message); err != nil {
|
||||||
@ -224,23 +222,23 @@ func (s *streamPool) readPeerLoop(peerId string, stream spacesyncproto.SpaceStre
|
|||||||
|
|
||||||
process := func(msg *spacesyncproto.ObjectSyncMessage) {
|
process := func(msg *spacesyncproto.ObjectSyncMessage) {
|
||||||
s.lastUsage.Store(time.Now().Unix())
|
s.lastUsage.Store(time.Now().Unix())
|
||||||
if msg.TrackingId == "" {
|
if msg.ReplyId == "" {
|
||||||
s.messageHandler(stream.Context(), peerId, msg)
|
s.messageHandler(stream.Context(), peerId, msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.With("trackingId", msg.TrackingId).Debug("getting message with tracking id")
|
log.With("trackingId", msg.ReplyId).Debug("getting message with tracking id")
|
||||||
s.waitersMx.Lock()
|
s.waitersMx.Lock()
|
||||||
waiter, exists := s.waiters[msg.TrackingId]
|
waiter, exists := s.waiters[msg.ReplyId]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
log.With("trackingId", msg.TrackingId).Debug("tracking id not exists")
|
log.With("trackingId", msg.ReplyId).Debug("tracking id not exists")
|
||||||
s.waitersMx.Unlock()
|
s.waitersMx.Unlock()
|
||||||
s.messageHandler(stream.Context(), peerId, msg)
|
s.messageHandler(stream.Context(), peerId, msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.With("trackingId", msg.TrackingId).Debug("tracking id exists")
|
log.With("trackingId", msg.ReplyId).Debug("tracking id exists")
|
||||||
|
|
||||||
delete(s.waiters, msg.TrackingId)
|
delete(s.waiters, msg.ReplyId)
|
||||||
s.waitersMx.Unlock()
|
s.waitersMx.Unlock()
|
||||||
waiter.ch <- msg
|
waiter.ch <- msg
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,7 +84,7 @@ func (s *syncService) LastUsage() time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncService) HandleMessage(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
func (s *syncService) HandleMessage(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
obj, err := s.objectGetter.GetObject(ctx, message.TreeId)
|
obj, err := s.objectGetter.GetObject(ctx, message.ObjectId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,17 +2,16 @@ package synctree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RequestFactory interface {
|
type RequestFactory interface {
|
||||||
CreateHeadUpdate(t tree.ObjectTree, added []*treechangeproto.RawTreeChangeWithId) (msg *spacesyncproto.ObjectSyncMessage)
|
CreateHeadUpdate(t tree.ObjectTree, added []*treechangeproto.RawTreeChangeWithId) (msg *treechangeproto.TreeSyncMessage)
|
||||||
CreateNewTreeRequest(id string) (msg *spacesyncproto.ObjectSyncMessage)
|
CreateNewTreeRequest() (msg *treechangeproto.TreeSyncMessage)
|
||||||
CreateFullSyncRequest(t tree.ObjectTree, theirHeads, theirSnapshotPath []string, trackingId string) (req *spacesyncproto.ObjectSyncMessage, err error)
|
CreateFullSyncRequest(t tree.ObjectTree, theirHeads, theirSnapshotPath []string) (req *treechangeproto.TreeSyncMessage, err error)
|
||||||
CreateFullSyncResponse(t tree.ObjectTree, theirHeads, theirSnapshotPath []string, trackingId string) (*spacesyncproto.ObjectSyncMessage, error)
|
CreateFullSyncResponse(t tree.ObjectTree, theirHeads, theirSnapshotPath []string) (*treechangeproto.TreeSyncMessage, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var factory = &requestFactory{}
|
var factory = &requestFactory{}
|
||||||
@ -23,20 +22,20 @@ func GetRequestFactory() RequestFactory {
|
|||||||
|
|
||||||
type requestFactory struct{}
|
type requestFactory struct{}
|
||||||
|
|
||||||
func (r *requestFactory) CreateHeadUpdate(t tree.ObjectTree, added []*treechangeproto.RawTreeChangeWithId) (msg *spacesyncproto.ObjectSyncMessage) {
|
func (r *requestFactory) CreateHeadUpdate(t tree.ObjectTree, added []*treechangeproto.RawTreeChangeWithId) (msg *treechangeproto.TreeSyncMessage) {
|
||||||
return spacesyncproto.WrapHeadUpdate(&spacesyncproto.ObjectHeadUpdate{
|
return treechangeproto.WrapHeadUpdate(&treechangeproto.TreeHeadUpdate{
|
||||||
Heads: t.Heads(),
|
Heads: t.Heads(),
|
||||||
Changes: added,
|
Changes: added,
|
||||||
SnapshotPath: t.SnapshotPath(),
|
SnapshotPath: t.SnapshotPath(),
|
||||||
}, t.Header(), t.ID(), "")
|
}, t.Header())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *requestFactory) CreateNewTreeRequest(id string) (msg *spacesyncproto.ObjectSyncMessage) {
|
func (r *requestFactory) CreateNewTreeRequest() (msg *treechangeproto.TreeSyncMessage) {
|
||||||
return spacesyncproto.WrapFullRequest(&spacesyncproto.ObjectFullSyncRequest{}, nil, id, "")
|
return treechangeproto.WrapFullRequest(&treechangeproto.TreeFullSyncRequest{}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *requestFactory) CreateFullSyncRequest(t tree.ObjectTree, theirHeads, theirSnapshotPath []string, trackingId string) (msg *spacesyncproto.ObjectSyncMessage, err error) {
|
func (r *requestFactory) CreateFullSyncRequest(t tree.ObjectTree, theirHeads, theirSnapshotPath []string) (msg *treechangeproto.TreeSyncMessage, err error) {
|
||||||
req := &spacesyncproto.ObjectFullSyncRequest{}
|
req := &treechangeproto.TreeFullSyncRequest{}
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return nil, fmt.Errorf("tree should not be empty")
|
return nil, fmt.Errorf("tree should not be empty")
|
||||||
}
|
}
|
||||||
@ -51,17 +50,17 @@ func (r *requestFactory) CreateFullSyncRequest(t tree.ObjectTree, theirHeads, th
|
|||||||
}
|
}
|
||||||
|
|
||||||
req.Changes = changesAfterSnapshot
|
req.Changes = changesAfterSnapshot
|
||||||
msg = spacesyncproto.WrapFullRequest(req, t.Header(), t.ID(), trackingId)
|
msg = treechangeproto.WrapFullRequest(req, t.Header())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *requestFactory) CreateFullSyncResponse(t tree.ObjectTree, theirHeads, theirSnapshotPath []string, trackingId string) (msg *spacesyncproto.ObjectSyncMessage, err error) {
|
func (r *requestFactory) CreateFullSyncResponse(t tree.ObjectTree, theirHeads, theirSnapshotPath []string) (msg *treechangeproto.TreeSyncMessage, err error) {
|
||||||
resp := &spacesyncproto.ObjectFullSyncResponse{
|
resp := &treechangeproto.TreeFullSyncResponse{
|
||||||
Heads: t.Heads(),
|
Heads: t.Heads(),
|
||||||
SnapshotPath: t.SnapshotPath(),
|
SnapshotPath: t.SnapshotPath(),
|
||||||
}
|
}
|
||||||
if slice.UnsortedEquals(theirHeads, t.Heads()) {
|
if slice.UnsortedEquals(theirHeads, t.Heads()) {
|
||||||
msg = spacesyncproto.WrapFullResponse(resp, t.Header(), t.ID(), trackingId)
|
msg = treechangeproto.WrapFullResponse(resp, t.Header())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +69,6 @@ func (r *requestFactory) CreateFullSyncResponse(t tree.ObjectTree, theirHeads, t
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp.Changes = ourChanges
|
resp.Changes = ourChanges
|
||||||
msg = spacesyncproto.WrapFullResponse(resp, t.Header(), t.ID(), trackingId)
|
msg = treechangeproto.WrapFullResponse(resp, t.Header())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,15 +5,17 @@ import (
|
|||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"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/common/commonspace/syncservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SyncClient interface {
|
type SyncClient interface {
|
||||||
syncservice.StreamPool
|
|
||||||
RequestFactory
|
RequestFactory
|
||||||
ocache.ObjectLastUsage
|
ocache.ObjectLastUsage
|
||||||
BroadcastAsyncOrSendResponsible(message *spacesyncproto.ObjectSyncMessage) (err error)
|
BroadcastAsync(message *treechangeproto.TreeSyncMessage) (err error)
|
||||||
|
BroadcastAsyncOrSendResponsible(message *treechangeproto.TreeSyncMessage) (err error)
|
||||||
|
SendAsync(peerId string, message *treechangeproto.TreeSyncMessage, replyId string) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type syncClient struct {
|
type syncClient struct {
|
||||||
@ -43,21 +45,51 @@ func (s *syncClient) LastUsage() time.Time {
|
|||||||
return s.StreamPool.LastUsage()
|
return s.StreamPool.LastUsage()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncClient) BroadcastAsync(message *spacesyncproto.ObjectSyncMessage) (err error) {
|
func (s *syncClient) BroadcastAsync(message *treechangeproto.TreeSyncMessage) (err error) {
|
||||||
s.notifyIfNeeded(message)
|
s.notifyIfNeeded(message)
|
||||||
return s.StreamPool.BroadcastAsync(message)
|
objMsg, err := marshallTreeMessage(message, message.RootChange.Id, "")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return s.StreamPool.BroadcastAsync(objMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncClient) BroadcastAsyncOrSendResponsible(message *spacesyncproto.ObjectSyncMessage) (err error) {
|
func (s *syncClient) SendAsync(peerId string, message *treechangeproto.TreeSyncMessage, replyId string) (err error) {
|
||||||
|
objMsg, err := marshallTreeMessage(message, message.RootChange.Id, replyId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return s.StreamPool.SendAsync([]string{peerId}, objMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncClient) BroadcastAsyncOrSendResponsible(message *treechangeproto.TreeSyncMessage) (err error) {
|
||||||
|
s.notifyIfNeeded(message)
|
||||||
|
objMsg, err := marshallTreeMessage(message, message.RootChange.Id, "")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if s.configuration.IsResponsible(s.spaceId) {
|
if s.configuration.IsResponsible(s.spaceId) {
|
||||||
return s.SendAsync(s.configuration.NodeIds(s.spaceId), message)
|
return s.StreamPool.SendAsync(s.configuration.NodeIds(s.spaceId), objMsg)
|
||||||
}
|
}
|
||||||
return s.BroadcastAsync(message)
|
return s.BroadcastAsync(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncClient) notifyIfNeeded(message *spacesyncproto.ObjectSyncMessage) {
|
func (s *syncClient) notifyIfNeeded(message *treechangeproto.TreeSyncMessage) {
|
||||||
if message.GetContent().GetHeadUpdate() != nil {
|
if message.GetContent().GetHeadUpdate() != nil {
|
||||||
update := message.GetContent().GetHeadUpdate()
|
update := message.GetContent().GetHeadUpdate()
|
||||||
s.notifiable.UpdateHeads(message.TreeId, update.Heads)
|
s.notifiable.UpdateHeads(message.RootChange.Id, update.Heads)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func marshallTreeMessage(message *treechangeproto.TreeSyncMessage, id, replyId string) (objMsg *spacesyncproto.ObjectSyncMessage, err error) {
|
||||||
|
payload, err := message.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
objMsg = &spacesyncproto.ObjectSyncMessage{
|
||||||
|
ReplyId: replyId,
|
||||||
|
Payload: payload,
|
||||||
|
ObjectId: id,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/diffservice"
|
||||||
|
spacestorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
||||||
@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrSyncTreeClosed = errors.New("sync tree is closed")
|
var ErrSyncTreeClosed = errors.New("sync tree is closed")
|
||||||
@ -50,7 +52,8 @@ type BuildDeps struct {
|
|||||||
HeadNotifiable diffservice.HeadNotifiable
|
HeadNotifiable diffservice.HeadNotifiable
|
||||||
Listener updatelistener.UpdateListener
|
Listener updatelistener.UpdateListener
|
||||||
AclList list.ACLList
|
AclList list.ACLList
|
||||||
Storage storage.TreeStorage
|
SpaceStorage spacestorage.SpaceStorage
|
||||||
|
TreeStorage storage.TreeStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeriveSyncTree(
|
func DeriveSyncTree(
|
||||||
@ -107,12 +110,72 @@ func CreateSyncTree(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BuildSyncTreeOrGetRemote(ctx context.Context, id string, deps BuildDeps) (t tree.ObjectTree, err error) {
|
||||||
|
getTreeRemote := func() (msg *treechangeproto.TreeSyncMessage, err error) {
|
||||||
|
// TODO: add empty context handling (when this is not happening due to head update)
|
||||||
|
peerId, err := syncservice.GetPeerIdFromStreamContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newTreeRequest := GetRequestFactory().CreateNewTreeRequest()
|
||||||
|
objMsg, err := marshallTreeMessage(newTreeRequest, id, "")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := deps.StreamPool.SendSync(peerId, objMsg)
|
||||||
|
if resp != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg = &treechangeproto.TreeSyncMessage{}
|
||||||
|
err = proto.Unmarshal(resp.Payload, msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
store, err := deps.SpaceStorage.TreeStorage(id)
|
||||||
|
if err != nil && err != storage.ErrUnknownTreeId {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isFirstBuild := false
|
||||||
|
if err == storage.ErrUnknownTreeId {
|
||||||
|
isFirstBuild = true
|
||||||
|
|
||||||
|
var resp *treechangeproto.TreeSyncMessage
|
||||||
|
resp, err = getTreeRemote()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fullSyncResp := resp.GetContent().GetFullSyncResponse()
|
||||||
|
|
||||||
|
payload := storage.TreeStorageCreatePayload{
|
||||||
|
TreeId: id,
|
||||||
|
RootRawChange: resp.RootChange,
|
||||||
|
Changes: fullSyncResp.Changes,
|
||||||
|
Heads: fullSyncResp.Heads,
|
||||||
|
}
|
||||||
|
|
||||||
|
// basically building tree with inmemory storage and validating that it was without errors
|
||||||
|
err = tree.ValidateRawTree(payload, deps.AclList)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// now we are sure that we can save it to the storage
|
||||||
|
store, err = deps.SpaceStorage.CreateTreeStorage(payload)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deps.TreeStorage = store
|
||||||
|
return BuildSyncTree(ctx, isFirstBuild, deps)
|
||||||
|
}
|
||||||
|
|
||||||
func BuildSyncTree(
|
func BuildSyncTree(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
isFirstBuild bool,
|
isFirstBuild bool,
|
||||||
deps BuildDeps) (t tree.ObjectTree, err error) {
|
deps BuildDeps) (t tree.ObjectTree, err error) {
|
||||||
|
|
||||||
t, err = buildObjectTree(deps.Storage, deps.AclList)
|
t, err = buildObjectTree(deps.TreeStorage, deps.AclList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,9 @@ import (
|
|||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type syncTreeHandler struct {
|
type syncTreeHandler struct {
|
||||||
@ -20,15 +22,21 @@ func newSyncTreeHandler(objTree tree.ObjectTree, syncClient SyncClient) synchand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncTreeHandler) HandleMessage(ctx context.Context, senderId string, msg *spacesyncproto.ObjectSyncMessage) error {
|
func (s *syncTreeHandler) HandleMessage(ctx context.Context, senderId string, msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
content := msg.GetContent()
|
unmarshalled := &treechangeproto.TreeSyncMessage{}
|
||||||
|
err = proto.Unmarshal(msg.Payload, unmarshalled)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
content := unmarshalled.GetContent()
|
||||||
switch {
|
switch {
|
||||||
case content.GetFullSyncRequest() != nil:
|
|
||||||
return s.handleFullSyncRequest(ctx, senderId, content.GetFullSyncRequest(), msg)
|
|
||||||
case content.GetFullSyncResponse() != nil:
|
|
||||||
return s.handleFullSyncResponse(ctx, senderId, content.GetFullSyncResponse(), msg)
|
|
||||||
case content.GetHeadUpdate() != nil:
|
case content.GetHeadUpdate() != nil:
|
||||||
return s.handleHeadUpdate(ctx, senderId, content.GetHeadUpdate(), msg)
|
return s.handleHeadUpdate(ctx, senderId, content.GetHeadUpdate(), msg.ReplyId)
|
||||||
|
case content.GetFullSyncRequest() != nil:
|
||||||
|
return s.handleFullSyncRequest(ctx, senderId, content.GetFullSyncRequest(), msg.ReplyId)
|
||||||
|
case content.GetFullSyncResponse() != nil:
|
||||||
|
return s.handleFullSyncResponse(ctx, senderId, content.GetFullSyncResponse())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -36,14 +44,14 @@ func (s *syncTreeHandler) HandleMessage(ctx context.Context, senderId string, ms
|
|||||||
func (s *syncTreeHandler) handleHeadUpdate(
|
func (s *syncTreeHandler) handleHeadUpdate(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
senderId string,
|
senderId string,
|
||||||
update *spacesyncproto.ObjectHeadUpdate,
|
update *treechangeproto.TreeHeadUpdate,
|
||||||
msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
replyId string) (err error) {
|
||||||
log.With("senderId", senderId).
|
log.With("senderId", senderId).
|
||||||
With("heads", update.Heads).
|
With("heads", update.Heads).
|
||||||
With("treeId", msg.TreeId).
|
With("treeId", s.objTree.ID()).
|
||||||
Debug("received head update message")
|
Debug("received head update message")
|
||||||
var (
|
var (
|
||||||
fullRequest *spacesyncproto.ObjectSyncMessage
|
fullRequest *treechangeproto.TreeSyncMessage
|
||||||
isEmptyUpdate = len(update.Changes) == 0
|
isEmptyUpdate = len(update.Changes) == 0
|
||||||
objTree = s.objTree
|
objTree = s.objTree
|
||||||
)
|
)
|
||||||
@ -54,12 +62,12 @@ func (s *syncTreeHandler) handleHeadUpdate(
|
|||||||
|
|
||||||
// isEmptyUpdate is sent when the tree is brought up from cache
|
// isEmptyUpdate is sent when the tree is brought up from cache
|
||||||
if isEmptyUpdate {
|
if isEmptyUpdate {
|
||||||
log.With("treeId", msg.TreeId).Debug("is empty update")
|
log.With("treeId", objTree.ID()).Debug("is empty update")
|
||||||
if slice.UnsortedEquals(objTree.Heads(), update.Heads) {
|
if slice.UnsortedEquals(objTree.Heads(), update.Heads) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// we need to sync in any case
|
// we need to sync in any case
|
||||||
fullRequest, err = s.syncClient.CreateFullSyncRequest(objTree, update.Heads, update.SnapshotPath, msg.TrackingId)
|
fullRequest, err = s.syncClient.CreateFullSyncRequest(objTree, update.Heads, update.SnapshotPath)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,20 +84,20 @@ func (s *syncTreeHandler) handleHeadUpdate(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fullRequest, err = s.syncClient.CreateFullSyncRequest(objTree, update.Heads, update.SnapshotPath, msg.TrackingId)
|
fullRequest, err = s.syncClient.CreateFullSyncRequest(objTree, update.Heads, update.SnapshotPath)
|
||||||
return err
|
return err
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if fullRequest != nil {
|
if fullRequest != nil {
|
||||||
log.With("senderId", senderId).
|
log.With("senderId", senderId).
|
||||||
With("heads", fullRequest.GetContent().GetFullSyncRequest().Heads).
|
With("heads", fullRequest.GetContent().GetFullSyncRequest().Heads).
|
||||||
With("treeId", msg.TreeId).
|
With("treeId", objTree.ID()).
|
||||||
Debug("sending full sync request")
|
Debug("sending full sync request")
|
||||||
return s.syncClient.SendAsync([]string{senderId}, fullRequest)
|
return s.syncClient.SendAsync(senderId, fullRequest, replyId)
|
||||||
}
|
}
|
||||||
log.With("senderId", senderId).
|
log.With("senderId", senderId).
|
||||||
With("heads", update.Heads).
|
With("heads", update.Heads).
|
||||||
With("treeId", msg.TreeId).
|
With("treeId", objTree.ID()).
|
||||||
Debug("head update finished correctly")
|
Debug("head update finished correctly")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -97,21 +105,21 @@ func (s *syncTreeHandler) handleHeadUpdate(
|
|||||||
func (s *syncTreeHandler) handleFullSyncRequest(
|
func (s *syncTreeHandler) handleFullSyncRequest(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
senderId string,
|
senderId string,
|
||||||
request *spacesyncproto.ObjectFullSyncRequest,
|
request *treechangeproto.TreeFullSyncRequest,
|
||||||
msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
replyId string) (err error) {
|
||||||
log.With("senderId", senderId).
|
log.With("senderId", senderId).
|
||||||
With("heads", request.Heads).
|
With("heads", request.Heads).
|
||||||
With("treeId", msg.TreeId).
|
With("treeId", s.objTree.ID()).
|
||||||
With("trackingId", msg.TrackingId).
|
With("trackingId", replyId).
|
||||||
Debug("received full sync request message")
|
Debug("received full sync request message")
|
||||||
var (
|
var (
|
||||||
fullResponse *spacesyncproto.ObjectSyncMessage
|
fullResponse *treechangeproto.TreeSyncMessage
|
||||||
header = msg.RootChange
|
header = s.objTree.Header()
|
||||||
objTree = s.objTree
|
objTree = s.objTree
|
||||||
)
|
)
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.syncClient.SendAsync([]string{senderId}, spacesyncproto.WrapError(err, header, msg.TreeId, msg.TrackingId))
|
s.syncClient.SendAsync(senderId, treechangeproto.WrapError(err, header), replyId)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -130,30 +138,29 @@ func (s *syncTreeHandler) handleFullSyncRequest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fullResponse, err = s.syncClient.CreateFullSyncResponse(objTree, request.Heads, request.SnapshotPath, msg.TrackingId)
|
fullResponse, err = s.syncClient.CreateFullSyncResponse(objTree, request.Heads, request.SnapshotPath)
|
||||||
return err
|
return err
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return s.syncClient.SendAsync([]string{senderId}, fullResponse)
|
return s.syncClient.SendAsync(senderId, fullResponse, replyId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncTreeHandler) handleFullSyncResponse(
|
func (s *syncTreeHandler) handleFullSyncResponse(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
senderId string,
|
senderId string,
|
||||||
response *spacesyncproto.ObjectFullSyncResponse,
|
response *treechangeproto.TreeFullSyncResponse) (err error) {
|
||||||
msg *spacesyncproto.ObjectSyncMessage) (err error) {
|
|
||||||
log.With("senderId", senderId).
|
log.With("senderId", senderId).
|
||||||
With("heads", response.Heads).
|
With("heads", response.Heads).
|
||||||
With("treeId", msg.TreeId).
|
With("treeId", s.objTree.ID()).
|
||||||
Debug("received full sync response message")
|
Debug("received full sync response message")
|
||||||
objTree := s.objTree
|
objTree := s.objTree
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.With("senderId", senderId).
|
log.With("senderId", senderId).
|
||||||
With("heads", response.Heads).
|
With("heads", response.Heads).
|
||||||
With("treeId", msg.TreeId).
|
With("treeId", s.objTree.ID()).
|
||||||
Debug("failed to find the tree in full sync response")
|
Debug("failed to find the tree in full sync response")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -170,7 +177,7 @@ func (s *syncTreeHandler) handleFullSyncResponse(
|
|||||||
}()
|
}()
|
||||||
log.With("error", err != nil).
|
log.With("error", err != nil).
|
||||||
With("heads", response.Heads).
|
With("heads", response.Heads).
|
||||||
With("treeId", msg.TreeId).
|
With("treeId", s.objTree.ID()).
|
||||||
Debug("finished full sync response")
|
Debug("finished full sync response")
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|||||||
@ -271,7 +271,7 @@ func (mr *MockObjectTreeMockRecorder) SnapshotPath() *gomock.Call {
|
|||||||
// Storage mocks base method.
|
// Storage mocks base method.
|
||||||
func (m *MockObjectTree) Storage() storage.TreeStorage {
|
func (m *MockObjectTree) Storage() storage.TreeStorage {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "Storage")
|
ret := m.ctrl.Call(m, "SpaceStorage")
|
||||||
ret0, _ := ret[0].(storage.TreeStorage)
|
ret0, _ := ret[0].(storage.TreeStorage)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
@ -279,7 +279,7 @@ func (m *MockObjectTree) Storage() storage.TreeStorage {
|
|||||||
// Storage indicates an expected call of Storage.
|
// Storage indicates an expected call of Storage.
|
||||||
func (mr *MockObjectTreeMockRecorder) Storage() *gomock.Call {
|
func (mr *MockObjectTreeMockRecorder) Storage() *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Storage", reflect.TypeOf((*MockObjectTree)(nil).Storage))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpaceStorage", reflect.TypeOf((*MockObjectTree)(nil).Storage))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock mocks base method.
|
// Unlock mocks base method.
|
||||||
|
|||||||
@ -53,3 +53,44 @@ message RawTreeChangeWithId {
|
|||||||
// Id is a cid made from rawChange payload
|
// Id is a cid made from rawChange payload
|
||||||
string id = 2;
|
string id = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message TreeSyncMessage {
|
||||||
|
TreeSyncContentValue content = 1;
|
||||||
|
RawTreeChangeWithId rootChange = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeSyncContentValue provides different types for tree sync
|
||||||
|
message TreeSyncContentValue {
|
||||||
|
oneof value {
|
||||||
|
TreeHeadUpdate headUpdate = 1;
|
||||||
|
TreeFullSyncRequest fullSyncRequest = 2;
|
||||||
|
TreeFullSyncResponse fullSyncResponse = 3;
|
||||||
|
TreeErrorResponse errorResponse = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeHeadUpdate is a message sent on document head update
|
||||||
|
message TreeHeadUpdate {
|
||||||
|
repeated string heads = 1;
|
||||||
|
repeated RawTreeChangeWithId changes = 2;
|
||||||
|
repeated string snapshotPath = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeHeadUpdate is a message sent when document needs full sync
|
||||||
|
message TreeFullSyncRequest {
|
||||||
|
repeated string heads = 1;
|
||||||
|
repeated RawTreeChangeWithId changes = 2;
|
||||||
|
repeated string snapshotPath = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeFullSyncResponse is a message sent as a response for a specific full sync
|
||||||
|
message TreeFullSyncResponse {
|
||||||
|
repeated string heads = 1;
|
||||||
|
repeated RawTreeChangeWithId changes = 2;
|
||||||
|
repeated string snapshotPath = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeErrorResponse is an error sent as a response for a full sync request
|
||||||
|
message TreeErrorResponse {
|
||||||
|
string error = 1;
|
||||||
|
}
|
||||||
|
|||||||
37
common/pkg/acl/treechangeproto/treechange.go
Normal file
37
common/pkg/acl/treechangeproto/treechange.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package treechangeproto
|
||||||
|
|
||||||
|
func WrapHeadUpdate(update *TreeHeadUpdate, rootChange *RawTreeChangeWithId) *TreeSyncMessage {
|
||||||
|
return &TreeSyncMessage{
|
||||||
|
Content: &TreeSyncContentValue{
|
||||||
|
Value: &TreeSyncContentValue_HeadUpdate{HeadUpdate: update},
|
||||||
|
},
|
||||||
|
RootChange: rootChange,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WrapFullRequest(request *TreeFullSyncRequest, rootChange *RawTreeChangeWithId) *TreeSyncMessage {
|
||||||
|
return &TreeSyncMessage{
|
||||||
|
Content: &TreeSyncContentValue{
|
||||||
|
Value: &TreeSyncContentValue_FullSyncRequest{FullSyncRequest: request},
|
||||||
|
},
|
||||||
|
RootChange: rootChange,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WrapFullResponse(response *TreeFullSyncResponse, rootChange *RawTreeChangeWithId) *TreeSyncMessage {
|
||||||
|
return &TreeSyncMessage{
|
||||||
|
Content: &TreeSyncContentValue{
|
||||||
|
Value: &TreeSyncContentValue_FullSyncResponse{FullSyncResponse: response},
|
||||||
|
},
|
||||||
|
RootChange: rootChange,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WrapError(err error, rootChange *RawTreeChangeWithId) *TreeSyncMessage {
|
||||||
|
return &TreeSyncMessage{
|
||||||
|
Content: &TreeSyncContentValue{
|
||||||
|
Value: &TreeSyncContentValue_ErrorResponse{ErrorResponse: &TreeErrorResponse{Error: err.Error()}},
|
||||||
|
},
|
||||||
|
RootChange: rootChange,
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user