1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-07 21:47:02 +09:00
any-sync/client/clientspace/clientcache/treecache.go
2023-01-05 12:45:50 +01:00

149 lines
4.4 KiB
Go

package clientcache
import (
"context"
"errors"
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/clientspace"
"github.com/anytypeio/go-anytype-infrastructure-experiments/client/document/textdocument"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/accountservice"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/ocache"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/object/tree/objecttree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/object/tree/treestorage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/object/treegetter"
"go.uber.org/zap"
"time"
)
var log = logger.NewNamed("treecache")
var ErrCacheObjectWithoutTree = errors.New("cache object contains no tree")
type ctxKey int
const (
spaceKey ctxKey = iota
treeCreateKey
)
type treeCache struct {
gcttl int
cache ocache.OCache
account accountservice.Service
clientService clientspace.Service
}
type TreeCache interface {
treegetter.TreeGetter
GetDocument(ctx context.Context, spaceId, id string) (doc textdocument.TextDocument, err error)
CreateDocument(ctx context.Context, spaceId string, payload objecttree.ObjectTreeCreatePayload) (ot textdocument.TextDocument, err error)
}
type updateListener struct {
}
func (u *updateListener) Update(tree objecttree.ObjectTree) {
log.With(
zap.Strings("heads", tree.Heads()),
zap.String("tree id", tree.Id())).
Debug("updating tree")
}
func (u *updateListener) Rebuild(tree objecttree.ObjectTree) {
log.With(
zap.Strings("heads", tree.Heads()),
zap.String("tree id", tree.Id())).
Debug("rebuilding tree")
}
func New(ttl int) TreeCache {
return &treeCache{
gcttl: ttl,
}
}
func (c *treeCache) Run(ctx context.Context) (err error) {
return nil
}
func (c *treeCache) Close(ctx context.Context) (err error) {
return c.cache.Close()
}
func (c *treeCache) Init(a *app.App) (err error) {
c.clientService = a.MustComponent(clientspace.CName).(clientspace.Service)
c.account = a.MustComponent(accountservice.CName).(accountservice.Service)
c.cache = ocache.New(
func(ctx context.Context, id string) (value ocache.Object, err error) {
spaceId := ctx.Value(spaceKey).(string)
space, err := c.clientService.GetSpace(ctx, spaceId)
if err != nil {
return
}
createPayload, exists := ctx.Value(treeCreateKey).(treestorage.TreeStorageCreatePayload)
if exists {
return textdocument.CreateTextDocument(ctx, space, createPayload, &updateListener{}, c.account)
}
return textdocument.NewTextDocument(ctx, space, id, &updateListener{}, c.account)
},
ocache.WithLogger(log.Sugar()),
ocache.WithGCPeriod(time.Minute),
ocache.WithTTL(time.Duration(c.gcttl)*time.Second),
)
return nil
}
func (c *treeCache) Name() (name string) {
return treegetter.CName
}
func (c *treeCache) GetDocument(ctx context.Context, spaceId, id string) (doc textdocument.TextDocument, err error) {
ctx = context.WithValue(ctx, spaceKey, spaceId)
v, err := c.cache.Get(ctx, id)
if err != nil {
return
}
doc = v.(textdocument.TextDocument)
return
}
func (c *treeCache) GetTree(ctx context.Context, spaceId, id string) (tr objecttree.ObjectTree, err error) {
doc, err := c.GetDocument(ctx, spaceId, id)
if err != nil {
return
}
// we have to do this trick, otherwise the compiler won't understand that TextDocument conforms to SyncHandler interface
tr = doc.InnerTree()
return
}
func (c *treeCache) CreateDocument(ctx context.Context, spaceId string, payload objecttree.ObjectTreeCreatePayload) (ot textdocument.TextDocument, err error) {
space, err := c.clientService.GetSpace(ctx, spaceId)
if err != nil {
return
}
create, err := space.CreateTree(context.Background(), payload)
if err != nil {
return
}
ctx = context.WithValue(ctx, spaceKey, spaceId)
ctx = context.WithValue(ctx, treeCreateKey, create)
v, err := c.cache.Get(ctx, create.RootRawChange.Id)
if err != nil {
return
}
return v.(textdocument.TextDocument), nil
}
func (c *treeCache) DeleteTree(ctx context.Context, spaceId, treeId string) (err error) {
tr, err := c.GetTree(ctx, spaceId, treeId)
if err != nil {
return
}
err = tr.Delete()
if err != nil {
return
}
_, err = c.cache.Remove(treeId)
return
}