Stopped space from unloading if trees are still there
This commit is contained in:
parent
aaecd2ae6d
commit
494b7552ce
@ -18,6 +18,7 @@ import (
|
|||||||
"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"
|
||||||
"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/ocache"
|
||||||
"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"
|
||||||
"github.com/zeebo/errs"
|
"github.com/zeebo/errs"
|
||||||
@ -65,6 +66,9 @@ func NewSpaceId(id string, repKey uint64) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Space interface {
|
type Space interface {
|
||||||
|
ocache.ObjectLocker
|
||||||
|
ocache.ObjectLastUsage
|
||||||
|
|
||||||
Id() string
|
Id() string
|
||||||
Init(ctx context.Context) error
|
Init(ctx context.Context) error
|
||||||
|
|
||||||
@ -98,13 +102,29 @@ type space struct {
|
|||||||
configuration nodeconf.Configuration
|
configuration nodeconf.Configuration
|
||||||
settingsDocument settingsdocument.SettingsDocument
|
settingsDocument settingsdocument.SettingsDocument
|
||||||
|
|
||||||
isClosed atomic.Bool
|
isClosed atomic.Bool
|
||||||
|
treesUsed atomic.Int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *space) StartTree() {
|
||||||
|
s.treesUsed.Add(1)
|
||||||
|
log.With(zap.Int32("trees used", s.treesUsed.Load())).Debug("starting tree")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *space) CloseTree() {
|
||||||
|
s.treesUsed.Add(-1)
|
||||||
|
log.With(zap.Int32("trees used", s.treesUsed.Load())).Debug("closing tree")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) LastUsage() time.Time {
|
func (s *space) LastUsage() time.Time {
|
||||||
return s.syncService.LastUsage()
|
return s.syncService.LastUsage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *space) Locked() bool {
|
||||||
|
log.With(zap.Bool("locked", s.treesUsed.Load() > 1)).Debug("space lock status check")
|
||||||
|
return s.treesUsed.Load() > 1
|
||||||
|
}
|
||||||
|
|
||||||
func (s *space) Id() string {
|
func (s *space) Id() string {
|
||||||
return s.id
|
return s.id
|
||||||
}
|
}
|
||||||
@ -131,6 +151,7 @@ func (s *space) Description() (desc SpaceDescription, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) Init(ctx context.Context) (err error) {
|
func (s *space) Init(ctx context.Context) (err error) {
|
||||||
|
log.With(zap.String("spaceId", s.id)).Debug("initializing space")
|
||||||
s.storage = newCommonStorage(s.storage)
|
s.storage = newCommonStorage(s.storage)
|
||||||
|
|
||||||
header, err := s.storage.SpaceHeader()
|
header, err := s.storage.SpaceHeader()
|
||||||
@ -207,14 +228,15 @@ func (s *space) DeriveTree(ctx context.Context, payload tree.ObjectTreeCreatePay
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
deps := synctree.CreateDeps{
|
deps := synctree.CreateDeps{
|
||||||
SpaceId: s.id,
|
SpaceId: s.id,
|
||||||
Payload: payload,
|
Payload: payload,
|
||||||
StreamPool: s.syncService.StreamPool(),
|
StreamPool: s.syncService.StreamPool(),
|
||||||
Configuration: s.configuration,
|
Configuration: s.configuration,
|
||||||
HeadNotifiable: s.diffService,
|
HeadNotifiable: s.diffService,
|
||||||
Listener: listener,
|
Listener: listener,
|
||||||
AclList: s.aclList,
|
AclList: s.aclList,
|
||||||
SpaceStorage: s.storage,
|
SpaceStorage: s.storage,
|
||||||
|
TreeUsageController: s,
|
||||||
}
|
}
|
||||||
return synctree.DeriveSyncTree(ctx, deps)
|
return synctree.DeriveSyncTree(ctx, deps)
|
||||||
}
|
}
|
||||||
@ -225,14 +247,15 @@ func (s *space) CreateTree(ctx context.Context, payload tree.ObjectTreeCreatePay
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
deps := synctree.CreateDeps{
|
deps := synctree.CreateDeps{
|
||||||
SpaceId: s.id,
|
SpaceId: s.id,
|
||||||
Payload: payload,
|
Payload: payload,
|
||||||
StreamPool: s.syncService.StreamPool(),
|
StreamPool: s.syncService.StreamPool(),
|
||||||
Configuration: s.configuration,
|
Configuration: s.configuration,
|
||||||
HeadNotifiable: s.diffService,
|
HeadNotifiable: s.diffService,
|
||||||
Listener: listener,
|
Listener: listener,
|
||||||
AclList: s.aclList,
|
AclList: s.aclList,
|
||||||
SpaceStorage: s.storage,
|
SpaceStorage: s.storage,
|
||||||
|
TreeUsageController: s,
|
||||||
}
|
}
|
||||||
return synctree.CreateSyncTree(ctx, deps)
|
return synctree.CreateSyncTree(ctx, deps)
|
||||||
}
|
}
|
||||||
@ -243,13 +266,14 @@ func (s *space) BuildTree(ctx context.Context, id string, listener updatelistene
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
deps := synctree.BuildDeps{
|
deps := synctree.BuildDeps{
|
||||||
SpaceId: s.id,
|
SpaceId: s.id,
|
||||||
StreamPool: s.syncService.StreamPool(),
|
StreamPool: s.syncService.StreamPool(),
|
||||||
Configuration: s.configuration,
|
Configuration: s.configuration,
|
||||||
HeadNotifiable: s.diffService,
|
HeadNotifiable: s.diffService,
|
||||||
Listener: listener,
|
Listener: listener,
|
||||||
AclList: s.aclList,
|
AclList: s.aclList,
|
||||||
SpaceStorage: s.storage,
|
SpaceStorage: s.storage,
|
||||||
|
TreeUsageController: s,
|
||||||
}
|
}
|
||||||
return synctree.BuildSyncTreeOrGetRemote(ctx, id, deps)
|
return synctree.BuildSyncTreeOrGetRemote(ctx, id, deps)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"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"
|
||||||
|
"go.uber.org/zap"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,6 +37,7 @@ type syncService struct {
|
|||||||
stopStreamLoop context.CancelFunc
|
stopStreamLoop context.CancelFunc
|
||||||
connector nodeconf.ConfConnector
|
connector nodeconf.ConfConnector
|
||||||
streamLoopDone chan struct{}
|
streamLoopDone chan struct{}
|
||||||
|
log *zap.SugaredLogger // TODO: change to logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSyncService(
|
func NewSyncService(
|
||||||
@ -62,6 +64,7 @@ func newSyncService(
|
|||||||
connector: connector,
|
connector: connector,
|
||||||
clientFactory: clientFactory,
|
clientFactory: clientFactory,
|
||||||
spaceId: spaceId,
|
spaceId: spaceId,
|
||||||
|
log: log.With(zap.String("id", spaceId)),
|
||||||
streamLoopDone: make(chan struct{}),
|
streamLoopDone: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,6 +86,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) {
|
||||||
|
s.log.With(zap.String("peerId", senderId), zap.String("objectId", message.ObjectId)).Debug("handling message")
|
||||||
obj, err := s.objectGetter.GetObject(ctx, message.ObjectId)
|
obj, err := s.objectGetter.GetObject(ctx, message.ObjectId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -93,18 +97,21 @@ func (s *syncService) HandleMessage(ctx context.Context, senderId string, messag
|
|||||||
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() {
|
||||||
|
s.log.Debug("dialing responsible peers")
|
||||||
respPeers, err := s.connector.DialResponsiblePeers(ctx, s.spaceId)
|
respPeers, err := s.connector.DialResponsiblePeers(ctx, s.spaceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
s.log.Error("failed to dial peers", zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, p := range respPeers {
|
for _, p := range respPeers {
|
||||||
if s.streamPool.HasActiveStream(p.Id()) {
|
if s.streamPool.HasActiveStream(p.Id()) {
|
||||||
|
s.log.Debug("has active stream for", zap.String("id", p.Id()))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stream, err := s.clientFactory.Client(p).Stream(ctx)
|
stream, err := s.clientFactory.Client(p).Stream(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = rpcerr.Unwrap(err)
|
err = rpcerr.Unwrap(err)
|
||||||
log.With("spaceId", s.spaceId).Errorf("failed to open stream: %v", err)
|
s.log.Errorf("failed to open stream: %v", err)
|
||||||
// so here probably the request is failed because there is no such space,
|
// so here probably the request is failed because there is no such space,
|
||||||
// but diffService should handle such cases by sending pushSpace
|
// but diffService should handle such cases by sending pushSpace
|
||||||
continue
|
continue
|
||||||
@ -113,9 +120,10 @@ func (s *syncService) responsibleStreamCheckLoop(ctx context.Context) {
|
|||||||
err = stream.Send(&spacesyncproto.ObjectSyncMessage{SpaceId: s.spaceId})
|
err = stream.Send(&spacesyncproto.ObjectSyncMessage{SpaceId: s.spaceId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = rpcerr.Unwrap(err)
|
err = rpcerr.Unwrap(err)
|
||||||
log.With("spaceId", s.spaceId).Errorf("failed to send first message to stream: %v", err)
|
s.log.Errorf("failed to send first message to stream: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
s.log.Debug("continue reading stream for", zap.String("id", p.Id()))
|
||||||
s.streamPool.AddAndReadStreamAsync(stream)
|
s.streamPool.AddAndReadStreamAsync(stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,15 +30,21 @@ type SyncTree interface {
|
|||||||
synchandler.SyncHandler
|
synchandler.SyncHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TreeUsageController interface {
|
||||||
|
StartTree()
|
||||||
|
CloseTree()
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
synchandler.SyncHandler
|
||||||
syncClient SyncClient
|
syncClient SyncClient
|
||||||
notifiable diffservice.HeadNotifiable
|
notifiable diffservice.HeadNotifiable
|
||||||
listener updatelistener.UpdateListener
|
listener updatelistener.UpdateListener
|
||||||
isClosed bool
|
usageController TreeUsageController
|
||||||
isDeleted bool
|
isClosed bool
|
||||||
|
isDeleted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var log = logger.NewNamed("commonspace.synctree").Sugar()
|
var log = logger.NewNamed("commonspace.synctree").Sugar()
|
||||||
@ -49,25 +55,27 @@ var buildObjectTree = tree.BuildObjectTree
|
|||||||
var createSyncClient = newSyncClient
|
var createSyncClient = newSyncClient
|
||||||
|
|
||||||
type CreateDeps struct {
|
type CreateDeps struct {
|
||||||
SpaceId string
|
SpaceId string
|
||||||
Payload tree.ObjectTreeCreatePayload
|
Payload tree.ObjectTreeCreatePayload
|
||||||
Configuration nodeconf.Configuration
|
Configuration nodeconf.Configuration
|
||||||
HeadNotifiable diffservice.HeadNotifiable
|
HeadNotifiable diffservice.HeadNotifiable
|
||||||
StreamPool syncservice.StreamPool
|
StreamPool syncservice.StreamPool
|
||||||
Listener updatelistener.UpdateListener
|
Listener updatelistener.UpdateListener
|
||||||
AclList list.ACLList
|
AclList list.ACLList
|
||||||
SpaceStorage spacestorage.SpaceStorage
|
SpaceStorage spacestorage.SpaceStorage
|
||||||
|
TreeUsageController TreeUsageController
|
||||||
}
|
}
|
||||||
|
|
||||||
type BuildDeps struct {
|
type BuildDeps struct {
|
||||||
SpaceId string
|
SpaceId string
|
||||||
StreamPool syncservice.StreamPool
|
StreamPool syncservice.StreamPool
|
||||||
Configuration nodeconf.Configuration
|
Configuration nodeconf.Configuration
|
||||||
HeadNotifiable diffservice.HeadNotifiable
|
HeadNotifiable diffservice.HeadNotifiable
|
||||||
Listener updatelistener.UpdateListener
|
Listener updatelistener.UpdateListener
|
||||||
AclList list.ACLList
|
AclList list.ACLList
|
||||||
SpaceStorage spacestorage.SpaceStorage
|
SpaceStorage spacestorage.SpaceStorage
|
||||||
TreeStorage storage.TreeStorage
|
TreeStorage storage.TreeStorage
|
||||||
|
TreeUsageController TreeUsageController
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeriveSyncTree(ctx context.Context, deps CreateDeps) (t SyncTree, err error) {
|
func DeriveSyncTree(ctx context.Context, deps CreateDeps) (t SyncTree, err error) {
|
||||||
@ -81,10 +89,11 @@ func DeriveSyncTree(ctx context.Context, deps CreateDeps) (t SyncTree, err error
|
|||||||
sharedFactory,
|
sharedFactory,
|
||||||
deps.Configuration)
|
deps.Configuration)
|
||||||
syncTree := &syncTree{
|
syncTree := &syncTree{
|
||||||
ObjectTree: objTree,
|
ObjectTree: objTree,
|
||||||
syncClient: syncClient,
|
syncClient: syncClient,
|
||||||
notifiable: deps.HeadNotifiable,
|
notifiable: deps.HeadNotifiable,
|
||||||
listener: deps.Listener,
|
usageController: deps.TreeUsageController,
|
||||||
|
listener: deps.Listener,
|
||||||
}
|
}
|
||||||
syncHandler := newSyncTreeHandler(syncTree, syncClient)
|
syncHandler := newSyncTreeHandler(syncTree, syncClient)
|
||||||
syncTree.SyncHandler = syncHandler
|
syncTree.SyncHandler = syncHandler
|
||||||
@ -94,6 +103,9 @@ func DeriveSyncTree(ctx context.Context, deps CreateDeps) (t SyncTree, err error
|
|||||||
if syncTree.listener != nil {
|
if syncTree.listener != nil {
|
||||||
syncTree.listener.Rebuild(syncTree)
|
syncTree.listener.Rebuild(syncTree)
|
||||||
}
|
}
|
||||||
|
if syncTree.usageController != nil {
|
||||||
|
syncTree.usageController.StartTree()
|
||||||
|
}
|
||||||
|
|
||||||
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
||||||
err = syncClient.BroadcastAsync(headUpdate)
|
err = syncClient.BroadcastAsync(headUpdate)
|
||||||
@ -111,10 +123,11 @@ func CreateSyncTree(ctx context.Context, deps CreateDeps) (t SyncTree, err error
|
|||||||
GetRequestFactory(),
|
GetRequestFactory(),
|
||||||
deps.Configuration)
|
deps.Configuration)
|
||||||
syncTree := &syncTree{
|
syncTree := &syncTree{
|
||||||
ObjectTree: objTree,
|
ObjectTree: objTree,
|
||||||
syncClient: syncClient,
|
syncClient: syncClient,
|
||||||
notifiable: deps.HeadNotifiable,
|
notifiable: deps.HeadNotifiable,
|
||||||
listener: deps.Listener,
|
usageController: deps.TreeUsageController,
|
||||||
|
listener: deps.Listener,
|
||||||
}
|
}
|
||||||
syncHandler := newSyncTreeHandler(syncTree, syncClient)
|
syncHandler := newSyncTreeHandler(syncTree, syncClient)
|
||||||
syncTree.SyncHandler = syncHandler
|
syncTree.SyncHandler = syncHandler
|
||||||
@ -125,6 +138,9 @@ func CreateSyncTree(ctx context.Context, deps CreateDeps) (t SyncTree, err error
|
|||||||
if syncTree.listener != nil {
|
if syncTree.listener != nil {
|
||||||
syncTree.listener.Rebuild(syncTree)
|
syncTree.listener.Rebuild(syncTree)
|
||||||
}
|
}
|
||||||
|
if syncTree.usageController != nil {
|
||||||
|
syncTree.usageController.StartTree()
|
||||||
|
}
|
||||||
|
|
||||||
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
headUpdate := syncClient.CreateHeadUpdate(t, nil)
|
||||||
err = syncClient.BroadcastAsync(headUpdate)
|
err = syncClient.BroadcastAsync(headUpdate)
|
||||||
@ -211,10 +227,11 @@ func buildSyncTree(ctx context.Context, isFirstBuild bool, deps BuildDeps) (t Sy
|
|||||||
GetRequestFactory(),
|
GetRequestFactory(),
|
||||||
deps.Configuration)
|
deps.Configuration)
|
||||||
syncTree := &syncTree{
|
syncTree := &syncTree{
|
||||||
ObjectTree: objTree,
|
ObjectTree: objTree,
|
||||||
syncClient: syncClient,
|
syncClient: syncClient,
|
||||||
notifiable: deps.HeadNotifiable,
|
notifiable: deps.HeadNotifiable,
|
||||||
listener: deps.Listener,
|
usageController: deps.TreeUsageController,
|
||||||
|
listener: deps.Listener,
|
||||||
}
|
}
|
||||||
syncHandler := newSyncTreeHandler(syncTree, syncClient)
|
syncHandler := newSyncTreeHandler(syncTree, syncClient)
|
||||||
syncTree.SyncHandler = syncHandler
|
syncTree.SyncHandler = syncHandler
|
||||||
@ -224,6 +241,9 @@ func buildSyncTree(ctx context.Context, isFirstBuild bool, deps BuildDeps) (t Sy
|
|||||||
if syncTree.listener != nil {
|
if syncTree.listener != nil {
|
||||||
syncTree.listener.Rebuild(syncTree)
|
syncTree.listener.Rebuild(syncTree)
|
||||||
}
|
}
|
||||||
|
if syncTree.usageController != nil {
|
||||||
|
syncTree.usageController.StartTree()
|
||||||
|
}
|
||||||
|
|
||||||
headUpdate := syncTree.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
|
||||||
@ -317,6 +337,9 @@ func (s *syncTree) Close() (err error) {
|
|||||||
if s.isClosed {
|
if s.isClosed {
|
||||||
return ErrSyncTreeClosed
|
return ErrSyncTreeClosed
|
||||||
}
|
}
|
||||||
|
if s.usageController != nil {
|
||||||
|
s.usageController.CloseTree()
|
||||||
|
}
|
||||||
s.isClosed = true
|
s.isClosed = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user