128 lines
3.4 KiB
Go
128 lines
3.4 KiB
Go
package treecache
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
|
aclstorage "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/storage"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
const CName = "treecache"
|
|
|
|
type ObjFunc = func(obj interface{}) error
|
|
|
|
var log = logger.NewNamed("treecache")
|
|
|
|
type Service interface {
|
|
Do(ctx context.Context, id string, f ObjFunc) error
|
|
Add(ctx context.Context, id string, payload any) error
|
|
}
|
|
|
|
type service struct {
|
|
storage storage.Service
|
|
account account.Service
|
|
cache ocache.OCache
|
|
}
|
|
|
|
func New() app.ComponentRunnable {
|
|
return &service{}
|
|
}
|
|
|
|
func (s *service) Do(ctx context.Context, treeId string, f ObjFunc) error {
|
|
log.
|
|
With(zap.String("treeId", treeId)).
|
|
Debug("requesting tree from cache to perform operation")
|
|
|
|
t, err := s.cache.Get(ctx, treeId)
|
|
defer s.cache.Release(treeId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return f(t)
|
|
}
|
|
|
|
func (s *service) Add(ctx context.Context, treeId string, payload any) error {
|
|
switch pl := payload.(type) {
|
|
case aclstorage.TreeStorageCreatePayload:
|
|
log.
|
|
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(pl.Changes))).
|
|
Debug("adding Tree with changes")
|
|
|
|
_, err := s.storage.CreateTreeStorage(payload.(aclstorage.TreeStorageCreatePayload))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case aclstorage.ACLListStorageCreatePayload:
|
|
log.
|
|
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(pl.Records))).
|
|
Debug("adding ACLList with records")
|
|
|
|
_, err := s.storage.CreateACLListStorage(payload.(aclstorage.ACLListStorageCreatePayload))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *service) Init(a *app.App) (err error) {
|
|
s.cache = ocache.New(s.loadTree)
|
|
s.account = a.MustComponent(account.CName).(account.Service)
|
|
s.storage = a.MustComponent(storage.CName).(storage.Service)
|
|
// TODO: for test we should load some predefined keys
|
|
return nil
|
|
}
|
|
|
|
func (s *service) Name() (name string) {
|
|
return CName
|
|
}
|
|
|
|
func (s *service) Run(ctx context.Context) (err error) {
|
|
return nil
|
|
}
|
|
|
|
func (s *service) Close(ctx context.Context) (err error) {
|
|
return s.cache.Close()
|
|
}
|
|
|
|
func (s *service) loadTree(ctx context.Context, id string) (ocache.Object, error) {
|
|
t, err := s.storage.Storage(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
header, err := t.Header()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch header.DocType { // handler
|
|
case aclpb.Header_ACL:
|
|
return list.BuildACLListWithIdentity(s.account.Account(), t.(aclstorage.ListStorage))
|
|
case aclpb.Header_DocTree:
|
|
break
|
|
default:
|
|
return nil, fmt.Errorf("incorrect type")
|
|
}
|
|
log.Info("got header", zap.String("header", header.String()))
|
|
var objTree tree.ObjectTree
|
|
err = s.Do(ctx, header.AclListId, func(obj interface{}) error {
|
|
aclList := obj.(list.ACLList)
|
|
objTree, err = tree.BuildObjectTree(t.(aclstorage.TreeStorage), nil, aclList)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
|
|
return objTree, err
|
|
}
|