WIP sync refactoring
This commit is contained in:
parent
cec48d1c44
commit
e289fd4f89
35
common/commonspace/commongetter.go
Normal file
35
common/commonspace/commongetter.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package commonspace
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/objectgetter"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncacl"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
|
||||||
|
)
|
||||||
|
|
||||||
|
type commonSpaceGetter struct {
|
||||||
|
spaceId string
|
||||||
|
aclList *syncacl.SyncACL
|
||||||
|
treeGetter treegetter.TreeGetter
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCommonSpaceGetter(spaceId string, aclList *syncacl.SyncACL, treeGetter treegetter.TreeGetter) objectgetter.ObjectGetter {
|
||||||
|
return &commonSpaceGetter{
|
||||||
|
spaceId: spaceId,
|
||||||
|
aclList: aclList,
|
||||||
|
treeGetter: treeGetter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *commonSpaceGetter) GetObject(ctx context.Context, objectId string) (obj objectgetter.Object, err error) {
|
||||||
|
if c.aclList.ID() == objectId {
|
||||||
|
obj = c.aclList
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t, err := c.treeGetter.GetTree(ctx, c.spaceId, objectId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
obj = t.(objectgetter.Object)
|
||||||
|
return
|
||||||
|
}
|
||||||
14
common/commonspace/objectgetter/objectgetter.go
Normal file
14
common/commonspace/objectgetter/objectgetter.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package objectgetter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Object interface {
|
||||||
|
synchandler.SyncHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
type ObjectGetter interface {
|
||||||
|
GetObject(ctx context.Context, objectId string) (Object, error)
|
||||||
|
}
|
||||||
@ -87,10 +87,11 @@ func (s *service) GetSpace(ctx context.Context, id string) (Space, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lastConfiguration := s.configurationService.GetLast()
|
lastConfiguration := s.configurationService.GetLast()
|
||||||
confConnector := nodeconf.NewConfConnector(lastConfiguration, s.pool)
|
confConnector := nodeconf.NewConfConnector(lastConfiguration, s.pool)
|
||||||
diffService := diffservice.NewDiffService(id, s.config.SyncPeriod, st, confConnector, s.cache, log)
|
diffService := diffservice.NewDiffService(id, s.config.SyncPeriod, st, confConnector, s.cache, log)
|
||||||
syncService := syncservice.NewSyncService(id, diffService, s.cache, lastConfiguration, confConnector)
|
syncService := syncservice.NewSyncService(id, diffService, lastConfiguration, confConnector)
|
||||||
sp := &space{
|
sp := &space{
|
||||||
id: id,
|
id: id,
|
||||||
syncService: syncService,
|
syncService: syncService,
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"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/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/syncservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
||||||
@ -73,7 +74,7 @@ type space struct {
|
|||||||
storage storage.SpaceStorage
|
storage storage.SpaceStorage
|
||||||
cache treegetter.TreeGetter
|
cache treegetter.TreeGetter
|
||||||
account account.Service
|
account account.Service
|
||||||
aclList list.ACLList
|
aclList *syncacl.SyncACL
|
||||||
|
|
||||||
isClosed atomic.Bool
|
isClosed atomic.Bool
|
||||||
}
|
}
|
||||||
@ -96,12 +97,14 @@ func (s *space) Init(ctx context.Context) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.aclList, err = list.BuildACLListWithIdentity(s.account.Account(), aclStorage)
|
aclList, err := list.BuildACLListWithIdentity(s.account.Account(), aclStorage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.aclList = syncacl.NewSyncACL(aclList, s.syncService.SyncClient())
|
||||||
|
objectGetter := newCommonSpaceGetter(s.id, s.aclList, s.cache)
|
||||||
|
s.syncService.Init(objectGetter)
|
||||||
s.diffService.Init(initialIds)
|
s.diffService.Init(initialIds)
|
||||||
s.syncService.Init()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +129,14 @@ func (s *space) DeriveTree(ctx context.Context, payload tree.ObjectTreeCreatePay
|
|||||||
err = ErrSpaceClosed
|
err = ErrSpaceClosed
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return synctree.DeriveSyncTree(ctx, payload, s.syncService.SyncClient(), listener, s.aclList, s.storage.CreateTreeStorage)
|
deps := synctree.SyncTreeCreateDeps{
|
||||||
|
Payload: payload,
|
||||||
|
SyncClient: s.syncService.SyncClient(),
|
||||||
|
Listener: listener,
|
||||||
|
AclList: s.aclList,
|
||||||
|
CreateStorage: s.storage.CreateTreeStorage,
|
||||||
|
}
|
||||||
|
return synctree.DeriveSyncTree(ctx, deps)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) CreateTree(ctx context.Context, payload tree.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tr tree.ObjectTree, err error) {
|
func (s *space) CreateTree(ctx context.Context, payload tree.ObjectTreeCreatePayload, listener updatelistener.UpdateListener) (tr tree.ObjectTree, err error) {
|
||||||
@ -134,7 +144,14 @@ func (s *space) CreateTree(ctx context.Context, payload tree.ObjectTreeCreatePay
|
|||||||
err = ErrSpaceClosed
|
err = ErrSpaceClosed
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return synctree.CreateSyncTree(ctx, payload, s.syncService.SyncClient(), listener, s.aclList, s.storage.CreateTreeStorage)
|
deps := synctree.SyncTreeCreateDeps{
|
||||||
|
Payload: payload,
|
||||||
|
SyncClient: s.syncService.SyncClient(),
|
||||||
|
Listener: listener,
|
||||||
|
AclList: s.aclList,
|
||||||
|
CreateStorage: s.storage.CreateTreeStorage,
|
||||||
|
}
|
||||||
|
return synctree.CreateSyncTree(ctx, deps)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) BuildTree(ctx context.Context, id string, listener updatelistener.UpdateListener) (t tree.ObjectTree, err error) {
|
func (s *space) BuildTree(ctx context.Context, id string, listener updatelistener.UpdateListener) (t tree.ObjectTree, err error) {
|
||||||
@ -187,7 +204,13 @@ func (s *space) BuildTree(ctx context.Context, id string, listener updatelistene
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return synctree.BuildSyncTree(ctx, s.syncService.SyncClient(), store.(aclstorage.TreeStorage), listener, s.aclList, isFirstBuild)
|
deps := synctree.SyncTreeBuildDeps{
|
||||||
|
SyncClient: s.syncService.SyncClient(),
|
||||||
|
Listener: listener,
|
||||||
|
AclList: s.aclList,
|
||||||
|
Storage: store,
|
||||||
|
}
|
||||||
|
return synctree.BuildSyncTree(ctx, isFirstBuild, deps)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) Close() error {
|
func (s *space) Close() error {
|
||||||
|
|||||||
21
common/commonspace/syncacl/syncacl.go
Normal file
21
common/commonspace/syncacl/syncacl.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package syncacl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"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/pkg/acl/list"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SyncACL struct {
|
||||||
|
list.ACLList
|
||||||
|
syncservice.SyncClient
|
||||||
|
synchandler.SyncHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSyncACL(aclList list.ACLList, syncClient syncservice.SyncClient) *SyncACL {
|
||||||
|
return &SyncACL{
|
||||||
|
ACLList: aclList,
|
||||||
|
SyncClient: syncClient,
|
||||||
|
SyncHandler: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
10
common/commonspace/syncservice/synchandler/synchhandler.go
Normal file
10
common/commonspace/syncservice/synchandler/synchhandler.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package synchandler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SyncHandler interface {
|
||||||
|
HandleMessage(ctx context.Context, senderId string, request *spacesyncproto.ObjectSyncMessage) (err error)
|
||||||
|
}
|
||||||
@ -4,8 +4,9 @@ package syncservice
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"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/objectgetter"
|
||||||
"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/treegetter"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpcerr"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpcerr"
|
||||||
"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/ocache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
||||||
@ -16,9 +17,10 @@ var log = logger.NewNamed("syncservice").Sugar()
|
|||||||
|
|
||||||
type SyncService interface {
|
type SyncService interface {
|
||||||
ocache.ObjectLastUsage
|
ocache.ObjectLastUsage
|
||||||
|
synchandler.SyncHandler
|
||||||
SyncClient() SyncClient
|
SyncClient() SyncClient
|
||||||
|
|
||||||
Init()
|
Init(getter objectgetter.ObjectGetter)
|
||||||
Close() (err error)
|
Close() (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +35,7 @@ type syncService struct {
|
|||||||
|
|
||||||
syncClient SyncClient
|
syncClient SyncClient
|
||||||
clientFactory spacesyncproto.ClientFactory
|
clientFactory spacesyncproto.ClientFactory
|
||||||
|
objectGetter objectgetter.ObjectGetter
|
||||||
|
|
||||||
streamLoopCtx context.Context
|
streamLoopCtx context.Context
|
||||||
stopStreamLoop context.CancelFunc
|
stopStreamLoop context.CancelFunc
|
||||||
@ -43,25 +46,19 @@ type syncService struct {
|
|||||||
func NewSyncService(
|
func NewSyncService(
|
||||||
spaceId string,
|
spaceId string,
|
||||||
headNotifiable HeadNotifiable,
|
headNotifiable HeadNotifiable,
|
||||||
cache treegetter.TreeGetter,
|
|
||||||
configuration nodeconf.Configuration,
|
configuration nodeconf.Configuration,
|
||||||
confConnector nodeconf.ConfConnector) SyncService {
|
confConnector nodeconf.ConfConnector) (syncService SyncService) {
|
||||||
var syncHandler SyncHandler
|
|
||||||
streamPool := newStreamPool(func(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
streamPool := newStreamPool(func(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
return syncHandler.HandleMessage(ctx, senderId, message)
|
return syncService.HandleMessage(ctx, senderId, message)
|
||||||
})
|
})
|
||||||
factory := newRequestFactory()
|
factory := newRequestFactory()
|
||||||
syncClient := newSyncClient(spaceId, streamPool, headNotifiable, factory, configuration)
|
syncClient := newSyncClient(spaceId, streamPool, headNotifiable, factory, configuration)
|
||||||
syncHandler = newSyncHandler(spaceId, cache, syncClient)
|
syncService = newSyncService(
|
||||||
return newSyncService(
|
|
||||||
spaceId,
|
spaceId,
|
||||||
syncClient,
|
syncClient,
|
||||||
spacesyncproto.ClientFactoryFunc(spacesyncproto.NewDRPCSpaceClient),
|
spacesyncproto.ClientFactoryFunc(spacesyncproto.NewDRPCSpaceClient),
|
||||||
confConnector)
|
confConnector)
|
||||||
}
|
return
|
||||||
|
|
||||||
func (s *syncService) LastUsage() time.Time {
|
|
||||||
return s.syncClient.LastUsage()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSyncService(
|
func newSyncService(
|
||||||
@ -78,7 +75,8 @@ func newSyncService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncService) Init() {
|
func (s *syncService) Init(objectGetter objectgetter.ObjectGetter) {
|
||||||
|
s.objectGetter = objectGetter
|
||||||
s.streamLoopCtx, s.stopStreamLoop = context.WithCancel(context.Background())
|
s.streamLoopCtx, s.stopStreamLoop = context.WithCancel(context.Background())
|
||||||
go s.responsibleStreamCheckLoop(s.streamLoopCtx)
|
go s.responsibleStreamCheckLoop(s.streamLoopCtx)
|
||||||
}
|
}
|
||||||
@ -89,6 +87,18 @@ func (s *syncService) Close() (err error) {
|
|||||||
return s.syncClient.Close()
|
return s.syncClient.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *syncService) LastUsage() time.Time {
|
||||||
|
return s.syncClient.LastUsage()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *syncService) HandleMessage(ctx context.Context, senderId string, message *spacesyncproto.ObjectSyncMessage) (err error) {
|
||||||
|
obj, err := s.objectGetter.GetObject(ctx, message.TreeId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return obj.HandleMessage(ctx, senderId, message)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *syncService) responsibleStreamCheckLoop(ctx context.Context) {
|
func (s *syncService) responsibleStreamCheckLoop(ctx context.Context) {
|
||||||
defer close(s.streamLoopDone)
|
defer close(s.streamLoopDone)
|
||||||
checkResponsiblePeers := func() {
|
checkResponsiblePeers := func() {
|
||||||
|
|||||||
@ -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/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/synctree/updatelistener"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/synctree/updatelistener"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
|
||||||
@ -17,6 +18,7 @@ var ErrSyncTreeClosed = errors.New("sync tree is closed")
|
|||||||
// SyncTree sends head updates to sync service and also sends new changes to update listener
|
// SyncTree sends head updates to sync service and also sends new changes to update listener
|
||||||
type SyncTree struct {
|
type SyncTree struct {
|
||||||
tree.ObjectTree
|
tree.ObjectTree
|
||||||
|
synchandler.SyncHandler
|
||||||
syncClient syncservice.SyncClient
|
syncClient syncservice.SyncClient
|
||||||
listener updatelistener.UpdateListener
|
listener updatelistener.UpdateListener
|
||||||
isClosed bool
|
isClosed bool
|
||||||
@ -28,85 +30,89 @@ var createDerivedObjectTree = tree.CreateDerivedObjectTree
|
|||||||
var createObjectTree = tree.CreateObjectTree
|
var createObjectTree = tree.CreateObjectTree
|
||||||
var buildObjectTree = tree.BuildObjectTree
|
var buildObjectTree = tree.BuildObjectTree
|
||||||
|
|
||||||
|
type SyncTreeCreateDeps struct {
|
||||||
|
Payload tree.ObjectTreeCreatePayload
|
||||||
|
SyncClient syncservice.SyncClient
|
||||||
|
Listener updatelistener.UpdateListener
|
||||||
|
AclList list.ACLList
|
||||||
|
CreateStorage storage.TreeStorageCreatorFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
type SyncTreeBuildDeps struct {
|
||||||
|
SyncClient syncservice.SyncClient
|
||||||
|
Listener updatelistener.UpdateListener
|
||||||
|
AclList list.ACLList
|
||||||
|
Storage storage.TreeStorage
|
||||||
|
}
|
||||||
|
|
||||||
func DeriveSyncTree(
|
func DeriveSyncTree(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
payload tree.ObjectTreeCreatePayload,
|
deps SyncTreeCreateDeps) (t tree.ObjectTree, err error) {
|
||||||
syncClient syncservice.SyncClient,
|
t, err = createDerivedObjectTree(deps.Payload, deps.AclList, deps.CreateStorage)
|
||||||
listener updatelistener.UpdateListener,
|
|
||||||
aclList list.ACLList,
|
|
||||||
createStorage storage.TreeStorageCreatorFunc) (t tree.ObjectTree, err error) {
|
|
||||||
t, err = createDerivedObjectTree(payload, aclList, createStorage)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t = &SyncTree{
|
syncTree := &SyncTree{
|
||||||
ObjectTree: t,
|
ObjectTree: t,
|
||||||
syncClient: syncClient,
|
syncClient: deps.SyncClient,
|
||||||
listener: listener,
|
listener: deps.Listener,
|
||||||
}
|
}
|
||||||
|
syncHandler := newSyncTreeHandler(syncTree, deps.SyncClient)
|
||||||
|
syncTree.SyncHandler = syncHandler
|
||||||
|
t = syncTree
|
||||||
|
|
||||||
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
headUpdate := deps.SyncClient.CreateHeadUpdate(t, nil)
|
||||||
err = syncClient.BroadcastAsync(headUpdate)
|
err = deps.SyncClient.BroadcastAsync(headUpdate)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateSyncTree(
|
func CreateSyncTree(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
payload tree.ObjectTreeCreatePayload,
|
deps SyncTreeCreateDeps) (t tree.ObjectTree, err error) {
|
||||||
syncClient syncservice.SyncClient,
|
t, err = createObjectTree(deps.Payload, deps.AclList, deps.CreateStorage)
|
||||||
listener updatelistener.UpdateListener,
|
|
||||||
aclList list.ACLList,
|
|
||||||
createStorage storage.TreeStorageCreatorFunc) (t tree.ObjectTree, err error) {
|
|
||||||
t, err = createObjectTree(payload, aclList, createStorage)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t = &SyncTree{
|
syncTree := &SyncTree{
|
||||||
ObjectTree: t,
|
ObjectTree: t,
|
||||||
syncClient: syncClient,
|
syncClient: deps.SyncClient,
|
||||||
listener: listener,
|
listener: deps.Listener,
|
||||||
}
|
}
|
||||||
|
syncHandler := newSyncTreeHandler(syncTree, deps.SyncClient)
|
||||||
|
syncTree.SyncHandler = syncHandler
|
||||||
|
t = syncTree
|
||||||
|
|
||||||
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
headUpdate := deps.SyncClient.CreateHeadUpdate(t, nil)
|
||||||
err = syncClient.BroadcastAsync(headUpdate)
|
err = deps.SyncClient.BroadcastAsync(headUpdate)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildSyncTree(
|
func BuildSyncTree(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
syncClient syncservice.SyncClient,
|
isFirstBuild bool,
|
||||||
treeStorage storage.TreeStorage,
|
deps SyncTreeBuildDeps) (t tree.ObjectTree, err error) {
|
||||||
listener updatelistener.UpdateListener,
|
|
||||||
aclList list.ACLList,
|
|
||||||
isFirstBuild bool) (t tree.ObjectTree, err error) {
|
|
||||||
return buildSyncTree(ctx, syncClient, treeStorage, listener, aclList, isFirstBuild)
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildSyncTree(
|
t, err = buildObjectTree(deps.Storage, deps.AclList)
|
||||||
ctx context.Context,
|
|
||||||
syncClient syncservice.SyncClient,
|
|
||||||
treeStorage storage.TreeStorage,
|
|
||||||
listener updatelistener.UpdateListener,
|
|
||||||
aclList list.ACLList,
|
|
||||||
isFirstBuild bool) (t tree.ObjectTree, err error) {
|
|
||||||
t, err = buildObjectTree(treeStorage, aclList)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t = &SyncTree{
|
syncTree := &SyncTree{
|
||||||
ObjectTree: t,
|
ObjectTree: t,
|
||||||
syncClient: syncClient,
|
syncClient: deps.SyncClient,
|
||||||
listener: listener,
|
listener: deps.Listener,
|
||||||
}
|
}
|
||||||
|
syncHandler := newSyncTreeHandler(syncTree, deps.SyncClient)
|
||||||
|
syncTree.SyncHandler = syncHandler
|
||||||
|
t = syncTree
|
||||||
|
|
||||||
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
headUpdate := syncTree.syncClient.CreateHeadUpdate(t, nil)
|
||||||
// here we will have different behaviour based on who is sending this update
|
// here we will have different behaviour based on who is sending this update
|
||||||
if isFirstBuild {
|
if isFirstBuild {
|
||||||
// send to everybody, because everybody should know that the node or client got new tree
|
// send to everybody, because everybody should know that the node or client got new tree
|
||||||
err = syncClient.BroadcastAsync(headUpdate)
|
err = syncTree.syncClient.BroadcastAsync(headUpdate)
|
||||||
} else {
|
} else {
|
||||||
// send either to everybody if client or to replica set if node
|
// send either to everybody if client or to replica set if node
|
||||||
err = syncClient.BroadcastAsyncOrSendResponsible(headUpdate)
|
err = syncTree.syncClient.BroadcastAsyncOrSendResponsible(headUpdate)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,32 +1,27 @@
|
|||||||
package syncservice
|
package synctree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"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/treegetter"
|
"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/pkg/acl/tree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
type syncHandler struct {
|
type syncTreeHandler struct {
|
||||||
spaceId string
|
objTree tree.ObjectTree
|
||||||
treeCache treegetter.TreeGetter
|
syncClient syncservice.SyncClient
|
||||||
syncClient SyncClient
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SyncHandler interface {
|
func newSyncTreeHandler(objTree tree.ObjectTree, syncClient syncservice.SyncClient) synchandler.SyncHandler {
|
||||||
HandleMessage(ctx context.Context, senderId string, request *spacesyncproto.ObjectSyncMessage) (err error)
|
return &syncTreeHandler{
|
||||||
}
|
objTree: objTree,
|
||||||
|
|
||||||
func newSyncHandler(spaceId string, treeCache treegetter.TreeGetter, syncClient SyncClient) *syncHandler {
|
|
||||||
return &syncHandler{
|
|
||||||
spaceId: spaceId,
|
|
||||||
treeCache: treeCache,
|
|
||||||
syncClient: syncClient,
|
syncClient: syncClient,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncHandler) HandleMessage(ctx context.Context, senderId string, msg *spacesyncproto.ObjectSyncMessage) error {
|
func (s *syncTreeHandler) HandleMessage(ctx context.Context, senderId string, msg *spacesyncproto.ObjectSyncMessage) error {
|
||||||
content := msg.GetContent()
|
content := msg.GetContent()
|
||||||
switch {
|
switch {
|
||||||
case content.GetFullSyncRequest() != nil:
|
case content.GetFullSyncRequest() != nil:
|
||||||
@ -39,7 +34,7 @@ func (s *syncHandler) HandleMessage(ctx context.Context, senderId string, msg *s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncHandler) handleHeadUpdate(
|
func (s *syncTreeHandler) handleHeadUpdate(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
senderId string,
|
senderId string,
|
||||||
update *spacesyncproto.ObjectHeadUpdate,
|
update *spacesyncproto.ObjectHeadUpdate,
|
||||||
@ -51,11 +46,8 @@ func (s *syncHandler) handleHeadUpdate(
|
|||||||
var (
|
var (
|
||||||
fullRequest *spacesyncproto.ObjectSyncMessage
|
fullRequest *spacesyncproto.ObjectSyncMessage
|
||||||
isEmptyUpdate = len(update.Changes) == 0
|
isEmptyUpdate = len(update.Changes) == 0
|
||||||
|
objTree = s.objTree
|
||||||
)
|
)
|
||||||
objTree, err := s.treeCache.GetTree(ctx, s.spaceId, msg.TreeId)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = func() error {
|
err = func() error {
|
||||||
objTree.Lock()
|
objTree.Lock()
|
||||||
@ -63,6 +55,7 @@ func (s *syncHandler) 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")
|
||||||
if slice.UnsortedEquals(objTree.Heads(), update.Heads) {
|
if slice.UnsortedEquals(objTree.Heads(), update.Heads) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -102,7 +95,7 @@ func (s *syncHandler) handleHeadUpdate(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncHandler) handleFullSyncRequest(
|
func (s *syncTreeHandler) handleFullSyncRequest(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
senderId string,
|
senderId string,
|
||||||
request *spacesyncproto.ObjectFullSyncRequest,
|
request *spacesyncproto.ObjectFullSyncRequest,
|
||||||
@ -115,6 +108,7 @@ func (s *syncHandler) handleFullSyncRequest(
|
|||||||
var (
|
var (
|
||||||
fullResponse *spacesyncproto.ObjectSyncMessage
|
fullResponse *spacesyncproto.ObjectSyncMessage
|
||||||
header = msg.RootChange
|
header = msg.RootChange
|
||||||
|
objTree = s.objTree
|
||||||
)
|
)
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -122,11 +116,6 @@ func (s *syncHandler) handleFullSyncRequest(
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
objTree, err := s.treeCache.GetTree(ctx, s.spaceId, msg.TreeId)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = func() error {
|
err = func() error {
|
||||||
objTree.Lock()
|
objTree.Lock()
|
||||||
defer objTree.Unlock()
|
defer objTree.Unlock()
|
||||||
@ -152,7 +141,7 @@ func (s *syncHandler) handleFullSyncRequest(
|
|||||||
return s.syncClient.SendAsync([]string{senderId}, fullResponse)
|
return s.syncClient.SendAsync([]string{senderId}, fullResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncHandler) handleFullSyncResponse(
|
func (s *syncTreeHandler) handleFullSyncResponse(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
senderId string,
|
senderId string,
|
||||||
response *spacesyncproto.ObjectFullSyncResponse,
|
response *spacesyncproto.ObjectFullSyncResponse,
|
||||||
@ -161,7 +150,7 @@ func (s *syncHandler) handleFullSyncResponse(
|
|||||||
With("heads", response.Heads).
|
With("heads", response.Heads).
|
||||||
With("treeId", msg.TreeId).
|
With("treeId", msg.TreeId).
|
||||||
Debug("received full sync response message")
|
Debug("received full sync response message")
|
||||||
objTree, err := s.treeCache.GetTree(ctx, s.spaceId, msg.TreeId)
|
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).
|
||||||
@ -188,6 +177,6 @@ func (s *syncHandler) handleFullSyncResponse(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *syncHandler) alreadyHasHeads(t tree.ObjectTree, heads []string) bool {
|
func (s *syncTreeHandler) alreadyHasHeads(t tree.ObjectTree, heads []string) bool {
|
||||||
return slice.UnsortedEquals(t.Heads(), heads) || t.HasChanges(heads...)
|
return slice.UnsortedEquals(t.Heads(), heads) || t.HasChanges(heads...)
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package syncservice
|
package synctree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -44,7 +44,7 @@ func TestSyncHandler_HandleHeadUpdate(t *testing.T) {
|
|||||||
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
||||||
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
||||||
|
|
||||||
syncHandler := newSyncHandler(spaceId, cacheMock, syncClientMock)
|
syncHandler := newSyncTreeHandler(spaceId, cacheMock, syncClientMock)
|
||||||
t.Run("head update non empty all heads added", func(t *testing.T) {
|
t.Run("head update non empty all heads added", func(t *testing.T) {
|
||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
@ -196,7 +196,7 @@ func TestSyncHandler_HandleFullSyncRequest(t *testing.T) {
|
|||||||
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
||||||
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
||||||
|
|
||||||
syncHandler := newSyncHandler(spaceId, cacheMock, syncClientMock)
|
syncHandler := newSyncTreeHandler(spaceId, cacheMock, syncClientMock)
|
||||||
t.Run("full sync request with change", func(t *testing.T) {
|
t.Run("full sync request with change", func(t *testing.T) {
|
||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
@ -307,7 +307,7 @@ func TestSyncHandler_HandleFullSyncResponse(t *testing.T) {
|
|||||||
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
syncClientMock := mock_syncservice.NewMockSyncClient(ctrl)
|
||||||
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
objectTreeMock := newTestObjMock(mock_tree.NewMockObjectTree(ctrl))
|
||||||
|
|
||||||
syncHandler := newSyncHandler(spaceId, cacheMock, syncClientMock)
|
syncHandler := newSyncTreeHandler(spaceId, cacheMock, syncClientMock)
|
||||||
t.Run("full sync response with change", func(t *testing.T) {
|
t.Run("full sync response with change", func(t *testing.T) {
|
||||||
treeId := "treeId"
|
treeId := "treeId"
|
||||||
senderId := "senderId"
|
senderId := "senderId"
|
||||||
Loading…
x
Reference in New Issue
Block a user