mirror of
https://github.com/anyproto/anytype-heart.git
synced 2025-06-09 17:44:59 +09:00
GO-2046 Merge feature/spaces 4
This commit is contained in:
commit
b73ff52e74
208 changed files with 7661 additions and 11484 deletions
|
@ -1,10 +1,10 @@
|
|||
dir: "{{.InterfaceDir}}/mock_{{.PackageName}}"
|
||||
testonly: True
|
||||
#testonly: True
|
||||
with-expecter: True
|
||||
all: False
|
||||
outpkg: "mock_{{.PackageName}}"
|
||||
packages:
|
||||
github.com/anyproto/anytype-heart/space/typeprovider:
|
||||
github.com/anyproto/anytype-heart/space/spacecore/typeprovider:
|
||||
interfaces:
|
||||
SmartBlockTypeProvider:
|
||||
github.com/anyproto/anytype-heart/core/wallet:
|
||||
|
@ -15,7 +15,7 @@ packages:
|
|||
Sender:
|
||||
github.com/anyproto/anytype-heart/core/block/getblock:
|
||||
interfaces:
|
||||
Picker:
|
||||
ObjectGetter:
|
||||
github.com/anyproto/anytype-heart/pkg/lib/core:
|
||||
interfaces:
|
||||
Service:
|
||||
|
@ -38,12 +38,26 @@ packages:
|
|||
github.com/anyproto/anytype-heart/core/system_object:
|
||||
interfaces:
|
||||
Service:
|
||||
deriver:
|
||||
github.com/anyproto/anytype-heart/core/filestorage/filesync:
|
||||
interfaces:
|
||||
FileSync:
|
||||
github.com/anyproto/anytype-heart/space:
|
||||
interfaces:
|
||||
Service:
|
||||
github.com/anyproto/anytype-heart/core/subscription:
|
||||
interfaces:
|
||||
CollectionService:
|
||||
github.com/anyproto/anytype-heart/core/block/object/objectcache:
|
||||
interfaces:
|
||||
Cache:
|
||||
github.com/anyproto/anytype-heart/core/indexer:
|
||||
interfaces:
|
||||
Indexer:
|
||||
github.com/anyproto/anytype-heart/space/spacecore:
|
||||
interfaces:
|
||||
SpaceCoreService:
|
||||
github.com/anyproto/anytype-heart/space/techspace:
|
||||
interfaces:
|
||||
TechSpace:
|
||||
github.com/anyproto/anytype-heart/space:
|
||||
interfaces:
|
||||
bundledObjectsInstaller:
|
||||
isNewAccount:
|
||||
|
|
|
@ -3,7 +3,7 @@ package service
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/anyproto/anytype-heart/space/localdiscovery"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/localdiscovery"
|
||||
)
|
||||
|
||||
type AndroidDiscoveryProxy interface {
|
||||
|
|
|
@ -4,19 +4,22 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/anytype/config"
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/wallet"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/gateway"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/addr"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/threads"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
)
|
||||
|
||||
const CName = "account"
|
||||
|
@ -26,15 +29,22 @@ var log = logging.Logger(CName)
|
|||
type Service interface {
|
||||
app.Component
|
||||
GetInfo(ctx context.Context, spaceID string) (*model.AccountInfo, error)
|
||||
Delete(ctx context.Context) (spacecore.NetworkStatus, error)
|
||||
RevertDeletion(ctx context.Context) error
|
||||
AccountID() string
|
||||
PersonalSpaceID() string
|
||||
}
|
||||
|
||||
type service struct {
|
||||
spaceService space.Service
|
||||
coreService core.Service
|
||||
spaceCore spacecore.SpaceCoreService
|
||||
spaceService space.SpaceService
|
||||
wallet wallet.Wallet
|
||||
gateway gateway.Gateway
|
||||
config *config.Config
|
||||
blockService *block.Service
|
||||
objectCache objectcache.Cache
|
||||
|
||||
once sync.Once
|
||||
personalSpaceID string
|
||||
}
|
||||
|
||||
func New() Service {
|
||||
|
@ -42,13 +52,30 @@ func New() Service {
|
|||
}
|
||||
|
||||
func (s *service) Init(a *app.App) (err error) {
|
||||
s.spaceService = app.MustComponent[space.Service](a)
|
||||
s.coreService = app.MustComponent[core.Service](a)
|
||||
s.spaceService = app.MustComponent[space.SpaceService](a)
|
||||
s.spaceCore = app.MustComponent[spacecore.SpaceCoreService](a)
|
||||
s.wallet = app.MustComponent[wallet.Wallet](a)
|
||||
s.gateway = app.MustComponent[gateway.Gateway](a)
|
||||
s.config = app.MustComponent[*config.Config](a)
|
||||
s.blockService = app.MustComponent[*block.Service](a)
|
||||
return nil
|
||||
s.objectCache = app.MustComponent[objectcache.Cache](a)
|
||||
s.personalSpaceID, err = s.spaceCore.DeriveID(context.Background(), spacecore.SpaceType)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *service) Delete(ctx context.Context) (spacecore.NetworkStatus, error) {
|
||||
return spacecore.NetworkStatus{}, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (s *service) RevertDeletion(ctx context.Context) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (s *service) AccountID() string {
|
||||
return s.wallet.Account().SignKey.GetPublic().Account()
|
||||
}
|
||||
|
||||
func (s *service) PersonalSpaceID() string {
|
||||
return s.personalSpaceID
|
||||
}
|
||||
|
||||
func (s *service) Name() (name string) {
|
||||
|
@ -59,7 +86,7 @@ func (s *service) GetInfo(ctx context.Context, spaceID string) (*model.AccountIn
|
|||
deviceKey := s.wallet.GetDevicePrivkey()
|
||||
deviceId := deviceKey.GetPublic().Account()
|
||||
|
||||
analyticsId, err := s.getAnalyticsID()
|
||||
analyticsId, err := s.getAnalyticsID(ctx)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get analytics id: %s", err)
|
||||
}
|
||||
|
@ -75,14 +102,20 @@ func (s *service) GetInfo(ctx context.Context, spaceID string) (*model.AccountIn
|
|||
cfg.CustomFileStorePath = s.wallet.RepoPath()
|
||||
}
|
||||
|
||||
ids, err := s.coreService.DerivePredefinedObjects(ctx, spaceID, false)
|
||||
// TODO Temporary
|
||||
personalIds, err := s.getIds(ctx, s.PersonalSpaceID())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("derive predefined objects: %w", err)
|
||||
return nil, fmt.Errorf("failed to get derived ids: %w", err)
|
||||
}
|
||||
|
||||
ids, err := s.getIds(ctx, spaceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get derived ids: %w", err)
|
||||
}
|
||||
return &model.AccountInfo{
|
||||
HomeObjectId: ids.Home,
|
||||
ArchiveObjectId: ids.Archive,
|
||||
ProfileObjectId: ids.Profile,
|
||||
ProfileObjectId: personalIds.Profile,
|
||||
MarketplaceWorkspaceId: addr.AnytypeMarketplaceWorkspace,
|
||||
AccountSpaceId: spaceID,
|
||||
WorkspaceObjectId: ids.Workspace,
|
||||
|
@ -96,12 +129,26 @@ func (s *service) GetInfo(ctx context.Context, spaceID string) (*model.AccountIn
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) getAnalyticsID() (string, error) {
|
||||
func (s *service) getIds(ctx context.Context, spaceID string) (ids threads.DerivedSmartblockIds, err error) {
|
||||
sp, err := s.spaceService.Get(ctx, spaceID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return sp.DerivedIDs(), nil
|
||||
}
|
||||
|
||||
func (s *service) getAnalyticsID(ctx context.Context) (string, error) {
|
||||
if s.config.AnalyticsId != "" {
|
||||
return s.config.AnalyticsId, nil
|
||||
}
|
||||
accountObjectID := s.coreService.AccountObjects().Workspace
|
||||
sb, err := s.blockService.PickBlock(context.Background(), accountObjectID)
|
||||
ids, err := s.getIds(ctx, s.personalSpaceID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get derived ids: %w", err)
|
||||
}
|
||||
sb, err := s.objectCache.GetObject(ctx, domain.FullID{
|
||||
ObjectID: ids.Workspace,
|
||||
SpaceID: s.personalSpaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor/converter"
|
||||
"github.com/anyproto/anytype-heart/core/block/export"
|
||||
importer "github.com/anyproto/anytype-heart/core/block/import"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcreator"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectgraph"
|
||||
|
@ -66,14 +67,16 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/clientserver"
|
||||
"github.com/anyproto/anytype-heart/space/credentialprovider"
|
||||
"github.com/anyproto/anytype-heart/space/localdiscovery"
|
||||
"github.com/anyproto/anytype-heart/space/peermanager"
|
||||
"github.com/anyproto/anytype-heart/space/peerstore"
|
||||
"github.com/anyproto/anytype-heart/space/storage"
|
||||
"github.com/anyproto/anytype-heart/space/syncstatusprovider"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/clientserver"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/credentialprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/localdiscovery"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/peermanager"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/peerstore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/storage"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/syncstatusprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/techspace"
|
||||
"github.com/anyproto/anytype-heart/util/builtinobjects"
|
||||
"github.com/anyproto/anytype-heart/util/builtintemplate"
|
||||
"github.com/anyproto/anytype-heart/util/linkpreview"
|
||||
|
@ -199,11 +202,12 @@ func Bootstrap(a *app.App, components ...app.Component) {
|
|||
Register(credentialprovider.New()).
|
||||
Register(commonspace.New()).
|
||||
Register(rpcstore.New()).
|
||||
Register(space.New()).
|
||||
Register(filestore.New()).
|
||||
Register(fileservice.New()).
|
||||
Register(filestorage.New()).
|
||||
Register(filesync.New()).
|
||||
Register(spacecore.New()).
|
||||
Register(idresolver.New()).
|
||||
Register(localdiscovery.New()).
|
||||
Register(peermanager.New()).
|
||||
Register(typeprovider.New()).
|
||||
|
@ -239,6 +243,8 @@ func Bootstrap(a *app.App, components ...app.Component) {
|
|||
Register(objectcreator.NewCreator()).
|
||||
Register(kanban.New()).
|
||||
Register(editor.NewObjectFactory()).
|
||||
Register(techspace.New()).
|
||||
Register(space.New()).
|
||||
Register(objectgraph.NewBuilder()).
|
||||
Register(account.New())
|
||||
}
|
||||
|
|
|
@ -236,6 +236,10 @@ func (c *Config) GetConfigPath() string {
|
|||
return filepath.Join(c.RepoPath, ConfigFileName)
|
||||
}
|
||||
|
||||
func (c *Config) IsNewAccount() bool {
|
||||
return c.NewAccount
|
||||
}
|
||||
|
||||
func getRandomPort() (int, error) {
|
||||
addr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:0")
|
||||
if err != nil {
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
@ -87,7 +86,7 @@ func (s *Service) handleCustomStorageLocation(req *pb.RpcAccountCreateRequest, a
|
|||
func (s *Service) setAccountAndProfileDetails(ctx context.Context, req *pb.RpcAccountCreateRequest, newAcc *model.Account) error {
|
||||
newAcc.Name = req.Name
|
||||
|
||||
spaceID := app.MustComponent[space.Service](s.app).AccountId()
|
||||
spaceID := app.MustComponent[account.Service](s.app).PersonalSpaceID()
|
||||
var err error
|
||||
newAcc.Info, err = app.MustComponent[account.Service](s.app).GetInfo(ctx, spaceID)
|
||||
if err != nil {
|
||||
|
|
|
@ -14,13 +14,13 @@ import (
|
|||
"github.com/anyproto/any-sync/util/crypto"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/anytype"
|
||||
"github.com/anyproto/anytype-heart/core/anytype/account"
|
||||
"github.com/anyproto/anytype-heart/core/anytype/config"
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/util/builtinobjects"
|
||||
"github.com/anyproto/anytype-heart/util/constant"
|
||||
oserror "github.com/anyproto/anytype-heart/util/os"
|
||||
|
@ -110,7 +110,7 @@ func (s *Service) CreateAccountFromExport(req *pb.RpcAccountRecoverFromLegacyExp
|
|||
return "", err
|
||||
}
|
||||
|
||||
spaceID := app.MustComponent[space.Service](s.app).AccountId()
|
||||
spaceID := app.MustComponent[account.Service](s.app).PersonalSpaceID()
|
||||
if err = s.app.MustComponent(builtinobjects.CName).(builtinobjects.BuiltinObjects).InjectMigrationDashboard(spaceID); err != nil {
|
||||
return "", errors.Join(ErrBadInput, err)
|
||||
}
|
||||
|
|
|
@ -4,10 +4,11 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/anytype/account"
|
||||
"github.com/anyproto/anytype-heart/core/configfetcher"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -18,26 +19,44 @@ var (
|
|||
func (s *Service) AccountDelete(ctx context.Context, req *pb.RpcAccountDeleteRequest) (*model.AccountStatus, error) {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
spaceService := s.app.MustComponent(space.CName).(space.Service)
|
||||
resp, err := spaceService.DeleteAccount(ctx, req.Revert)
|
||||
status := &model.AccountStatus{
|
||||
StatusType: model.AccountStatusType(resp.Status),
|
||||
DeletionDate: resp.DeletionDate.Unix(),
|
||||
convErr := func(err error) error {
|
||||
switch err {
|
||||
case spacecore.ErrSpaceIsDeleted:
|
||||
return ErrAccountIsAlreadyDeleted
|
||||
case spacecore.ErrSpaceDeletionPending:
|
||||
return ErrAccountIsAlreadyDeleted
|
||||
case spacecore.ErrSpaceIsCreated:
|
||||
return ErrAccountIsActive
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
var (
|
||||
accountService = s.app.MustComponent(account.CName).(account.Service)
|
||||
status *model.AccountStatus
|
||||
)
|
||||
if !req.Revert {
|
||||
networkStatus, err := accountService.Delete(ctx)
|
||||
if err != nil {
|
||||
return nil, convErr(err)
|
||||
}
|
||||
status = &model.AccountStatus{
|
||||
StatusType: model.AccountStatusType(networkStatus.Status),
|
||||
DeletionDate: networkStatus.DeletionDate.Unix(),
|
||||
}
|
||||
} else {
|
||||
err := accountService.RevertDeletion(ctx)
|
||||
if err != nil {
|
||||
return nil, convErr(err)
|
||||
}
|
||||
status = &model.AccountStatus{
|
||||
StatusType: model.AccountStatusType(spacecore.SpaceStatusCreated),
|
||||
}
|
||||
}
|
||||
|
||||
// so we will receive updated account status
|
||||
s.refreshRemoteAccountState()
|
||||
|
||||
switch err {
|
||||
case space.ErrSpaceIsDeleted:
|
||||
return nil, ErrAccountIsAlreadyDeleted
|
||||
case space.ErrSpaceDeletionPending:
|
||||
return nil, ErrAccountIsAlreadyDeleted
|
||||
case space.ErrSpaceIsCreated:
|
||||
return nil, ErrAccountIsActive
|
||||
}
|
||||
return status, err
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func (s *Service) refreshRemoteAccountState() {
|
||||
|
|
|
@ -3,7 +3,7 @@ package application
|
|||
import (
|
||||
"github.com/anyproto/any-sync/app"
|
||||
|
||||
"github.com/anyproto/anytype-heart/space/localdiscovery"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/localdiscovery"
|
||||
)
|
||||
|
||||
func (s *Service) EnableLocalNetworkSync() error {
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
)
|
||||
|
||||
// we cannot check the constant error from badger because they hardcoded it there
|
||||
|
@ -50,7 +49,7 @@ func (s *Service) AccountSelect(ctx context.Context, req *pb.RpcAccountSelectReq
|
|||
objectCache := app.MustComponent[objectcache.Cache](s.app)
|
||||
objectCache.CloseBlocks()
|
||||
|
||||
spaceID := app.MustComponent[space.Service](s.app).AccountId()
|
||||
spaceID := app.MustComponent[account.Service](s.app).PersonalSpaceID()
|
||||
acc := &model.Account{Id: req.Id}
|
||||
var err error
|
||||
acc.Info, err = app.MustComponent[account.Service](s.app).GetInfo(ctx, spaceID)
|
||||
|
@ -122,7 +121,7 @@ func (s *Service) AccountSelect(ctx context.Context, req *pb.RpcAccountSelectReq
|
|||
}
|
||||
|
||||
acc := &model.Account{Id: req.Id}
|
||||
spaceID := app.MustComponent[space.Service](s.app).AccountId()
|
||||
spaceID := app.MustComponent[account.Service](s.app).PersonalSpaceID()
|
||||
acc.Info, err = app.MustComponent[account.Service](s.app).GetInfo(ctx, spaceID)
|
||||
return acc, nil
|
||||
}
|
||||
|
|
|
@ -6,16 +6,18 @@ import (
|
|||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/session"
|
||||
)
|
||||
|
||||
type Picker interface {
|
||||
PickBlock(ctx context.Context, objectID string) (sb smartblock.SmartBlock, err error)
|
||||
type ObjectGetter interface {
|
||||
GetObject(ctx context.Context, objectID string) (sb smartblock.SmartBlock, err error)
|
||||
GetObjectByFullID(ctx context.Context, id domain.FullID) (sb smartblock.SmartBlock, err error)
|
||||
}
|
||||
|
||||
func Do[t any](p Picker, objectID string, apply func(sb t) error) error {
|
||||
func Do[t any](p ObjectGetter, objectID string, apply func(sb t) error) error {
|
||||
ctx := context.Background()
|
||||
sb, err := p.PickBlock(ctx, objectID)
|
||||
sb, err := p.GetObject(ctx, objectID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -31,8 +33,25 @@ func Do[t any](p Picker, objectID string, apply func(sb t) error) error {
|
|||
return apply(bb)
|
||||
}
|
||||
|
||||
func DoContext[t any](p Picker, ctx context.Context, objectID string, apply func(sb t) error) error {
|
||||
sb, err := p.PickBlock(ctx, objectID)
|
||||
func DoContext[t any](p ObjectGetter, ctx context.Context, objectID string, apply func(sb t) error) error {
|
||||
sb, err := p.GetObject(ctx, objectID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bb, ok := sb.(t)
|
||||
if !ok {
|
||||
var dummy = new(t)
|
||||
return fmt.Errorf("the interface %T is not implemented in %T", dummy, sb)
|
||||
}
|
||||
|
||||
sb.Lock()
|
||||
defer sb.Unlock()
|
||||
return apply(bb)
|
||||
}
|
||||
|
||||
func DoContextFullID[t any](p ObjectGetter, ctx context.Context, id domain.FullID, apply func(sb t) error) error {
|
||||
sb, err := p.GetObjectByFullID(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -50,7 +69,7 @@ func DoContext[t any](p Picker, ctx context.Context, objectID string, apply func
|
|||
|
||||
// DoState2 picks two blocks and perform an action on them. The order of locks is always the same for two ids.
|
||||
// It correctly handles the case when two ids are the same.
|
||||
func DoState2[t1, t2 any](s Picker, firstID, secondID string, f func(*state.State, *state.State, t1, t2) error) error {
|
||||
func DoState2[t1, t2 any](s ObjectGetter, firstID, secondID string, f func(*state.State, *state.State, t1, t2) error) error {
|
||||
if firstID == secondID {
|
||||
return DoStateAsync(s, firstID, func(st *state.State, b t1) error {
|
||||
// Check that b satisfies t2
|
||||
|
@ -76,9 +95,9 @@ func DoState2[t1, t2 any](s Picker, firstID, secondID string, f func(*state.Stat
|
|||
})
|
||||
}
|
||||
|
||||
func DoStateAsync[t any](p Picker, id string, apply func(s *state.State, sb t) error, flags ...smartblock.ApplyFlag) error {
|
||||
func DoStateAsync[t any](p ObjectGetter, id string, apply func(s *state.State, sb t) error, flags ...smartblock.ApplyFlag) error {
|
||||
ctx := context.Background()
|
||||
sb, err := p.PickBlock(ctx, id)
|
||||
sb, err := p.GetObject(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -102,8 +121,8 @@ func DoStateAsync[t any](p Picker, id string, apply func(s *state.State, sb t) e
|
|||
}
|
||||
|
||||
// TODO rename to something more meaningful
|
||||
func DoStateCtx[t any](p Picker, ctx session.Context, id string, apply func(s *state.State, sb t) error, flags ...smartblock.ApplyFlag) error {
|
||||
sb, err := p.PickBlock(context.Background(), id)
|
||||
func DoStateCtx[t any](p ObjectGetter, ctx session.Context, id string, apply func(s *state.State, sb t) error, flags ...smartblock.ApplyFlag) error {
|
||||
sb, err := p.GetObject(context.Background(), id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ type Service struct {
|
|||
lock *sync.RWMutex
|
||||
collections map[string]map[string]chan []string
|
||||
systemObjectService system_object.Service
|
||||
picker block.Picker
|
||||
picker block.ObjectGetter
|
||||
objectStore objectstore.ObjectStore
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ func New() *Service {
|
|||
}
|
||||
|
||||
func (s *Service) Init(a *app.App) (err error) {
|
||||
s.picker = app.MustComponent[block.Picker](a)
|
||||
s.picker = app.MustComponent[block.ObjectGetter](a)
|
||||
s.objectStore = app.MustComponent[objectstore.ObjectStore](a)
|
||||
s.systemObjectService = app.MustComponent[system_object.Service](a)
|
||||
return nil
|
||||
|
|
|
@ -26,7 +26,11 @@ type testPicker struct {
|
|||
sb smartblock.SmartBlock
|
||||
}
|
||||
|
||||
func (t *testPicker) PickBlock(ctx context.Context, id string) (sb smartblock.SmartBlock, err error) {
|
||||
func (t *testPicker) GetObject(ctx context.Context, id string) (sb smartblock.SmartBlock, err error) {
|
||||
return t.sb, nil
|
||||
}
|
||||
|
||||
func (t *testPicker) GetObjectByFullID(ctx context.Context, id domain.FullID) (sb smartblock.SmartBlock, err error) {
|
||||
return t.sb, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
|
||||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/basic"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
|
@ -31,13 +30,13 @@ func (s *Service) TemplateCreateFromObject(ctx context.Context, id string) (temp
|
|||
return fmt.Errorf("can't make template from this obect type")
|
||||
}
|
||||
objectTypeKeys = b.ObjectTypeKeys()
|
||||
st, err = b.TemplateCreateFromObjectState()
|
||||
st, err = s.templateCreateFromObjectState(b)
|
||||
return err
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
spaceID, err := s.ResolveSpaceID(id)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(id)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -49,6 +48,23 @@ func (s *Service) TemplateCreateFromObject(ctx context.Context, id string) (temp
|
|||
return
|
||||
}
|
||||
|
||||
func (s *Service) templateCreateFromObjectState(sb smartblock.SmartBlock) (*state.State, error) {
|
||||
st := sb.NewState().Copy()
|
||||
st.SetLocalDetails(nil)
|
||||
targetObjectTypeID, err := s.systemObjectService.GetTypeIdByKey(context.Background(), sb.SpaceID(), st.ObjectTypeKey())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get type id by key: %s", err)
|
||||
}
|
||||
st.SetDetail(bundle.RelationKeyTargetObjectType.String(), pbtypes.String(targetObjectTypeID))
|
||||
st.SetObjectTypeKeys([]domain.TypeKey{bundle.TypeKeyTemplate, st.ObjectTypeKey()})
|
||||
for _, rel := range sb.Relations(st) {
|
||||
if rel.DataSource == model.Relation_details && !rel.Hidden {
|
||||
st.RemoveDetail(rel.Key)
|
||||
}
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
func (s *Service) TemplateClone(spaceID string, id string) (templateID string, err error) {
|
||||
var (
|
||||
st *state.State
|
||||
|
@ -104,7 +120,7 @@ func (s *Service) ObjectDuplicate(ctx context.Context, id string) (objectID stri
|
|||
return
|
||||
}
|
||||
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(id)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(id)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -146,39 +162,11 @@ func (s *Service) TemplateCreateFromObjectByObjectType(ctx context.Context, obje
|
|||
}
|
||||
|
||||
func (s *Service) CreateWorkspace(ctx context.Context, req *pb.RpcWorkspaceCreateRequest) (spaceID string, err error) {
|
||||
spc, err := s.spaceService.CreateSpace(ctx)
|
||||
newSpace, err := s.spaceService.Create(ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("create space: %w", err)
|
||||
}
|
||||
|
||||
predefinedObjectIDs, err := s.anytype.DerivePredefinedObjects(ctx, spc.Id(), true)
|
||||
if err != nil {
|
||||
// TODO Delete space?
|
||||
return "", fmt.Errorf("derive workspace object for space %s: %w", spc.Id(), err)
|
||||
}
|
||||
|
||||
err = DoStateAsync(s, s.anytype.AccountObjects().Workspace, func(st *state.State, b *editor.Workspaces) error {
|
||||
spaces := pbtypes.CopyVal(st.Store().GetFields()["spaces"])
|
||||
if spaces == nil {
|
||||
spaces = pbtypes.Struct(&types.Struct{
|
||||
Fields: map[string]*types.Value{
|
||||
spc.Id(): pbtypes.String(predefinedObjectIDs.Workspace),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
spaces.GetStructValue().Fields[spc.Id()] = pbtypes.String(predefinedObjectIDs.Workspace)
|
||||
}
|
||||
st.SetInStore([]string{"spaces"}, spaces)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("add space to account space: %w", err)
|
||||
}
|
||||
|
||||
err = s.indexer.EnsurePreinstalledObjects(spc.Id())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("reindex space %s: %w", spc.Id(), err)
|
||||
return "", fmt.Errorf("error creating space: %w", err)
|
||||
}
|
||||
predefinedObjectIDs := newSpace.DerivedIDs()
|
||||
|
||||
err = Do(s, predefinedObjectIDs.Workspace, func(b basic.DetailsSettable) error {
|
||||
details := make([]*pb.RpcObjectSetDetailsDetail, 0, len(req.Details.GetFields()))
|
||||
|
@ -191,14 +179,13 @@ func (s *Service) CreateWorkspace(ctx context.Context, req *pb.RpcWorkspaceCreat
|
|||
return b.SetDetails(nil, details, true)
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("set details for space %s: %w", spc.Id(), err)
|
||||
return "", fmt.Errorf("set details for space %s: %w", newSpace.Id(), err)
|
||||
}
|
||||
|
||||
_, err = s.builtinObjectService.CreateObjectsForUseCase(nil, spc.Id(), req.UseCase)
|
||||
_, err = s.builtinObjectService.CreateObjectsForUseCase(nil, newSpace.Id(), req.UseCase)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("import use-case: %w", err)
|
||||
}
|
||||
return spc.Id(), err
|
||||
return newSpace.Id(), err
|
||||
}
|
||||
|
||||
// CreateLinkToTheNewObject creates an object and stores the link to it in the context block
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
package block
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
)
|
||||
|
||||
func (s *Service) CreateTreePayload(ctx context.Context, spaceID string, tp coresb.SmartBlockType, createdTime time.Time) (treestorage.TreeStorageCreatePayload, error) {
|
||||
space, err := s.spaceService.GetSpace(ctx, spaceID)
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
return s.CreateTreePayloadWithSpaceAndCreatedTime(ctx, space, tp, createdTime)
|
||||
}
|
||||
|
||||
func (s *Service) CreateTreePayloadWithSpace(ctx context.Context, space commonspace.Space, tp coresb.SmartBlockType) (treestorage.TreeStorageCreatePayload, error) {
|
||||
return s.CreateTreePayloadWithSpaceAndCreatedTime(ctx, space, tp, time.Now())
|
||||
}
|
||||
|
||||
func (s *Service) CreateTreePayloadWithSpaceAndCreatedTime(ctx context.Context, space commonspace.Space, tp coresb.SmartBlockType, createdTime time.Time) (treestorage.TreeStorageCreatePayload, error) {
|
||||
changePayload, err := createChangePayload(tp, nil)
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
treePayload, err := createPayload(space.Id(), s.commonAccount.Account().SignKey, changePayload, createdTime.Unix())
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
return space.TreeBuilder().CreateTree(ctx, treePayload)
|
||||
}
|
||||
|
||||
func (s *Service) CreateTreeObjectWithPayload(ctx context.Context, spaceID string, payload treestorage.TreeStorageCreatePayload, initFunc smartblock.InitFunc) (sb smartblock.SmartBlock, err error) {
|
||||
space, err := s.spaceService.GetSpace(ctx, spaceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id := domain.FullID{
|
||||
SpaceID: spaceID,
|
||||
ObjectID: payload.RootRawChange.Id,
|
||||
}
|
||||
tr, err := space.TreeBuilder().PutTree(ctx, payload, nil)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to put tree: %w", err)
|
||||
return
|
||||
}
|
||||
if tr != nil {
|
||||
tr.Close()
|
||||
}
|
||||
return s.cacheCreatedObject(ctx, id, initFunc)
|
||||
}
|
||||
|
||||
func (s *Service) CreateTreeObject(ctx context.Context, spaceID string, tp coresb.SmartBlockType, initFunc smartblock.InitFunc) (sb smartblock.SmartBlock, err error) {
|
||||
space, err := s.spaceService.GetSpace(ctx, spaceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payload, err := s.CreateTreePayloadWithSpace(ctx, space, tp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.CreateTreeObjectWithPayload(ctx, spaceID, payload, initFunc)
|
||||
}
|
||||
|
||||
func (s *Service) cacheCreatedObject(ctx context.Context, id domain.FullID, initFunc smartblock.InitFunc) (sb smartblock.SmartBlock, err error) {
|
||||
ctx = objectcache.ContextWithCreateOption(ctx, initFunc)
|
||||
return s.objectCache.GetObject(ctx, id)
|
||||
}
|
|
@ -18,7 +18,7 @@ import (
|
|||
)
|
||||
|
||||
func (s *Service) DeleteObject(objectID string) (err error) {
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(objectID)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(objectID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -70,7 +70,8 @@ func (s *Service) DeleteObject(objectID string) (err error) {
|
|||
})
|
||||
default:
|
||||
var space commonspace.Space
|
||||
space, err = s.spaceService.GetSpace(context.Background(), spaceID)
|
||||
// TODO: [MR] should we do this via spaceService instead?
|
||||
space, err = s.spaceCore.Get(context.Background(), spaceID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
package block
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treechangeproto"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
"github.com/anyproto/any-sync/commonspace/spacesyncproto"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/block/source"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
derivedObjectLoadTimeout = time.Minute * 30
|
||||
)
|
||||
|
||||
// DeriveTreeCreatePayload creates payload for the tree of derived object.
|
||||
// Method should be called before DeriveObject to prepare payload
|
||||
func (s *Service) DeriveTreeCreatePayload(
|
||||
ctx context.Context,
|
||||
spaceID string,
|
||||
key domain.UniqueKey,
|
||||
) (treestorage.TreeStorageCreatePayload, error) {
|
||||
space, err := s.spaceService.GetSpace(ctx, spaceID)
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
changePayload, err := createChangePayload(key.SmartblockType(), key)
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
treePayload := derivePayload(space.Id(), s.commonAccount.Account().SignKey, changePayload)
|
||||
create, err := space.TreeBuilder().CreateTree(context.Background(), treePayload)
|
||||
return create, err
|
||||
}
|
||||
|
||||
// DeriveObject derives the object with id specified in the payload and triggers cache.Get
|
||||
// DeriveTreeCreatePayload should be called first to prepare the payload and derive the tree
|
||||
func (s *Service) DeriveObject(
|
||||
ctx context.Context, spaceID string, payload treestorage.TreeStorageCreatePayload, newAccount bool,
|
||||
) (err error) {
|
||||
space, err := s.spaceService.GetSpace(ctx, spaceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get space: %w", err)
|
||||
}
|
||||
_, err = s.getDerivedObject(ctx, space, &payload, newAccount, func(id string) *smartblock.InitContext {
|
||||
return &smartblock.InitContext{Ctx: ctx, SpaceID: spaceID, State: state.NewDoc(id, nil).(*state.State)}
|
||||
})
|
||||
if err != nil {
|
||||
log.With(zap.Error(err)).Debug("derived object with error")
|
||||
return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) DeriveTreeObjectWithUniqueKey(ctx context.Context, spaceID string, key domain.UniqueKey, initFunc smartblock.InitFunc) (sb smartblock.SmartBlock, err error) {
|
||||
payload, err := s.DeriveTreeCreatePayload(ctx, spaceID, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.CreateTreeObjectWithPayload(ctx, spaceID, payload, initFunc)
|
||||
}
|
||||
|
||||
func (s *Service) getDerivedObject(
|
||||
ctx context.Context, space commonspace.Space, payload *treestorage.TreeStorageCreatePayload, newAccount bool, initFunc smartblock.InitFunc,
|
||||
) (sb smartblock.SmartBlock, err error) {
|
||||
id := domain.FullID{
|
||||
SpaceID: space.Id(),
|
||||
ObjectID: payload.RootRawChange.Id,
|
||||
}
|
||||
if newAccount {
|
||||
var tr objecttree.ObjectTree
|
||||
tr, err = space.TreeBuilder().PutTree(ctx, *payload, nil)
|
||||
s.predefinedObjectWasMissing = true
|
||||
if err != nil {
|
||||
if !errors.Is(err, treestorage.ErrTreeExists) {
|
||||
err = fmt.Errorf("failed to put tree: %w", err)
|
||||
return
|
||||
}
|
||||
s.predefinedObjectWasMissing = false
|
||||
// the object exists locally
|
||||
return s.objectCache.GetObjectWithTimeout(ctx, id)
|
||||
}
|
||||
tr.Close()
|
||||
return s.cacheCreatedObject(ctx, id, initFunc)
|
||||
}
|
||||
|
||||
// timing out when getting objects from remote
|
||||
// here we set very long timeout, because we must load these documents
|
||||
ctx, cancel := context.WithTimeout(ctx, derivedObjectLoadTimeout)
|
||||
|
||||
// TODO: revive p2p (right now we are not ready to load from local clients due to the fact that we need to know when local peers connect)
|
||||
ctx = objectcache.ContextWithBuildOptions(ctx, source.BuildOptions{})
|
||||
defer cancel()
|
||||
|
||||
sb, err = s.objectCache.GetObjectWithTimeout(ctx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, treechangeproto.ErrGetTree) {
|
||||
err = spacesyncproto.ErrSpaceMissing
|
||||
}
|
||||
err = fmt.Errorf("failed to get object from node: %w", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
|
@ -374,7 +374,7 @@ func (bs *basic) AddRelationAndSet(ctx session.Context, systemObjectService syst
|
|||
return smartblock.ErrSimpleBlockNotFound
|
||||
}
|
||||
|
||||
rel, err := systemObjectService.FetchRelationByKey(s.SpaceID(), req.RelationKey)
|
||||
rel, err := systemObjectService.FetchRelationByKey(bs.SpaceID(), req.RelationKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ func (bs *basic) createDetailUpdate(st *state.State, detail *pb.RpcObjectSetDeta
|
|||
if err := bs.addRelationLink(detail.Key, st); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := bs.validateDetailFormat(st.SpaceID(), detail.Key, detail.Value); err != nil {
|
||||
if err := bs.validateDetailFormat(bs.SpaceID(), detail.Key, detail.Value); err != nil {
|
||||
return nil, fmt.Errorf("failed to validate relation: %w", err)
|
||||
}
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ func (bs *basic) setDetailSpecialCases(st *state.State, detail *pb.RpcObjectSetD
|
|||
|
||||
func (bs *basic) addRelationLink(relationKey string, st *state.State) error {
|
||||
// TODO: add relation.WithWorkspaceId(workspaceId) filter
|
||||
rel, err := bs.systemObjectService.FetchRelationByKey(st.SpaceID(), relationKey)
|
||||
rel, err := bs.systemObjectService.FetchRelationByKey(bs.SpaceID(), relationKey)
|
||||
if err != nil || rel == nil {
|
||||
return fmt.Errorf("failed to get relation: %w", err)
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ var log = logging.Logger("bookmark")
|
|||
|
||||
func NewBookmark(
|
||||
sb smartblock.SmartBlock,
|
||||
picker getblock.Picker,
|
||||
picker getblock.ObjectGetter,
|
||||
bookmarkSvc BookmarkService,
|
||||
objectStore objectstore.ObjectStore,
|
||||
) Bookmark {
|
||||
|
@ -51,7 +51,7 @@ type BookmarkService interface {
|
|||
|
||||
type sbookmark struct {
|
||||
smartblock.SmartBlock
|
||||
picker getblock.Picker
|
||||
picker getblock.ObjectGetter
|
||||
bookmarkSvc BookmarkService
|
||||
objectStore objectstore.ObjectStore
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/database"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
)
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
)
|
||||
|
@ -105,7 +105,7 @@ func (d *sdataview) SetSource(ctx session.Context, blockId string, source []stri
|
|||
return d.Apply(s, smartblock.NoRestrictions)
|
||||
}
|
||||
|
||||
dvContent, _, err := BlockBySource(s.SpaceID(), d.sbtProvider, d.systemObjectService, source)
|
||||
dvContent, _, err := BlockBySource(d.SpaceID(), d.sbtProvider, d.systemObjectService, source)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ func (d *sdataview) AddRelations(ctx session.Context, blockId string, relationKe
|
|||
return err
|
||||
}
|
||||
for _, key := range relationKeys {
|
||||
relation, err2 := d.systemObjectService.FetchRelationByKey(s.SpaceID(), key)
|
||||
relation, err2 := d.systemObjectService.FetchRelationByKey(d.SpaceID(), key)
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package editor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
||||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/anytype/config"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/bookmark"
|
||||
|
@ -22,11 +24,24 @@ import (
|
|||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
)
|
||||
|
||||
var log = logging.Logger("anytype-mw-editor")
|
||||
|
||||
type spaceIndexer interface {
|
||||
smartblock.Indexer
|
||||
ReindexSpace(spaceID string) error
|
||||
}
|
||||
|
||||
type personalIDProvider interface {
|
||||
PersonalSpaceID() string
|
||||
}
|
||||
|
||||
type bundledObjectsInstaller interface {
|
||||
InstallBundledObjects(ctx context.Context, spaceID string, ids []string) ([]string, []*types.Struct, error)
|
||||
}
|
||||
|
||||
type ObjectFactory struct {
|
||||
anytype core.Service
|
||||
bookmarkService bookmark.BookmarkService
|
||||
|
@ -40,10 +55,11 @@ type ObjectFactory struct {
|
|||
tempDirProvider core.TempDirProvider
|
||||
fileService files.Service
|
||||
config *config.Config
|
||||
picker getblock.Picker
|
||||
picker getblock.ObjectGetter
|
||||
eventSender event.Sender
|
||||
restrictionService restriction.Service
|
||||
indexer smartblock.Indexer
|
||||
indexer spaceIndexer
|
||||
spaceService spaceService
|
||||
objectDeriver objectDeriver
|
||||
}
|
||||
|
||||
|
@ -65,10 +81,11 @@ func (f *ObjectFactory) Init(a *app.App) (err error) {
|
|||
f.tempDirProvider = app.MustComponent[core.TempDirProvider](a)
|
||||
f.sbtProvider = app.MustComponent[typeprovider.SmartBlockTypeProvider](a)
|
||||
f.layoutConverter = app.MustComponent[converter.LayoutConverter](a)
|
||||
f.picker = app.MustComponent[getblock.Picker](a)
|
||||
f.indexer = app.MustComponent[smartblock.Indexer](a)
|
||||
f.picker = app.MustComponent[getblock.ObjectGetter](a)
|
||||
f.indexer = app.MustComponent[spaceIndexer](a)
|
||||
f.eventSender = app.MustComponent[event.Sender](a)
|
||||
f.objectDeriver = app.MustComponent[objectDeriver](a)
|
||||
f.spaceService = app.MustComponent[spaceService](a)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -214,6 +231,11 @@ func (f *ObjectFactory) New(sbType coresb.SmartBlockType) (smartblock.SmartBlock
|
|||
f.eventSender,
|
||||
f.objectDeriver,
|
||||
), nil
|
||||
case coresb.SmartBlockTypeSpaceView:
|
||||
return newSpaceView(
|
||||
sb,
|
||||
f.spaceService,
|
||||
), nil
|
||||
case coresb.SmartBlockTypeMissingObject:
|
||||
return NewMissingObject(sb), nil
|
||||
case coresb.SmartBlockTypeWidget:
|
||||
|
|
|
@ -47,7 +47,7 @@ func NewFile(
|
|||
idGetter PredefinedObjectsGetter,
|
||||
tempDirProvider core.TempDirProvider,
|
||||
fileService files.Service,
|
||||
picker getblock.Picker,
|
||||
picker getblock.ObjectGetter,
|
||||
) File {
|
||||
return &sfile{
|
||||
SmartBlock: sb,
|
||||
|
@ -88,7 +88,7 @@ type sfile struct {
|
|||
fileSource BlockService
|
||||
tempDirProvider core.TempDirProvider
|
||||
fileService files.Service
|
||||
picker getblock.Picker
|
||||
picker getblock.ObjectGetter
|
||||
predefinedObjects PredefinedObjectsGetter
|
||||
}
|
||||
|
||||
|
@ -322,7 +322,7 @@ type dropFilesProcess struct {
|
|||
id string
|
||||
spaceID string
|
||||
s BlockService
|
||||
picker getblock.Picker
|
||||
picker getblock.ObjectGetter
|
||||
fileService files.Service
|
||||
tempDirProvider core.TempDirProvider
|
||||
root *dropFileEntry
|
||||
|
|
|
@ -45,7 +45,7 @@ func NewUploader(
|
|||
s BlockService,
|
||||
fileService files.Service,
|
||||
provider core.TempDirProvider,
|
||||
picker getblock.Picker,
|
||||
picker getblock.ObjectGetter,
|
||||
) Uploader {
|
||||
return &uploader{
|
||||
spaceID: spaceID,
|
||||
|
@ -107,7 +107,7 @@ func (ur UploadResult) ToBlock() file.Block {
|
|||
type uploader struct {
|
||||
spaceID string
|
||||
service BlockService
|
||||
picker getblock.Picker
|
||||
picker getblock.ObjectGetter
|
||||
block file.Block
|
||||
getReader func(ctx context.Context) (*fileReader, error)
|
||||
name string
|
||||
|
|
|
@ -42,7 +42,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
fx.fileService.EXPECT().ImageAdd(gomock.Any(), gomock.Any(), gomock.Any()).Return(im, nil)
|
||||
im.EXPECT().GetOriginalFile(gomock.Any()).Return(fx.file, nil)
|
||||
b := newBlock(model.BlockContentFile_Image)
|
||||
fx.picker.EXPECT().PickBlock(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.picker.EXPECT().GetObject(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.file.EXPECT().Meta().Return(&files.FileMeta{Media: "image/jpg"}).AnyTimes()
|
||||
res := fx.Uploader.SetBlock(b).SetFile("./testdata/unnamed.jpg").Upload(ctx)
|
||||
require.NoError(t, res.Err)
|
||||
|
@ -55,7 +55,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
fx := newFixture(t)
|
||||
defer fx.tearDown()
|
||||
im := fx.newImage("123")
|
||||
fx.picker.EXPECT().PickBlock(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.picker.EXPECT().GetObject(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.fileService.EXPECT().ImageAdd(gomock.Any(), gomock.Any(), gomock.Any()).Return(im, nil)
|
||||
im.EXPECT().GetOriginalFile(gomock.Any())
|
||||
res := fx.Uploader.AutoType(true).SetFile("./testdata/unnamed.jpg").Upload(ctx)
|
||||
|
@ -71,7 +71,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
Added: time.Now(),
|
||||
}
|
||||
// fx.anytype.EXPECT().ImageAdd(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, image.ErrFormat)
|
||||
fx.picker.EXPECT().PickBlock(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.picker.EXPECT().GetObject(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.fileService.EXPECT().FileAdd(gomock.Any(), gomock.Any(), gomock.Any()).Return(fx.newFile("123", meta), nil)
|
||||
b := newBlock(model.BlockContentFile_Image)
|
||||
res := fx.Uploader.SetBlock(b).SetFile("./testdata/test.txt").Upload(ctx)
|
||||
|
@ -92,7 +92,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
fx := newFixture(t)
|
||||
defer fx.tearDown()
|
||||
im := fx.newImage("123")
|
||||
fx.picker.EXPECT().PickBlock(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.picker.EXPECT().GetObject(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.fileService.EXPECT().ImageAdd(gomock.Any(), gomock.Any(), gomock.Any()).Return(im, nil)
|
||||
im.EXPECT().GetOriginalFile(gomock.Any())
|
||||
res := fx.Uploader.AutoType(true).SetUrl(serv.URL + "/unnamed.jpg").Upload(ctx)
|
||||
|
@ -115,7 +115,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
fx := newFixture(t)
|
||||
defer fx.tearDown()
|
||||
im := fx.newImage("123")
|
||||
fx.picker.EXPECT().PickBlock(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.picker.EXPECT().GetObject(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.fileService.EXPECT().ImageAdd(gomock.Any(), gomock.Any(), gomock.Any()).Return(im, nil)
|
||||
im.EXPECT().GetOriginalFile(gomock.Any())
|
||||
res := fx.Uploader.AutoType(true).SetUrl(serv.URL + "/unnamed.jpg").Upload(ctx)
|
||||
|
@ -137,7 +137,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
fx := newFixture(t)
|
||||
defer fx.tearDown()
|
||||
im := fx.newImage("123")
|
||||
fx.picker.EXPECT().PickBlock(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.picker.EXPECT().GetObject(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.fileService.EXPECT().ImageAdd(gomock.Any(), gomock.Any(), gomock.Any()).Return(im, nil)
|
||||
im.EXPECT().GetOriginalFile(gomock.Any())
|
||||
res := fx.Uploader.AutoType(true).SetUrl(serv.URL + "/unnamed.jpg?text=text").Upload(ctx)
|
||||
|
@ -151,7 +151,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
t.Run("bytes", func(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
defer fx.tearDown()
|
||||
fx.picker.EXPECT().PickBlock(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.picker.EXPECT().GetObject(mock.Anything, mock.Anything).Return(nil, nil)
|
||||
fx.fileService.EXPECT().FileAdd(gomock.Any(), gomock.Any(), gomock.Any()).Return(fx.newFile("123", &files.FileMeta{}), nil)
|
||||
res := fx.Uploader.SetBytes([]byte("my bytes")).SetName("filename").Upload(ctx)
|
||||
require.NoError(t, res.Err)
|
||||
|
@ -161,7 +161,7 @@ func TestUploader_Upload(t *testing.T) {
|
|||
}
|
||||
|
||||
func newFixture(t *testing.T) *uplFixture {
|
||||
picker := mock_getblock.NewMockPicker(t)
|
||||
picker := mock_getblock.NewMockObjectGetter(t)
|
||||
fx := &uplFixture{
|
||||
ctrl: gomock.NewController(t),
|
||||
picker: picker,
|
||||
|
@ -181,7 +181,7 @@ type uplFixture struct {
|
|||
file *testMock.MockFile
|
||||
fileService *testMock.MockFileService
|
||||
ctrl *gomock.Controller
|
||||
picker *mock_getblock.MockPicker
|
||||
picker *mock_getblock.MockObjectGetter
|
||||
}
|
||||
|
||||
func (fx *uplFixture) newImage(hash string) *testMock.MockImage {
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
@ -48,7 +48,7 @@ func NewPage(
|
|||
objectStore objectstore.ObjectStore,
|
||||
anytype core.Service,
|
||||
fileBlockService file.BlockService,
|
||||
picker getblock.Picker,
|
||||
picker getblock.ObjectGetter,
|
||||
bookmarkService bookmark.BookmarkService,
|
||||
systemObjectService system_object.Service,
|
||||
tempDirProvider core.TempDirProvider,
|
||||
|
@ -124,7 +124,7 @@ func (p *Page) CreationStateMigration(ctx *smartblock.InitContext) migration.Mig
|
|||
if err != nil {
|
||||
log.Errorf("failed to create unique key: %v", err)
|
||||
} else {
|
||||
otype, err := p.systemObjectService.GetObjectByUniqueKey(s.SpaceID(), uk)
|
||||
otype, err := p.systemObjectService.GetObjectByUniqueKey(p.SpaceID(), uk)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get object by unique key: %v", err)
|
||||
} else {
|
||||
|
|
|
@ -46,7 +46,7 @@ func NewProfile(
|
|||
systemObjectService system_object.Service,
|
||||
fileBlockService file.BlockService,
|
||||
anytype core.Service,
|
||||
picker getblock.Picker,
|
||||
picker getblock.ObjectGetter,
|
||||
bookmarkService bookmark.BookmarkService,
|
||||
tempDirProvider core.TempDirProvider,
|
||||
layoutConverter converter.LayoutConverter,
|
||||
|
|
|
@ -126,7 +126,6 @@ type SmartBlock interface {
|
|||
AddRelationLinks(ctx session.Context, relationIds ...string) (err error)
|
||||
AddRelationLinksToState(s *state.State, relationIds ...string) (err error)
|
||||
RemoveExtraRelations(ctx session.Context, relationKeys []string) (err error)
|
||||
TemplateCreateFromObjectState() (*state.State, error)
|
||||
SetVerticalAlign(ctx session.Context, align model.BlockVerticalAlign, ids ...string) error
|
||||
SetIsDeleted()
|
||||
IsDeleted() bool
|
||||
|
@ -872,7 +871,7 @@ func (sb *smartBlock) AddRelationLinksToState(s *state.State, relationKeys ...st
|
|||
if len(relationKeys) == 0 {
|
||||
return
|
||||
}
|
||||
relations, err := sb.systemObjectService.FetchRelationByKeys(s.SpaceID(), relationKeys...)
|
||||
relations, err := sb.systemObjectService.FetchRelationByKeys(sb.SpaceID(), relationKeys...)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -989,23 +988,6 @@ func (sb *smartBlock) SetVerticalAlign(ctx session.Context, align model.BlockVer
|
|||
return sb.Apply(s)
|
||||
}
|
||||
|
||||
func (sb *smartBlock) TemplateCreateFromObjectState() (*state.State, error) {
|
||||
st := sb.NewState().Copy()
|
||||
st.SetLocalDetails(nil)
|
||||
targetObjectTypeID, err := sb.systemObjectService.GetTypeIdByKey(context.Background(), st.SpaceID(), st.ObjectTypeKey())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get type id by key: %s", err)
|
||||
}
|
||||
st.SetDetail(bundle.RelationKeyTargetObjectType.String(), pbtypes.String(targetObjectTypeID))
|
||||
st.SetObjectTypeKeys([]domain.TypeKey{bundle.TypeKeyTemplate, st.ObjectTypeKey()})
|
||||
for _, rel := range sb.Relations(st) {
|
||||
if rel.DataSource == model.Relation_details && !rel.Hidden {
|
||||
st.RemoveDetail(rel.Key)
|
||||
}
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
func (sb *smartBlock) RemoveExtraRelations(ctx session.Context, relationIds []string) (err error) {
|
||||
st := sb.NewStateCtx(ctx)
|
||||
st.RemoveRelation(relationIds...)
|
||||
|
|
89
core/block/editor/spaceview.go
Normal file
89
core/block/editor/spaceview.go
Normal file
|
@ -0,0 +1,89 @@
|
|||
package editor
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/spaceinfo"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
var ErrIncorrectSpaceInfo = errors.New("space info is incorrect")
|
||||
|
||||
type spaceService interface {
|
||||
OnViewCreated(spaceID string)
|
||||
}
|
||||
|
||||
// SpaceView is a wrapper around smartblock.SmartBlock that indicates the current space state
|
||||
type SpaceView struct {
|
||||
smartblock.SmartBlock
|
||||
spaceService spaceService
|
||||
}
|
||||
|
||||
// newSpaceView creates a new SpaceView with given deps
|
||||
func newSpaceView(sb smartblock.SmartBlock, spaceService spaceService) *SpaceView {
|
||||
return &SpaceView{
|
||||
SmartBlock: sb,
|
||||
spaceService: spaceService,
|
||||
}
|
||||
}
|
||||
|
||||
// Init initializes SpaceView
|
||||
func (s *SpaceView) Init(ctx *smartblock.InitContext) (err error) {
|
||||
if err = s.SmartBlock.Init(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
spaceID, err := s.targetSpaceID()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
s.DisableLayouts()
|
||||
s.spaceService.OnViewCreated(spaceID)
|
||||
return s.setSpaceInfo(ctx.State, spaceinfo.SpaceInfo{})
|
||||
}
|
||||
|
||||
func (s *SpaceView) TryClose(objectTTL time.Duration) (res bool, err error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (s *SpaceView) SetSpaceInfo(info spaceinfo.SpaceInfo) (err error) {
|
||||
st := s.NewState()
|
||||
if err = s.setSpaceInfo(st, info); err != nil {
|
||||
return
|
||||
}
|
||||
return s.Apply(st)
|
||||
}
|
||||
|
||||
func (s *SpaceView) setSpaceInfo(st *state.State, info spaceinfo.SpaceInfo) (err error) {
|
||||
st.SetLocalDetail(bundle.RelationKeySpaceLocalStatus.String(), pbtypes.Int64(int64(info.LocalStatus)))
|
||||
st.SetLocalDetail(bundle.RelationKeySpaceRemoteStatus.String(), pbtypes.Int64(int64(info.RemoteStatus)))
|
||||
return
|
||||
}
|
||||
|
||||
// targetSpaceID returns space id from the root of space object's tree
|
||||
func (s *SpaceView) targetSpaceID() (id string, err error) {
|
||||
changeInfo := s.Tree().ChangeInfo()
|
||||
if changeInfo == nil {
|
||||
return "", ErrIncorrectSpaceInfo
|
||||
}
|
||||
var (
|
||||
changePayload = &model.ObjectChangePayload{}
|
||||
spaceHeader = &model.SpaceObjectHeader{}
|
||||
)
|
||||
err = proto.Unmarshal(changeInfo.ChangePayload, changePayload)
|
||||
if err != nil {
|
||||
return "", ErrIncorrectSpaceInfo
|
||||
}
|
||||
err = proto.Unmarshal(changePayload.Data, spaceHeader)
|
||||
if err != nil {
|
||||
return "", ErrIncorrectSpaceInfo
|
||||
}
|
||||
return spaceHeader.SpaceID, nil
|
||||
}
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
smartblock2 "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
|
@ -17,7 +18,7 @@ import (
|
|||
)
|
||||
|
||||
type objectDeriver interface {
|
||||
DeriveTreeObjectWithUniqueKey(ctx context.Context, spaceID string, key domain.UniqueKey, initFunc smartblock.InitFunc) (sb smartblock.SmartBlock, err error)
|
||||
DeriveTreeObject(ctx context.Context, spaceID string, params objectcache.TreeDerivationParams) (sb smartblock.SmartBlock, err error)
|
||||
}
|
||||
|
||||
// Migrate legacy sub-objects to ordinary objects
|
||||
|
@ -51,15 +52,18 @@ func (m *subObjectsMigration) migrateSubObject(
|
|||
if err != nil {
|
||||
return "", fmt.Errorf("unmarshal unique key: %w", err)
|
||||
}
|
||||
sb, err := m.objectDeriver.DeriveTreeObjectWithUniqueKey(ctx, m.workspace.SpaceID(), uniqueKey, func(id string) *smartblock.InitContext {
|
||||
st := state.NewDocWithUniqueKey(id, nil, uniqueKey).NewState()
|
||||
st.SetDetails(details)
|
||||
st.SetObjectTypeKey(typeKey)
|
||||
return &smartblock.InitContext{
|
||||
IsNewObject: true,
|
||||
State: st,
|
||||
SpaceID: m.workspace.SpaceID(),
|
||||
}
|
||||
sb, err := m.objectDeriver.DeriveTreeObject(ctx, m.workspace.SpaceID(), objectcache.TreeDerivationParams{
|
||||
Key: uniqueKey,
|
||||
InitFunc: func(id string) *smartblock.InitContext {
|
||||
st := state.NewDocWithUniqueKey(id, nil, uniqueKey).NewState()
|
||||
st.SetDetails(details)
|
||||
st.SetObjectTypeKey(typeKey)
|
||||
return &smartblock.InitContext{
|
||||
IsNewObject: true,
|
||||
State: st,
|
||||
SpaceID: m.workspace.SpaceID(),
|
||||
}
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
@ -19,14 +19,14 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
type Template struct {
|
||||
*Page
|
||||
|
||||
picker getblock.Picker
|
||||
picker getblock.ObjectGetter
|
||||
}
|
||||
|
||||
func NewTemplate(
|
||||
|
@ -34,7 +34,7 @@ func NewTemplate(
|
|||
objectStore objectstore.ObjectStore,
|
||||
anytype core.Service,
|
||||
fileBlockService file.BlockService,
|
||||
picker getblock.Picker,
|
||||
picker getblock.ObjectGetter,
|
||||
bookmarkService bookmark.BookmarkService,
|
||||
systemObjectService system_object.Service,
|
||||
tempDirProvider core.TempDirProvider,
|
||||
|
|
|
@ -32,7 +32,6 @@ func NewTemplateTest(t *testing.T, ctrl *gomock.Controller, templateName string)
|
|||
objectStore := testMock.NewMockObjectStore(ctrl)
|
||||
|
||||
systemObjectService := mock_system_object.NewMockService(t)
|
||||
systemObjectService.EXPECT().GetObjectTypes(mock.Anything).Return(nil, nil).Maybe()
|
||||
templ := &Template{
|
||||
Page: &Page{
|
||||
SmartBlock: sb,
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block"
|
||||
sb "github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/getblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/block/process"
|
||||
"github.com/anyproto/anytype-heart/core/converter"
|
||||
"github.com/anyproto/anytype-heart/core/converter/dot"
|
||||
|
@ -38,8 +39,8 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/constant"
|
||||
oserror "github.com/anyproto/anytype-heart/util/os"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
|
@ -59,13 +60,14 @@ type Export interface {
|
|||
|
||||
type export struct {
|
||||
blockService *block.Service
|
||||
picker getblock.Picker
|
||||
picker getblock.ObjectGetter
|
||||
objectStore objectstore.ObjectStore
|
||||
coreService core.Service
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
fileService files.Service
|
||||
systemObjectService system_object.Service
|
||||
spaceService space.Service
|
||||
spaceService spacecore.SpaceCoreService
|
||||
resolver idresolver.Resolver
|
||||
}
|
||||
|
||||
func New() Export {
|
||||
|
@ -77,10 +79,11 @@ func (e *export) Init(a *app.App) (err error) {
|
|||
e.coreService = a.MustComponent(core.CName).(core.Service)
|
||||
e.objectStore = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
e.fileService = app.MustComponent[files.Service](a)
|
||||
e.picker = app.MustComponent[getblock.Picker](a)
|
||||
e.picker = app.MustComponent[getblock.ObjectGetter](a)
|
||||
e.resolver = a.MustComponent(idresolver.CName).(idresolver.Resolver)
|
||||
e.sbtProvider = app.MustComponent[typeprovider.SmartBlockTypeProvider](a)
|
||||
e.systemObjectService = app.MustComponent[system_object.Service](a)
|
||||
e.spaceService = app.MustComponent[space.Service](a)
|
||||
e.spaceService = app.MustComponent[spacecore.SpaceCoreService](a)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -375,7 +378,7 @@ func (e *export) saveFiles(ctx context.Context, b sb.SmartBlock, queue process.Q
|
|||
}
|
||||
|
||||
func (e *export) saveFile(ctx context.Context, wr writer, hash string) (err error) {
|
||||
spaceID, err := e.spaceService.ResolveSpaceID(hash)
|
||||
spaceID, err := e.resolver.ResolveSpaceID(hash)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ func (s *Service) DownloadFile(ctx context.Context, req *pb.RpcFileDownloadReque
|
|||
}
|
||||
|
||||
func (s *Service) getFileOrLargestImage(ctx context.Context, hash string) (files.File, error) {
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(hash)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(hash)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
)
|
||||
|
||||
type Picker interface {
|
||||
PickBlock(ctx context.Context, id string) (sb smartblock.SmartBlock, err error)
|
||||
type ObjectGetter interface {
|
||||
GetObject(ctx context.Context, id string) (sb smartblock.SmartBlock, err error)
|
||||
}
|
||||
|
||||
func Do[t any](p Picker, objectID string, apply func(sb t) error) error {
|
||||
func Do[t any](p ObjectGetter, objectID string, apply func(sb t) error) error {
|
||||
ctx := context.Background()
|
||||
sb, err := p.PickBlock(ctx, objectID)
|
||||
sb, err := p.GetObject(ctx, objectID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
94
core/block/getblock/mock_getblock/mock_ObjectGetter.go
Normal file
94
core/block/getblock/mock_getblock/mock_ObjectGetter.go
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Code generated by mockery v2.26.1. DO NOT EDIT.
|
||||
|
||||
package mock_getblock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
smartblock "github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
)
|
||||
|
||||
// MockObjectGetter is an autogenerated mock type for the ObjectGetter type
|
||||
type MockObjectGetter struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockObjectGetter_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockObjectGetter) EXPECT() *MockObjectGetter_Expecter {
|
||||
return &MockObjectGetter_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GetObject provides a mock function with given fields: ctx, id
|
||||
func (_m *MockObjectGetter) GetObject(ctx context.Context, id string) (smartblock.SmartBlock, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
||||
var r0 smartblock.SmartBlock
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (smartblock.SmartBlock, error)); ok {
|
||||
return rf(ctx, id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) smartblock.SmartBlock); ok {
|
||||
r0 = rf(ctx, id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(smartblock.SmartBlock)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, id)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockObjectGetter_GetObject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetObject'
|
||||
type MockObjectGetter_GetObject_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetObject is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id string
|
||||
func (_e *MockObjectGetter_Expecter) GetObject(ctx interface{}, id interface{}) *MockObjectGetter_GetObject_Call {
|
||||
return &MockObjectGetter_GetObject_Call{Call: _e.mock.On("GetObject", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *MockObjectGetter_GetObject_Call) Run(run func(ctx context.Context, id string)) *MockObjectGetter_GetObject_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockObjectGetter_GetObject_Call) Return(sb smartblock.SmartBlock, err error) *MockObjectGetter_GetObject_Call {
|
||||
_c.Call.Return(sb, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockObjectGetter_GetObject_Call) RunAndReturn(run func(context.Context, string) (smartblock.SmartBlock, error)) *MockObjectGetter_GetObject_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewMockObjectGetter interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewMockObjectGetter creates a new instance of MockObjectGetter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewMockObjectGetter(t mockConstructorTestingTNewMockObjectGetter) *MockObjectGetter {
|
||||
mock := &MockObjectGetter{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
// Code generated by mockery v2.26.1. DO NOT EDIT.
|
||||
|
||||
package mock_getblock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
smartblock "github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
)
|
||||
|
||||
// MockPicker is an autogenerated mock type for the Picker type
|
||||
type MockPicker struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockPicker_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockPicker) EXPECT() *MockPicker_Expecter {
|
||||
return &MockPicker_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// PickBlock provides a mock function with given fields: ctx, id
|
||||
func (_m *MockPicker) PickBlock(ctx context.Context, id string) (smartblock.SmartBlock, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
||||
var r0 smartblock.SmartBlock
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (smartblock.SmartBlock, error)); ok {
|
||||
return rf(ctx, id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) smartblock.SmartBlock); ok {
|
||||
r0 = rf(ctx, id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(smartblock.SmartBlock)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, id)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockPicker_PickBlock_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PickBlock'
|
||||
type MockPicker_PickBlock_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// PickBlock is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id string
|
||||
func (_e *MockPicker_Expecter) PickBlock(ctx interface{}, id interface{}) *MockPicker_PickBlock_Call {
|
||||
return &MockPicker_PickBlock_Call{Call: _e.mock.On("PickBlock", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *MockPicker_PickBlock_Call) Run(run func(ctx context.Context, id string)) *MockPicker_PickBlock_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockPicker_PickBlock_Call) Return(sb smartblock.SmartBlock, err error) *MockPicker_PickBlock_Call {
|
||||
_c.Call.Return(sb, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockPicker_PickBlock_Call) RunAndReturn(run func(context.Context, string) (smartblock.SmartBlock, error)) *MockPicker_PickBlock_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewMockPicker interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewMockPicker creates a new instance of MockPicker. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewMockPicker(t mockConstructorTestingTNewMockPicker) *MockPicker {
|
||||
mock := &MockPicker{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
|
@ -16,7 +16,6 @@ import (
|
|||
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/collection"
|
||||
"github.com/anyproto/anytype-heart/core/block/getblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/converter"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/csv"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/html"
|
||||
|
@ -27,6 +26,8 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/import/txt"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/web"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/workerpool"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/block/process"
|
||||
"github.com/anyproto/anytype-heart/core/filestorage/filesync"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
|
@ -37,7 +38,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
@ -81,14 +82,14 @@ func (i *Import) Init(a *app.App) (err error) {
|
|||
for _, c := range converters {
|
||||
i.converters[c.Name()] = c
|
||||
}
|
||||
|
||||
picker := app.MustComponent[getblock.Picker](a)
|
||||
factory := syncer.New(syncer.NewFileSyncer(i.s), syncer.NewBookmarkSyncer(i.s), syncer.NewIconSyncer(i.s, picker))
|
||||
objectCache := app.MustComponent[objectcache.Cache](a)
|
||||
resolver := a.MustComponent(idresolver.CName).(idresolver.Resolver)
|
||||
factory := syncer.New(syncer.NewFileSyncer(i.s), syncer.NewBookmarkSyncer(i.s), syncer.NewIconSyncer(i.s, resolver))
|
||||
store := app.MustComponent[objectstore.ObjectStore](a)
|
||||
i.objectIDGetter = NewObjectIDGetter(store, coreService, i.s)
|
||||
i.objectIDGetter = NewObjectIDGetter(store, coreService, objectCache)
|
||||
fileStore := app.MustComponent[filestore.FileStore](a)
|
||||
relationSyncer := syncer.NewFileRelationSyncer(i.s, fileStore)
|
||||
i.oc = NewCreator(i.s, coreService, factory, store, relationSyncer, fileStore, picker)
|
||||
i.oc = NewCreator(i.s, objectCache, coreService, factory, store, relationSyncer, fileStore)
|
||||
i.sbtProvider = app.MustComponent[typeprovider.SmartBlockTypeProvider](a)
|
||||
i.fileSync = a.MustComponent(filesync.CName).(filesync.FileSync)
|
||||
return nil
|
||||
|
|
|
@ -14,10 +14,9 @@ import (
|
|||
time "time"
|
||||
|
||||
treestorage "github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
converter "github.com/anyproto/anytype-heart/core/block/import/converter"
|
||||
types "github.com/gogo/protobuf/types"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
|
||||
converter "github.com/anyproto/anytype-heart/core/block/import/converter"
|
||||
)
|
||||
|
||||
// MockCreator is a mock of Creator interface.
|
||||
|
|
|
@ -3,6 +3,7 @@ package importer
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
|
@ -13,13 +14,14 @@ import (
|
|||
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/basic"
|
||||
sb "github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/template"
|
||||
"github.com/anyproto/anytype-heart/core/block/getblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/history"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/converter"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/syncer"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
|
@ -37,7 +39,7 @@ const relationsLimit = 10
|
|||
|
||||
type ObjectCreator struct {
|
||||
service *block.Service
|
||||
picker getblock.Picker
|
||||
objectCache objectcache.Cache
|
||||
core core.Service
|
||||
objectStore objectstore.ObjectStore
|
||||
relationSyncer syncer.RelationSyncer
|
||||
|
@ -47,12 +49,12 @@ type ObjectCreator struct {
|
|||
}
|
||||
|
||||
func NewCreator(service *block.Service,
|
||||
cache objectcache.Cache,
|
||||
core core.Service,
|
||||
syncFactory *syncer.Factory,
|
||||
objectStore objectstore.ObjectStore,
|
||||
relationSyncer syncer.RelationSyncer,
|
||||
fileStore filestore.FileStore,
|
||||
picker getblock.Picker,
|
||||
) Creator {
|
||||
return &ObjectCreator{
|
||||
service: service,
|
||||
|
@ -61,7 +63,7 @@ func NewCreator(service *block.Service,
|
|||
objectStore: objectStore,
|
||||
relationSyncer: relationSyncer,
|
||||
fileStore: fileStore,
|
||||
picker: picker,
|
||||
objectCache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,23 +198,31 @@ func (oc *ObjectCreator) createNewObject(
|
|||
st *state.State,
|
||||
newID string,
|
||||
oldIDtoNew map[string]string) (*types.Struct, error) {
|
||||
sb, err := oc.service.CreateTreeObjectWithPayload(ctx, spaceID, payload, func(id string) *sb.InitContext {
|
||||
return &sb.InitContext{
|
||||
var respDetails *types.Struct
|
||||
sb, err := oc.objectCache.CreateTreeObjectWithPayload(ctx, spaceID, payload, func(id string) *smartblock.InitContext {
|
||||
return &smartblock.InitContext{
|
||||
Ctx: ctx,
|
||||
IsNewObject: true,
|
||||
State: st,
|
||||
SpaceID: spaceID,
|
||||
}
|
||||
})
|
||||
if errors.Is(err, treestorage.ErrTreeExists) {
|
||||
sb, err = oc.picker.PickBlock(ctx, newID)
|
||||
}
|
||||
if err != nil {
|
||||
if err == nil {
|
||||
respDetails = sb.Details()
|
||||
} else if errors.Is(err, treestorage.ErrTreeExists) {
|
||||
err = getblock.Do(oc.service, newID, func(sb smartblock.SmartBlock) error {
|
||||
respDetails = sb.Details()
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get existing object %s: %w", newID, err)
|
||||
}
|
||||
} else {
|
||||
log.With("objectID", newID).Errorf("failed to create %s: %s", newID, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
log.With("objectID", newID).Infof("import object created %s", pbtypes.GetString(st.CombinedDetails(), bundle.RelationKeyName.String()))
|
||||
respDetails := sb.Details()
|
||||
|
||||
// update collection after we create it
|
||||
if st.Store() != nil {
|
||||
oc.updateLinksInCollections(st, oldIDtoNew, true)
|
||||
|
@ -337,7 +347,7 @@ func (oc *ObjectCreator) handleCoverRelation(spaceID string, st *state.State) []
|
|||
|
||||
func (oc *ObjectCreator) resetState(newID string, st *state.State) *types.Struct {
|
||||
var respDetails *types.Struct
|
||||
err := getblock.Do(oc.picker, newID, func(b sb.SmartBlock) error {
|
||||
err := block.Do(oc.service, newID, func(b smartblock.SmartBlock) error {
|
||||
err := history.ResetToVersion(b, st)
|
||||
if err != nil {
|
||||
log.With(zap.String("object id", newID)).Errorf("failed to set state %s: %s", newID, err.Error())
|
||||
|
@ -383,7 +393,7 @@ func (oc *ObjectCreator) setArchived(snapshot *model.SmartBlockSnapshotBase, new
|
|||
func (oc *ObjectCreator) syncFilesAndLinks(newID string) error {
|
||||
tasks := make([]func() error, 0)
|
||||
// todo: rewrite it in order not to create state with URLs inside links
|
||||
err := getblock.Do(oc.picker, newID, func(b sb.SmartBlock) error {
|
||||
err := block.Do(oc.service, newID, func(b smartblock.SmartBlock) error {
|
||||
st := b.NewState()
|
||||
return st.Iterate(func(bl simple.Block) (isContinue bool) {
|
||||
s := oc.syncFactory.GetSyncer(bl)
|
||||
|
@ -412,7 +422,7 @@ func (oc *ObjectCreator) syncFilesAndLinks(newID string) error {
|
|||
}
|
||||
|
||||
func (oc *ObjectCreator) updateLinksInCollections(st *state.State, oldIDtoNew map[string]string, isNewCollection bool) {
|
||||
err := block.Do(oc.service, st.RootId(), func(b sb.SmartBlock) error {
|
||||
err := block.Do(oc.service, st.RootId(), func(b smartblock.SmartBlock) error {
|
||||
originalState := b.NewState()
|
||||
var existedObjects []string
|
||||
if !isNewCollection {
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/import/converter"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/payloadcreator"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
|
@ -41,10 +41,10 @@ type ObjectIDGetter struct {
|
|||
objectStore objectstore.ObjectStore
|
||||
core core.Service
|
||||
createPayload map[string]treestorage.TreeStorageCreatePayload
|
||||
service *block.Service
|
||||
service payloadcreator.PayloadCreator
|
||||
}
|
||||
|
||||
func NewObjectIDGetter(objectStore objectstore.ObjectStore, core core.Service, service *block.Service) IDGetter {
|
||||
func NewObjectIDGetter(objectStore objectstore.ObjectStore, core core.Service, service payloadcreator.PayloadCreator) IDGetter {
|
||||
return &ObjectIDGetter{
|
||||
objectStore: objectStore,
|
||||
service: service,
|
||||
|
@ -90,12 +90,17 @@ func (ou *ObjectIDGetter) Get(
|
|||
if err != nil {
|
||||
return "", treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
payload, err = ou.service.DeriveTreeCreatePayload(context.Background(), spaceID, uk)
|
||||
payload, err = ou.service.DeriveTreePayload(context.Background(), spaceID, payloadcreator.PayloadDerivationParams{
|
||||
Key: uk,
|
||||
})
|
||||
if err != nil {
|
||||
return "", treestorage.TreeStorageCreatePayload{}, fmt.Errorf("derive tree create payload: %w", err)
|
||||
}
|
||||
} else {
|
||||
payload, err = ou.service.CreateTreePayload(context.Background(), spaceID, sbType, createdTime)
|
||||
payload, err = ou.service.CreateTreePayload(context.Background(), spaceID, payloadcreator.PayloadCreationParams{
|
||||
Time: createdTime,
|
||||
SmartblockType: sbType,
|
||||
})
|
||||
if err != nil {
|
||||
return "", treestorage.TreeStorageCreatePayload{}, fmt.Errorf("create tree payload: %w", err)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/addr"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/constant"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/basic"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/getblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/block/simple"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
|
@ -20,12 +20,12 @@ import (
|
|||
var log = logging.Logger("import")
|
||||
|
||||
type IconSyncer struct {
|
||||
service *block.Service
|
||||
picker getblock.Picker
|
||||
service *block.Service
|
||||
resolver idresolver.Resolver
|
||||
}
|
||||
|
||||
func NewIconSyncer(service *block.Service, picker getblock.Picker) *IconSyncer {
|
||||
return &IconSyncer{service: service, picker: picker}
|
||||
func NewIconSyncer(service *block.Service, resolver idresolver.Resolver) *IconSyncer {
|
||||
return &IconSyncer{service: service, resolver: resolver}
|
||||
}
|
||||
|
||||
func (is *IconSyncer) Sync(id string, b simple.Block) error {
|
||||
|
@ -38,7 +38,7 @@ func (is *IconSyncer) Sync(id string, b simple.Block) error {
|
|||
if strings.HasPrefix(icon, "http://") || strings.HasPrefix(icon, "https://") {
|
||||
req = pb.RpcFileUploadRequest{Url: icon}
|
||||
}
|
||||
spaceID, err := is.service.ResolveSpaceID(id)
|
||||
spaceID, err := is.resolver.ResolveSpaceID(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ func (is *IconSyncer) Sync(id string, b simple.Block) error {
|
|||
log.Errorf("failed uploading icon image file: %s", oserror.TransformError(err))
|
||||
}
|
||||
|
||||
err = getblock.Do(is.picker, id, func(sb smartblock.SmartBlock) error {
|
||||
err = block.Do(is.service, id, func(sb smartblock.SmartBlock) error {
|
||||
updater := sb.(basic.Updatable)
|
||||
upErr := updater.Update(nil, func(simpleBlock simple.Block) error {
|
||||
simpleBlock.Model().GetText().IconImage = hash
|
||||
|
|
44
core/block/object/idresolver/resolver.go
Normal file
44
core/block/object/idresolver/resolver.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package idresolver
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/anyproto/any-sync/commonspace/spacestorage"
|
||||
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/addr"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/storage"
|
||||
)
|
||||
|
||||
const CName = "block.object.resolver"
|
||||
|
||||
type Resolver interface {
|
||||
app.Component
|
||||
ResolveSpaceID(objectID string) (string, error)
|
||||
}
|
||||
|
||||
func New() Resolver {
|
||||
return &resolver{}
|
||||
}
|
||||
|
||||
type resolver struct {
|
||||
storage storage.ClientStorage
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (r *resolver) Init(a *app.App) (err error) {
|
||||
r.storage = a.MustComponent(spacestorage.CName).(storage.ClientStorage)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *resolver) Name() (name string) {
|
||||
return CName
|
||||
}
|
||||
|
||||
func (r *resolver) ResolveSpaceID(objectID string) (string, error) {
|
||||
// TODO: [MR] remove it, because maybe we don't need it
|
||||
if addr.IsBundledId(objectID) {
|
||||
return addr.AnytypeMarketplaceWorkspace, nil
|
||||
}
|
||||
return r.storage.GetSpaceID(objectID)
|
||||
}
|
|
@ -5,16 +5,18 @@ import (
|
|||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/accountservice"
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/anyproto/any-sync/app/ocache"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/payloadcreator"
|
||||
"github.com/anyproto/anytype-heart/core/block/source"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
)
|
||||
|
||||
var log = logging.Logger("anytype-mw-object-cache")
|
||||
|
@ -38,10 +40,21 @@ type cacheOpts struct {
|
|||
putObject smartblock.SmartBlock
|
||||
}
|
||||
|
||||
const CName = "client.object.objectcache"
|
||||
|
||||
type InitFunc = func(id string) *smartblock.InitContext
|
||||
|
||||
type objectFactory interface {
|
||||
InitObject(id string, initCtx *smartblock.InitContext) (sb smartblock.SmartBlock, err error)
|
||||
}
|
||||
|
||||
type Cache interface {
|
||||
app.ComponentRunnable
|
||||
payloadcreator.PayloadCreator
|
||||
|
||||
PickBlock(ctx context.Context, objectID string) (sb smartblock.SmartBlock, err error)
|
||||
CreateTreeObject(ctx context.Context, spaceID string, params TreeCreationParams) (sb smartblock.SmartBlock, err error)
|
||||
CreateTreeObjectWithPayload(ctx context.Context, spaceID string, payload treestorage.TreeStorageCreatePayload, initFunc InitFunc) (sb smartblock.SmartBlock, err error)
|
||||
DeriveTreeObject(ctx context.Context, spaceID string, params TreeDerivationParams) (sb smartblock.SmartBlock, err error)
|
||||
GetObject(ctx context.Context, id domain.FullID) (sb smartblock.SmartBlock, err error)
|
||||
GetObjectWithTimeout(ctx context.Context, id domain.FullID) (sb smartblock.SmartBlock, err error)
|
||||
DoLockedIfNotExists(objectID string, proc func() error) error
|
||||
|
@ -49,12 +62,18 @@ type Cache interface {
|
|||
CloseBlocks()
|
||||
}
|
||||
|
||||
type personalIDProvider interface {
|
||||
PersonalSpaceID() string
|
||||
}
|
||||
|
||||
type objectCache struct {
|
||||
objectFactory *editor.ObjectFactory
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
spaceService space.Service
|
||||
cache ocache.OCache
|
||||
closing chan struct{}
|
||||
objectFactory objectFactory
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
spaceService spacecore.SpaceCoreService
|
||||
provider personalIDProvider
|
||||
accountService accountservice.Service
|
||||
cache ocache.OCache
|
||||
closing chan struct{}
|
||||
}
|
||||
|
||||
func New() Cache {
|
||||
|
@ -64,9 +83,11 @@ func New() Cache {
|
|||
}
|
||||
|
||||
func (c *objectCache) Init(a *app.App) error {
|
||||
c.objectFactory = app.MustComponent[*editor.ObjectFactory](a)
|
||||
c.accountService = app.MustComponent[accountservice.Service](a)
|
||||
c.objectFactory = app.MustComponent[objectFactory](a)
|
||||
c.provider = app.MustComponent[personalIDProvider](a)
|
||||
c.sbtProvider = app.MustComponent[typeprovider.SmartBlockTypeProvider](a)
|
||||
c.spaceService = app.MustComponent[space.Service](a)
|
||||
c.spaceService = app.MustComponent[spacecore.SpaceCoreService](a)
|
||||
c.cache = ocache.New(
|
||||
c.cacheLoad,
|
||||
// ocache.WithLogger(log.Desugar()),
|
||||
|
@ -78,7 +99,7 @@ func (c *objectCache) Init(a *app.App) error {
|
|||
}
|
||||
|
||||
func (c *objectCache) Name() string {
|
||||
return "object-cache"
|
||||
return CName
|
||||
}
|
||||
|
||||
func (c *objectCache) Run(_ context.Context) error {
|
||||
|
@ -110,7 +131,6 @@ func ContextWithBuildOptions(ctx context.Context, buildOpts source.BuildOptions)
|
|||
func (c *objectCache) cacheLoad(ctx context.Context, id string) (value ocache.Object, err error) {
|
||||
// TODO Pass options as parameter?
|
||||
opts := ctx.Value(optsKey).(cacheOpts)
|
||||
|
||||
buildObject := func(id string) (sb smartblock.SmartBlock, err error) {
|
||||
return c.objectFactory.InitObject(id, &smartblock.InitContext{Ctx: ctx, BuildOpts: opts.buildOption, SpaceID: opts.spaceId})
|
||||
}
|
||||
|
@ -189,19 +209,6 @@ func (c *objectCache) GetObjectWithTimeout(ctx context.Context, id domain.FullID
|
|||
return c.GetObject(ctx, id)
|
||||
}
|
||||
|
||||
// PickBlock returns opened smartBlock or opens smartBlock in silent mode
|
||||
func (c *objectCache) PickBlock(ctx context.Context, objectID string) (sb smartblock.SmartBlock, err error) {
|
||||
spaceID, err := c.spaceService.ResolveSpaceID(objectID)
|
||||
if err != nil {
|
||||
// Object not loaded yet
|
||||
return nil, source.ErrObjectNotFound
|
||||
}
|
||||
return c.GetObjectWithTimeout(ctx, domain.FullID{
|
||||
SpaceID: spaceID,
|
||||
ObjectID: objectID,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *objectCache) DoLockedIfNotExists(objectID string, proc func() error) error {
|
||||
return c.cache.DoLockedIfNotExists(objectID, proc)
|
||||
}
|
||||
|
|
770
core/block/object/objectcache/mock_objectcache/mock_Cache.go
Normal file
770
core/block/object/objectcache/mock_objectcache/mock_Cache.go
Normal file
|
@ -0,0 +1,770 @@
|
|||
// Code generated by mockery v2.26.1. DO NOT EDIT.
|
||||
|
||||
package mock_objectcache
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
app "github.com/anyproto/any-sync/app"
|
||||
treestorage "github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
smartblock "github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
objectcache "github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
payloadcreator "github.com/anyproto/anytype-heart/core/block/object/payloadcreator"
|
||||
domain "github.com/anyproto/anytype-heart/core/domain"
|
||||
)
|
||||
|
||||
// MockCache is an autogenerated mock type for the Cache type
|
||||
type MockCache struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockCache_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockCache) EXPECT() *MockCache_Expecter {
|
||||
return &MockCache_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Close provides a mock function with given fields: ctx
|
||||
func (_m *MockCache) Close(ctx context.Context) error {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockCache_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
|
||||
type MockCache_Close_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Close is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *MockCache_Expecter) Close(ctx interface{}) *MockCache_Close_Call {
|
||||
return &MockCache_Close_Call{Call: _e.mock.On("Close", ctx)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_Close_Call) Run(run func(ctx context.Context)) *MockCache_Close_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Close_Call) Return(err error) *MockCache_Close_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Close_Call) RunAndReturn(run func(context.Context) error) *MockCache_Close_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CloseBlocks provides a mock function with given fields:
|
||||
func (_m *MockCache) CloseBlocks() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// MockCache_CloseBlocks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CloseBlocks'
|
||||
type MockCache_CloseBlocks_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CloseBlocks is a helper method to define mock.On call
|
||||
func (_e *MockCache_Expecter) CloseBlocks() *MockCache_CloseBlocks_Call {
|
||||
return &MockCache_CloseBlocks_Call{Call: _e.mock.On("CloseBlocks")}
|
||||
}
|
||||
|
||||
func (_c *MockCache_CloseBlocks_Call) Run(run func()) *MockCache_CloseBlocks_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_CloseBlocks_Call) Return() *MockCache_CloseBlocks_Call {
|
||||
_c.Call.Return()
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_CloseBlocks_Call) RunAndReturn(run func()) *MockCache_CloseBlocks_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateTreeObject provides a mock function with given fields: ctx, spaceID, params
|
||||
func (_m *MockCache) CreateTreeObject(ctx context.Context, spaceID string, params objectcache.TreeCreationParams) (smartblock.SmartBlock, error) {
|
||||
ret := _m.Called(ctx, spaceID, params)
|
||||
|
||||
var r0 smartblock.SmartBlock
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, objectcache.TreeCreationParams) (smartblock.SmartBlock, error)); ok {
|
||||
return rf(ctx, spaceID, params)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, objectcache.TreeCreationParams) smartblock.SmartBlock); ok {
|
||||
r0 = rf(ctx, spaceID, params)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(smartblock.SmartBlock)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, objectcache.TreeCreationParams) error); ok {
|
||||
r1 = rf(ctx, spaceID, params)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockCache_CreateTreeObject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateTreeObject'
|
||||
type MockCache_CreateTreeObject_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateTreeObject is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - spaceID string
|
||||
// - params objectcache.TreeCreationParams
|
||||
func (_e *MockCache_Expecter) CreateTreeObject(ctx interface{}, spaceID interface{}, params interface{}) *MockCache_CreateTreeObject_Call {
|
||||
return &MockCache_CreateTreeObject_Call{Call: _e.mock.On("CreateTreeObject", ctx, spaceID, params)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_CreateTreeObject_Call) Run(run func(ctx context.Context, spaceID string, params objectcache.TreeCreationParams)) *MockCache_CreateTreeObject_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(objectcache.TreeCreationParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_CreateTreeObject_Call) Return(sb smartblock.SmartBlock, err error) *MockCache_CreateTreeObject_Call {
|
||||
_c.Call.Return(sb, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_CreateTreeObject_Call) RunAndReturn(run func(context.Context, string, objectcache.TreeCreationParams) (smartblock.SmartBlock, error)) *MockCache_CreateTreeObject_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateTreeObjectWithPayload provides a mock function with given fields: ctx, spaceID, payload, initFunc
|
||||
func (_m *MockCache) CreateTreeObjectWithPayload(ctx context.Context, spaceID string, payload treestorage.TreeStorageCreatePayload, initFunc func(string) *smartblock.InitContext) (smartblock.SmartBlock, error) {
|
||||
ret := _m.Called(ctx, spaceID, payload, initFunc)
|
||||
|
||||
var r0 smartblock.SmartBlock
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, treestorage.TreeStorageCreatePayload, func(string) *smartblock.InitContext) (smartblock.SmartBlock, error)); ok {
|
||||
return rf(ctx, spaceID, payload, initFunc)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, treestorage.TreeStorageCreatePayload, func(string) *smartblock.InitContext) smartblock.SmartBlock); ok {
|
||||
r0 = rf(ctx, spaceID, payload, initFunc)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(smartblock.SmartBlock)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, treestorage.TreeStorageCreatePayload, func(string) *smartblock.InitContext) error); ok {
|
||||
r1 = rf(ctx, spaceID, payload, initFunc)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockCache_CreateTreeObjectWithPayload_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateTreeObjectWithPayload'
|
||||
type MockCache_CreateTreeObjectWithPayload_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateTreeObjectWithPayload is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - spaceID string
|
||||
// - payload treestorage.TreeStorageCreatePayload
|
||||
// - initFunc func(string) *smartblock.InitContext
|
||||
func (_e *MockCache_Expecter) CreateTreeObjectWithPayload(ctx interface{}, spaceID interface{}, payload interface{}, initFunc interface{}) *MockCache_CreateTreeObjectWithPayload_Call {
|
||||
return &MockCache_CreateTreeObjectWithPayload_Call{Call: _e.mock.On("CreateTreeObjectWithPayload", ctx, spaceID, payload, initFunc)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_CreateTreeObjectWithPayload_Call) Run(run func(ctx context.Context, spaceID string, payload treestorage.TreeStorageCreatePayload, initFunc func(string) *smartblock.InitContext)) *MockCache_CreateTreeObjectWithPayload_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(treestorage.TreeStorageCreatePayload), args[3].(func(string) *smartblock.InitContext))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_CreateTreeObjectWithPayload_Call) Return(sb smartblock.SmartBlock, err error) *MockCache_CreateTreeObjectWithPayload_Call {
|
||||
_c.Call.Return(sb, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_CreateTreeObjectWithPayload_Call) RunAndReturn(run func(context.Context, string, treestorage.TreeStorageCreatePayload, func(string) *smartblock.InitContext) (smartblock.SmartBlock, error)) *MockCache_CreateTreeObjectWithPayload_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// CreateTreePayload provides a mock function with given fields: ctx, spaceID, params
|
||||
func (_m *MockCache) CreateTreePayload(ctx context.Context, spaceID string, params payloadcreator.PayloadCreationParams) (treestorage.TreeStorageCreatePayload, error) {
|
||||
ret := _m.Called(ctx, spaceID, params)
|
||||
|
||||
var r0 treestorage.TreeStorageCreatePayload
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, payloadcreator.PayloadCreationParams) (treestorage.TreeStorageCreatePayload, error)); ok {
|
||||
return rf(ctx, spaceID, params)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, payloadcreator.PayloadCreationParams) treestorage.TreeStorageCreatePayload); ok {
|
||||
r0 = rf(ctx, spaceID, params)
|
||||
} else {
|
||||
r0 = ret.Get(0).(treestorage.TreeStorageCreatePayload)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, payloadcreator.PayloadCreationParams) error); ok {
|
||||
r1 = rf(ctx, spaceID, params)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockCache_CreateTreePayload_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateTreePayload'
|
||||
type MockCache_CreateTreePayload_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateTreePayload is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - spaceID string
|
||||
// - params payloadcreator.PayloadCreationParams
|
||||
func (_e *MockCache_Expecter) CreateTreePayload(ctx interface{}, spaceID interface{}, params interface{}) *MockCache_CreateTreePayload_Call {
|
||||
return &MockCache_CreateTreePayload_Call{Call: _e.mock.On("CreateTreePayload", ctx, spaceID, params)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_CreateTreePayload_Call) Run(run func(ctx context.Context, spaceID string, params payloadcreator.PayloadCreationParams)) *MockCache_CreateTreePayload_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(payloadcreator.PayloadCreationParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_CreateTreePayload_Call) Return(_a0 treestorage.TreeStorageCreatePayload, _a1 error) *MockCache_CreateTreePayload_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_CreateTreePayload_Call) RunAndReturn(run func(context.Context, string, payloadcreator.PayloadCreationParams) (treestorage.TreeStorageCreatePayload, error)) *MockCache_CreateTreePayload_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DeriveObjectID provides a mock function with given fields: ctx, spaceID, uniqueKey
|
||||
func (_m *MockCache) DeriveObjectID(ctx context.Context, spaceID string, uniqueKey domain.UniqueKey) (string, error) {
|
||||
ret := _m.Called(ctx, spaceID, uniqueKey)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, domain.UniqueKey) (string, error)); ok {
|
||||
return rf(ctx, spaceID, uniqueKey)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, domain.UniqueKey) string); ok {
|
||||
r0 = rf(ctx, spaceID, uniqueKey)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, domain.UniqueKey) error); ok {
|
||||
r1 = rf(ctx, spaceID, uniqueKey)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockCache_DeriveObjectID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeriveObjectID'
|
||||
type MockCache_DeriveObjectID_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DeriveObjectID is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - spaceID string
|
||||
// - uniqueKey domain.UniqueKey
|
||||
func (_e *MockCache_Expecter) DeriveObjectID(ctx interface{}, spaceID interface{}, uniqueKey interface{}) *MockCache_DeriveObjectID_Call {
|
||||
return &MockCache_DeriveObjectID_Call{Call: _e.mock.On("DeriveObjectID", ctx, spaceID, uniqueKey)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_DeriveObjectID_Call) Run(run func(ctx context.Context, spaceID string, uniqueKey domain.UniqueKey)) *MockCache_DeriveObjectID_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(domain.UniqueKey))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_DeriveObjectID_Call) Return(id string, err error) *MockCache_DeriveObjectID_Call {
|
||||
_c.Call.Return(id, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_DeriveObjectID_Call) RunAndReturn(run func(context.Context, string, domain.UniqueKey) (string, error)) *MockCache_DeriveObjectID_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DeriveTreeObject provides a mock function with given fields: ctx, spaceID, params
|
||||
func (_m *MockCache) DeriveTreeObject(ctx context.Context, spaceID string, params objectcache.TreeDerivationParams) (smartblock.SmartBlock, error) {
|
||||
ret := _m.Called(ctx, spaceID, params)
|
||||
|
||||
var r0 smartblock.SmartBlock
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, objectcache.TreeDerivationParams) (smartblock.SmartBlock, error)); ok {
|
||||
return rf(ctx, spaceID, params)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, objectcache.TreeDerivationParams) smartblock.SmartBlock); ok {
|
||||
r0 = rf(ctx, spaceID, params)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(smartblock.SmartBlock)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, objectcache.TreeDerivationParams) error); ok {
|
||||
r1 = rf(ctx, spaceID, params)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockCache_DeriveTreeObject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeriveTreeObject'
|
||||
type MockCache_DeriveTreeObject_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DeriveTreeObject is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - spaceID string
|
||||
// - params objectcache.TreeDerivationParams
|
||||
func (_e *MockCache_Expecter) DeriveTreeObject(ctx interface{}, spaceID interface{}, params interface{}) *MockCache_DeriveTreeObject_Call {
|
||||
return &MockCache_DeriveTreeObject_Call{Call: _e.mock.On("DeriveTreeObject", ctx, spaceID, params)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_DeriveTreeObject_Call) Run(run func(ctx context.Context, spaceID string, params objectcache.TreeDerivationParams)) *MockCache_DeriveTreeObject_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(objectcache.TreeDerivationParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_DeriveTreeObject_Call) Return(sb smartblock.SmartBlock, err error) *MockCache_DeriveTreeObject_Call {
|
||||
_c.Call.Return(sb, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_DeriveTreeObject_Call) RunAndReturn(run func(context.Context, string, objectcache.TreeDerivationParams) (smartblock.SmartBlock, error)) *MockCache_DeriveTreeObject_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DeriveTreePayload provides a mock function with given fields: ctx, spaceID, params
|
||||
func (_m *MockCache) DeriveTreePayload(ctx context.Context, spaceID string, params payloadcreator.PayloadDerivationParams) (treestorage.TreeStorageCreatePayload, error) {
|
||||
ret := _m.Called(ctx, spaceID, params)
|
||||
|
||||
var r0 treestorage.TreeStorageCreatePayload
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, payloadcreator.PayloadDerivationParams) (treestorage.TreeStorageCreatePayload, error)); ok {
|
||||
return rf(ctx, spaceID, params)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, payloadcreator.PayloadDerivationParams) treestorage.TreeStorageCreatePayload); ok {
|
||||
r0 = rf(ctx, spaceID, params)
|
||||
} else {
|
||||
r0 = ret.Get(0).(treestorage.TreeStorageCreatePayload)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, payloadcreator.PayloadDerivationParams) error); ok {
|
||||
r1 = rf(ctx, spaceID, params)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockCache_DeriveTreePayload_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeriveTreePayload'
|
||||
type MockCache_DeriveTreePayload_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DeriveTreePayload is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - spaceID string
|
||||
// - params payloadcreator.PayloadDerivationParams
|
||||
func (_e *MockCache_Expecter) DeriveTreePayload(ctx interface{}, spaceID interface{}, params interface{}) *MockCache_DeriveTreePayload_Call {
|
||||
return &MockCache_DeriveTreePayload_Call{Call: _e.mock.On("DeriveTreePayload", ctx, spaceID, params)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_DeriveTreePayload_Call) Run(run func(ctx context.Context, spaceID string, params payloadcreator.PayloadDerivationParams)) *MockCache_DeriveTreePayload_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string), args[2].(payloadcreator.PayloadDerivationParams))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_DeriveTreePayload_Call) Return(storagePayload treestorage.TreeStorageCreatePayload, err error) *MockCache_DeriveTreePayload_Call {
|
||||
_c.Call.Return(storagePayload, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_DeriveTreePayload_Call) RunAndReturn(run func(context.Context, string, payloadcreator.PayloadDerivationParams) (treestorage.TreeStorageCreatePayload, error)) *MockCache_DeriveTreePayload_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// DoLockedIfNotExists provides a mock function with given fields: objectID, proc
|
||||
func (_m *MockCache) DoLockedIfNotExists(objectID string, proc func() error) error {
|
||||
ret := _m.Called(objectID, proc)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, func() error) error); ok {
|
||||
r0 = rf(objectID, proc)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockCache_DoLockedIfNotExists_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DoLockedIfNotExists'
|
||||
type MockCache_DoLockedIfNotExists_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// DoLockedIfNotExists is a helper method to define mock.On call
|
||||
// - objectID string
|
||||
// - proc func() error
|
||||
func (_e *MockCache_Expecter) DoLockedIfNotExists(objectID interface{}, proc interface{}) *MockCache_DoLockedIfNotExists_Call {
|
||||
return &MockCache_DoLockedIfNotExists_Call{Call: _e.mock.On("DoLockedIfNotExists", objectID, proc)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_DoLockedIfNotExists_Call) Run(run func(objectID string, proc func() error)) *MockCache_DoLockedIfNotExists_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string), args[1].(func() error))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_DoLockedIfNotExists_Call) Return(_a0 error) *MockCache_DoLockedIfNotExists_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_DoLockedIfNotExists_Call) RunAndReturn(run func(string, func() error) error) *MockCache_DoLockedIfNotExists_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetObject provides a mock function with given fields: ctx, id
|
||||
func (_m *MockCache) GetObject(ctx context.Context, id domain.FullID) (smartblock.SmartBlock, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
||||
var r0 smartblock.SmartBlock
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, domain.FullID) (smartblock.SmartBlock, error)); ok {
|
||||
return rf(ctx, id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, domain.FullID) smartblock.SmartBlock); ok {
|
||||
r0 = rf(ctx, id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(smartblock.SmartBlock)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, domain.FullID) error); ok {
|
||||
r1 = rf(ctx, id)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockCache_GetObject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetObject'
|
||||
type MockCache_GetObject_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetObject is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id domain.FullID
|
||||
func (_e *MockCache_Expecter) GetObject(ctx interface{}, id interface{}) *MockCache_GetObject_Call {
|
||||
return &MockCache_GetObject_Call{Call: _e.mock.On("GetObject", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_GetObject_Call) Run(run func(ctx context.Context, id domain.FullID)) *MockCache_GetObject_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(domain.FullID))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_GetObject_Call) Return(sb smartblock.SmartBlock, err error) *MockCache_GetObject_Call {
|
||||
_c.Call.Return(sb, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_GetObject_Call) RunAndReturn(run func(context.Context, domain.FullID) (smartblock.SmartBlock, error)) *MockCache_GetObject_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetObjectWithTimeout provides a mock function with given fields: ctx, id
|
||||
func (_m *MockCache) GetObjectWithTimeout(ctx context.Context, id domain.FullID) (smartblock.SmartBlock, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
||||
var r0 smartblock.SmartBlock
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, domain.FullID) (smartblock.SmartBlock, error)); ok {
|
||||
return rf(ctx, id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, domain.FullID) smartblock.SmartBlock); ok {
|
||||
r0 = rf(ctx, id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(smartblock.SmartBlock)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, domain.FullID) error); ok {
|
||||
r1 = rf(ctx, id)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// MockCache_GetObjectWithTimeout_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetObjectWithTimeout'
|
||||
type MockCache_GetObjectWithTimeout_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetObjectWithTimeout is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - id domain.FullID
|
||||
func (_e *MockCache_Expecter) GetObjectWithTimeout(ctx interface{}, id interface{}) *MockCache_GetObjectWithTimeout_Call {
|
||||
return &MockCache_GetObjectWithTimeout_Call{Call: _e.mock.On("GetObjectWithTimeout", ctx, id)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_GetObjectWithTimeout_Call) Run(run func(ctx context.Context, id domain.FullID)) *MockCache_GetObjectWithTimeout_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(domain.FullID))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_GetObjectWithTimeout_Call) Return(sb smartblock.SmartBlock, err error) *MockCache_GetObjectWithTimeout_Call {
|
||||
_c.Call.Return(sb, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_GetObjectWithTimeout_Call) RunAndReturn(run func(context.Context, domain.FullID) (smartblock.SmartBlock, error)) *MockCache_GetObjectWithTimeout_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Init provides a mock function with given fields: a
|
||||
func (_m *MockCache) Init(a *app.App) error {
|
||||
ret := _m.Called(a)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*app.App) error); ok {
|
||||
r0 = rf(a)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockCache_Init_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Init'
|
||||
type MockCache_Init_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Init is a helper method to define mock.On call
|
||||
// - a *app.App
|
||||
func (_e *MockCache_Expecter) Init(a interface{}) *MockCache_Init_Call {
|
||||
return &MockCache_Init_Call{Call: _e.mock.On("Init", a)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_Init_Call) Run(run func(a *app.App)) *MockCache_Init_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(*app.App))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Init_Call) Return(err error) *MockCache_Init_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Init_Call) RunAndReturn(run func(*app.App) error) *MockCache_Init_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Name provides a mock function with given fields:
|
||||
func (_m *MockCache) Name() string {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockCache_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name'
|
||||
type MockCache_Name_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Name is a helper method to define mock.On call
|
||||
func (_e *MockCache_Expecter) Name() *MockCache_Name_Call {
|
||||
return &MockCache_Name_Call{Call: _e.mock.On("Name")}
|
||||
}
|
||||
|
||||
func (_c *MockCache_Name_Call) Run(run func()) *MockCache_Name_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Name_Call) Return(name string) *MockCache_Name_Call {
|
||||
_c.Call.Return(name)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Name_Call) RunAndReturn(run func() string) *MockCache_Name_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Remove provides a mock function with given fields: ctx, objectID
|
||||
func (_m *MockCache) Remove(ctx context.Context, objectID string) error {
|
||||
ret := _m.Called(ctx, objectID)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, objectID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockCache_Remove_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Remove'
|
||||
type MockCache_Remove_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Remove is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - objectID string
|
||||
func (_e *MockCache_Expecter) Remove(ctx interface{}, objectID interface{}) *MockCache_Remove_Call {
|
||||
return &MockCache_Remove_Call{Call: _e.mock.On("Remove", ctx, objectID)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_Remove_Call) Run(run func(ctx context.Context, objectID string)) *MockCache_Remove_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Remove_Call) Return(_a0 error) *MockCache_Remove_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Remove_Call) RunAndReturn(run func(context.Context, string) error) *MockCache_Remove_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Run provides a mock function with given fields: ctx
|
||||
func (_m *MockCache) Run(ctx context.Context) error {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockCache_Run_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Run'
|
||||
type MockCache_Run_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Run is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *MockCache_Expecter) Run(ctx interface{}) *MockCache_Run_Call {
|
||||
return &MockCache_Run_Call{Call: _e.mock.On("Run", ctx)}
|
||||
}
|
||||
|
||||
func (_c *MockCache_Run_Call) Run(run func(ctx context.Context)) *MockCache_Run_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Run_Call) Return(err error) *MockCache_Run_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockCache_Run_Call) RunAndReturn(run func(context.Context) error) *MockCache_Run_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewMockCache interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewMockCache creates a new instance of MockCache. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewMockCache(t mockConstructorTestingTNewMockCache) *MockCache {
|
||||
mock := &MockCache{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package block
|
||||
package objectcache
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
|
@ -10,10 +10,12 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
spaceservice "github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
)
|
||||
|
||||
func createChangePayload(sbType coresb.SmartBlockType, key domain.UniqueKey) (data []byte, err error) {
|
||||
const ChangeType = "anytype.object"
|
||||
|
||||
func createChangePayload(sbType coresb.SmartBlockType, key domain.UniqueKey, spaceID string) (data []byte, err error) {
|
||||
var keyStr string
|
||||
if key != nil {
|
||||
if key.SmartblockType() != sbType {
|
||||
|
@ -21,15 +23,31 @@ func createChangePayload(sbType coresb.SmartBlockType, key domain.UniqueKey) (da
|
|||
}
|
||||
keyStr = key.InternalKey()
|
||||
}
|
||||
|
||||
payload := &model.ObjectChangePayload{SmartBlockType: model.SmartBlockType(sbType), Key: keyStr}
|
||||
if sbType == coresb.SmartBlockTypeSpaceView {
|
||||
mdl := &model.SpaceObjectHeader{SpaceID: spaceID}
|
||||
marshalled, err := mdl.Marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payload.Data = marshalled
|
||||
}
|
||||
return payload.Marshal()
|
||||
}
|
||||
|
||||
func derivePayload(spaceId string, signKey crypto.PrivKey, changePayload []byte) objecttree.ObjectTreeCreatePayload {
|
||||
func derivePayload(spaceId string, changePayload []byte) objecttree.ObjectTreeDerivePayload {
|
||||
return objecttree.ObjectTreeDerivePayload{
|
||||
ChangeType: spacecore.ChangeType,
|
||||
ChangePayload: changePayload,
|
||||
SpaceId: spaceId,
|
||||
IsEncrypted: true,
|
||||
}
|
||||
}
|
||||
|
||||
func derivePersonalPayload(spaceId string, signKey crypto.PrivKey, changePayload []byte) objecttree.ObjectTreeCreatePayload {
|
||||
return objecttree.ObjectTreeCreatePayload{
|
||||
PrivKey: signKey,
|
||||
ChangeType: spaceservice.ChangeType,
|
||||
ChangeType: spacecore.ChangeType,
|
||||
ChangePayload: changePayload,
|
||||
SpaceId: spaceId,
|
||||
IsEncrypted: true,
|
||||
|
@ -43,7 +61,7 @@ func createPayload(spaceId string, signKey crypto.PrivKey, changePayload []byte,
|
|||
}
|
||||
return objecttree.ObjectTreeCreatePayload{
|
||||
PrivKey: signKey,
|
||||
ChangeType: spaceservice.ChangeType,
|
||||
ChangeType: spacecore.ChangeType,
|
||||
ChangePayload: changePayload,
|
||||
SpaceId: spaceId,
|
||||
IsEncrypted: true,
|
|
@ -1,4 +1,4 @@
|
|||
package block
|
||||
package objectcache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
spaceservice "github.com/anyproto/anytype-heart/space"
|
||||
spaceservice "github.com/anyproto/anytype-heart/space/spacecore"
|
||||
)
|
||||
|
||||
func Test_Payloads(t *testing.T) {
|
||||
|
@ -56,12 +56,12 @@ func Test_Payloads(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("test derive payload", func(t *testing.T) {
|
||||
firstPayload := derivePayload("spaceId", keys.SignKey, changePayload)
|
||||
firstRoot, err := objecttree.CreateObjectTreeRoot(firstPayload, aclList)
|
||||
firstPayload := derivePayload("spaceId", changePayload)
|
||||
firstRoot, err := objecttree.DeriveObjectTreeRoot(firstPayload, aclList)
|
||||
require.NoError(t, err)
|
||||
|
||||
secondPayload := derivePayload("spaceId", keys.SignKey, changePayload)
|
||||
secondRoot, err := objecttree.CreateObjectTreeRoot(secondPayload, aclList)
|
||||
secondPayload := derivePayload("spaceId", changePayload)
|
||||
secondRoot, err := objecttree.DeriveObjectTreeRoot(secondPayload, aclList)
|
||||
require.NoError(t, err)
|
||||
|
||||
// checking that derived roots are equal
|
134
core/block/object/objectcache/tree.go
Normal file
134
core/block/object/objectcache/tree.go
Normal file
|
@ -0,0 +1,134 @@
|
|||
package objectcache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/payloadcreator"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
)
|
||||
|
||||
// TreeDerivationParams is a struct for deriving a tree
|
||||
type TreeDerivationParams struct {
|
||||
Key domain.UniqueKey
|
||||
InitFunc InitFunc
|
||||
TargetSpaceID string
|
||||
}
|
||||
|
||||
// TreeCreationParams is a struct for creating a tree
|
||||
type TreeCreationParams struct {
|
||||
Time time.Time
|
||||
SmartblockType coresb.SmartBlockType
|
||||
InitFunc InitFunc
|
||||
TargetSpaceID string
|
||||
}
|
||||
|
||||
// CreateTreePayload creates a tree payload for a given space and smart block type
|
||||
func (c *objectCache) CreateTreePayload(ctx context.Context, spaceID string, params payloadcreator.PayloadCreationParams) (treestorage.TreeStorageCreatePayload, error) {
|
||||
space, err := c.spaceService.Get(ctx, spaceID)
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
changePayload, err := createChangePayload(params.SmartblockType, nil, params.TargetSpaceID)
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
treePayload, err := createPayload(space.Id(), c.accountService.Account().SignKey, changePayload, params.Time.Unix())
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
return space.TreeBuilder().CreateTree(ctx, treePayload)
|
||||
}
|
||||
|
||||
// CreateTreeObject creates a tree object
|
||||
func (c *objectCache) CreateTreeObject(ctx context.Context, spaceID string, params TreeCreationParams) (sb smartblock.SmartBlock, err error) {
|
||||
payload, err := c.CreateTreePayload(ctx, spaceID, payloadcreator.PayloadCreationParams{
|
||||
Time: params.Time,
|
||||
SmartblockType: params.SmartblockType,
|
||||
TargetSpaceID: params.TargetSpaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.CreateTreeObjectWithPayload(ctx, spaceID, payload, params.InitFunc)
|
||||
}
|
||||
|
||||
// CreateTreeObjectWithPayload creates a tree object with a given payload and object init func
|
||||
func (c *objectCache) CreateTreeObjectWithPayload(ctx context.Context, spaceID string, payload treestorage.TreeStorageCreatePayload, initFunc InitFunc) (sb smartblock.SmartBlock, err error) {
|
||||
space, err := c.spaceService.Get(ctx, spaceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id := domain.FullID{
|
||||
SpaceID: spaceID,
|
||||
ObjectID: payload.RootRawChange.Id,
|
||||
}
|
||||
tr, err := space.TreeBuilder().PutTree(ctx, payload, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("put tree: %w", err)
|
||||
}
|
||||
if tr != nil {
|
||||
tr.Close()
|
||||
}
|
||||
ctx = ContextWithCreateOption(ctx, initFunc)
|
||||
return c.GetObject(ctx, id)
|
||||
}
|
||||
|
||||
// DeriveTreePayload derives a tree payload for a given space and smart block type
|
||||
// it takes into account whether it is for personal space and if so uses old derivation logic
|
||||
// to maintain backward compatibility
|
||||
func (c *objectCache) DeriveTreePayload(ctx context.Context, spaceID string, params payloadcreator.PayloadDerivationParams) (storagePayload treestorage.TreeStorageCreatePayload, err error) {
|
||||
space, err := c.spaceService.Get(ctx, spaceID)
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
changePayload, err := createChangePayload(params.Key.SmartblockType(), params.Key, params.TargetSpaceID)
|
||||
if err != nil {
|
||||
return treestorage.TreeStorageCreatePayload{}, err
|
||||
}
|
||||
accountKeys := c.accountService.Account()
|
||||
// we have to derive ids differently for personal space
|
||||
if c.provider.PersonalSpaceID() == spaceID {
|
||||
treePayload := derivePersonalPayload(space.Id(), accountKeys.SignKey, changePayload)
|
||||
create, err := space.TreeBuilder().CreateTree(context.Background(), treePayload)
|
||||
if err != nil {
|
||||
return storagePayload, err
|
||||
}
|
||||
return create, err
|
||||
}
|
||||
treePayload := derivePayload(space.Id(), changePayload)
|
||||
create, err := space.TreeBuilder().DeriveTree(context.Background(), treePayload)
|
||||
if err != nil {
|
||||
return storagePayload, err
|
||||
}
|
||||
return create, err
|
||||
}
|
||||
|
||||
// DeriveTreeObject derives a tree object for a given space and smart block type
|
||||
func (c *objectCache) DeriveTreeObject(ctx context.Context, spaceID string, params TreeDerivationParams) (sb smartblock.SmartBlock, err error) {
|
||||
payload, err := c.DeriveTreePayload(ctx, spaceID, payloadcreator.PayloadDerivationParams{
|
||||
Key: params.Key,
|
||||
TargetSpaceID: params.TargetSpaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: [MR] rewrite to use any-sync derivation
|
||||
return c.CreateTreeObjectWithPayload(ctx, spaceID, payload, params.InitFunc)
|
||||
}
|
||||
|
||||
func (c *objectCache) DeriveObjectID(ctx context.Context, spaceID string, uniqueKey domain.UniqueKey) (id string, err error) {
|
||||
payload, err := c.DeriveTreePayload(ctx, spaceID, payloadcreator.PayloadDerivationParams{
|
||||
Key: uniqueKey,
|
||||
TargetSpaceID: spaceID,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return payload.RootRawChange.Id, nil
|
||||
}
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/template"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/system_object"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
|
@ -28,7 +29,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/internalflag"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/uri"
|
||||
|
@ -49,7 +50,8 @@ type Service interface {
|
|||
|
||||
type Creator struct {
|
||||
blockService BlockService
|
||||
blockPicker block.Picker
|
||||
objectCache objectcache.Cache
|
||||
blockPicker block.ObjectGetter
|
||||
objectStore objectstore.ObjectStore
|
||||
collectionService CollectionService
|
||||
systemObjectService system_object.Service
|
||||
|
@ -72,7 +74,8 @@ func NewCreator() *Creator {
|
|||
|
||||
func (c *Creator) Init(a *app.App) (err error) {
|
||||
c.blockService = a.MustComponent(block.CName).(BlockService)
|
||||
c.blockPicker = a.MustComponent(block.CName).(block.Picker)
|
||||
c.objectCache = a.MustComponent(objectcache.CName).(objectcache.Cache)
|
||||
c.blockPicker = a.MustComponent(block.CName).(block.ObjectGetter)
|
||||
c.objectStore = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
c.bookmark = a.MustComponent(bookmark.CName).(bookmark.Service)
|
||||
c.bookmark = a.MustComponent(bookmark.CName).(bookmark.Service)
|
||||
|
@ -93,8 +96,6 @@ func (c *Creator) Name() (name string) {
|
|||
// TODO Temporarily
|
||||
type BlockService interface {
|
||||
StateFromTemplate(templateID, name string) (st *state.State, err error)
|
||||
CreateTreeObject(ctx context.Context, spaceID string, tp coresb.SmartBlockType, initFunc smartblock.InitFunc) (sb smartblock.SmartBlock, err error)
|
||||
DeriveTreeObjectWithUniqueKey(ctx context.Context, spaceID string, key domain.UniqueKey, initFunc smartblock.InitFunc) (sb smartblock.SmartBlock, err error)
|
||||
TemplateClone(spaceID string, id string) (templateID string, err error)
|
||||
}
|
||||
|
||||
|
@ -168,12 +169,19 @@ func (c *Creator) CreateSmartBlockFromState(ctx context.Context, spaceID string,
|
|||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
sb, err = c.blockService.DeriveTreeObjectWithUniqueKey(ctx, spaceID, uk, initFunc)
|
||||
sb, err = c.objectCache.DeriveTreeObject(ctx, spaceID, objectcache.TreeDerivationParams{
|
||||
Key: uk,
|
||||
InitFunc: initFunc,
|
||||
})
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
} else {
|
||||
sb, err = c.blockService.CreateTreeObject(ctx, spaceID, sbType, initFunc)
|
||||
sb, err = c.objectCache.CreateTreeObject(ctx, spaceID, objectcache.TreeCreationParams{
|
||||
Time: time.Now(),
|
||||
SmartblockType: sbType,
|
||||
InitFunc: initFunc,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -306,7 +314,7 @@ func (w *Creator) createRelationOption(ctx context.Context, spaceID string, deta
|
|||
} else if pbtypes.GetString(details, "name") == "" {
|
||||
return "", nil, fmt.Errorf("name is empty")
|
||||
} else if pbtypes.GetString(details, bundle.RelationKeyRelationKey.String()) == "" {
|
||||
return "", nil, fmt.Errorf("invalid relation key: unknown enum")
|
||||
return "", nil, fmt.Errorf("invalid relation Key: unknown enum")
|
||||
}
|
||||
|
||||
uniqueKey, err := getUniqueKeyOrGenerate(coresb.SmartBlockTypeRelationOption, details)
|
||||
|
@ -350,9 +358,9 @@ func (w *Creator) createObjectType(ctx context.Context, spaceID string, details
|
|||
for _, relKey := range recommendedRelationKeys {
|
||||
uk, err := domain.NewUniqueKey(coresb.SmartBlockTypeRelation, relKey)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to create unique key: %w", err)
|
||||
return "", nil, fmt.Errorf("failed to create unique Key: %w", err)
|
||||
}
|
||||
id, err := w.coreService.DeriveObjectId(ctx, spaceID, uk)
|
||||
id, err := w.objectCache.DeriveObjectID(ctx, spaceID, uk)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to derive object id: %w", err)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/database"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
|
30
core/block/object/payloadcreator/payloadcreator.go
Normal file
30
core/block/object/payloadcreator/payloadcreator.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package payloadcreator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/treestorage"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
)
|
||||
|
||||
// PayloadDerivationParams is a struct for deriving a payload
|
||||
type PayloadDerivationParams struct {
|
||||
Key domain.UniqueKey
|
||||
TargetSpaceID string
|
||||
}
|
||||
|
||||
// PayloadCreationParams is a struct for creating a payload
|
||||
type PayloadCreationParams struct {
|
||||
Time time.Time
|
||||
SmartblockType coresb.SmartBlockType
|
||||
TargetSpaceID string
|
||||
}
|
||||
|
||||
type PayloadCreator interface {
|
||||
CreateTreePayload(ctx context.Context, spaceID string, params PayloadCreationParams) (treestorage.TreeStorageCreatePayload, error)
|
||||
DeriveTreePayload(ctx context.Context, spaceID string, params PayloadDerivationParams) (storagePayload treestorage.TreeStorageCreatePayload, err error)
|
||||
DeriveObjectID(ctx context.Context, spaceID string, uniqueKey domain.UniqueKey) (id string, err error)
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
package treemanager
|
|
@ -22,10 +22,6 @@ import (
|
|||
|
||||
var log = logging.Logger("anytype-mw-tree-manager")
|
||||
|
||||
const (
|
||||
concurrentTrees = 10
|
||||
)
|
||||
|
||||
var errAppIsNotRunning = errors.New("app is not running")
|
||||
|
||||
type treeManager struct {
|
||||
|
@ -35,7 +31,6 @@ type treeManager struct {
|
|||
|
||||
onDelete func(id domain.FullID) error
|
||||
|
||||
syncer map[string]*treeSyncer
|
||||
syncStarted bool
|
||||
syncerLock sync.Mutex
|
||||
}
|
||||
|
@ -47,7 +42,6 @@ func New() treemanager.TreeManager {
|
|||
func newTreeManager(onDelete func(id domain.FullID) error) *treeManager {
|
||||
return &treeManager{
|
||||
onDelete: onDelete,
|
||||
syncer: make(map[string]*treeSyncer),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,15 +74,6 @@ func (m *treeManager) Close(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *treeManager) StartSync() {
|
||||
m.syncerLock.Lock()
|
||||
defer m.syncerLock.Unlock()
|
||||
m.syncStarted = true
|
||||
for _, syncer := range m.syncer {
|
||||
syncer.Run()
|
||||
}
|
||||
}
|
||||
|
||||
// GetTree should only be called by either space services or debug apis, not the client code
|
||||
func (m *treeManager) GetTree(ctx context.Context, spaceId, id string) (tr objecttree.ObjectTree, err error) {
|
||||
if !m.coreService.IsStarted() {
|
||||
|
@ -145,19 +130,6 @@ func (m *treeManager) DeleteTree(ctx context.Context, spaceId, treeId string) (e
|
|||
return
|
||||
}
|
||||
|
||||
// NewTreeSyncer is called in commonspace.SpaceService/NewSpace, so loading a space into cache in space.Service creates a syncer
|
||||
func (m *treeManager) NewTreeSyncer(spaceId string, treeManager treemanager.TreeManager) treemanager.TreeSyncer {
|
||||
m.syncerLock.Lock()
|
||||
defer m.syncerLock.Unlock()
|
||||
syncer := newTreeSyncer(spaceId, objectcache.ObjectLoadTimeout, concurrentTrees, treeManager)
|
||||
m.syncer[spaceId] = syncer
|
||||
if m.syncStarted {
|
||||
log.With("spaceID", spaceId).Warn("creating tree syncer after run")
|
||||
syncer.Run()
|
||||
}
|
||||
return syncer
|
||||
}
|
||||
|
||||
func (m *treeManager) sendOnRemoveEvent(ids ...string) {
|
||||
m.eventSender.Broadcast(&pb.Event{
|
||||
Messages: []*pb.EventMessage{
|
|
@ -1,130 +0,0 @@
|
|||
package treemanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree/mock_objecttree"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/synctree/mock_synctree"
|
||||
"github.com/anyproto/any-sync/commonspace/object/treemanager/mock_treemanager"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
)
|
||||
|
||||
func TestTreeSyncer(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
managerMock := mock_treemanager.NewMockTreeManager(ctrl)
|
||||
spaceId := "spaceId"
|
||||
peerId := "peerId"
|
||||
existingId := "existing"
|
||||
missingId := "missing"
|
||||
missingMock := mock_objecttree.NewMockObjectTree(ctrl)
|
||||
existingMock := mock_synctree.NewMockSyncTree(ctrl)
|
||||
|
||||
t.Run("delayed sync", func(t *testing.T) {
|
||||
syncer := newTreeSyncer(spaceId, objectcache.ObjectLoadTimeout, 10, managerMock)
|
||||
syncer.Init()
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(existingMock, nil)
|
||||
existingMock.EXPECT().SyncWithPeer(gomock.Any(), peerId).Return(nil)
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(missingMock, nil)
|
||||
err := syncer.SyncAll(context.Background(), peerId, []string{existingId}, []string{missingId})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, syncer.requestPools[peerId])
|
||||
require.NotNil(t, syncer.headPools[peerId])
|
||||
|
||||
syncer.Run()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
syncer.Close()
|
||||
})
|
||||
|
||||
t.Run("sync after run", func(t *testing.T) {
|
||||
syncer := newTreeSyncer(spaceId, objectcache.ObjectLoadTimeout, 10, managerMock)
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(existingMock, nil)
|
||||
existingMock.EXPECT().SyncWithPeer(gomock.Any(), peerId).Return(nil)
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(missingMock, nil)
|
||||
syncer.Init()
|
||||
syncer.Run()
|
||||
err := syncer.SyncAll(context.Background(), peerId, []string{existingId}, []string{missingId})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, syncer.requestPools[peerId])
|
||||
require.NotNil(t, syncer.headPools[peerId])
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
syncer.Close()
|
||||
})
|
||||
|
||||
t.Run("sync same ids", func(t *testing.T) {
|
||||
syncer := newTreeSyncer(spaceId, objectcache.ObjectLoadTimeout, 10, managerMock)
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(existingMock, nil)
|
||||
existingMock.EXPECT().SyncWithPeer(gomock.Any(), peerId).Return(nil)
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(missingMock, nil)
|
||||
syncer.Init()
|
||||
syncer.Run()
|
||||
err := syncer.SyncAll(context.Background(), peerId, []string{existingId, existingId}, []string{missingId, missingId, missingId})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, syncer.requestPools[peerId])
|
||||
require.NotNil(t, syncer.headPools[peerId])
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
syncer.Close()
|
||||
})
|
||||
|
||||
t.Run("sync concurrent ids", func(t *testing.T) {
|
||||
ch := make(chan struct{}, 2)
|
||||
syncer := newTreeSyncer(spaceId, objectcache.ObjectLoadTimeout, 2, managerMock)
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(existingMock, nil)
|
||||
existingMock.EXPECT().SyncWithPeer(gomock.Any(), peerId).Return(nil)
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, missingId+"1").DoAndReturn(func(ctx context.Context, spaceId, treeId string) (objecttree.ObjectTree, error) {
|
||||
<-ch
|
||||
return missingMock, nil
|
||||
})
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, missingId+"2").DoAndReturn(func(ctx context.Context, spaceId, treeId string) (objecttree.ObjectTree, error) {
|
||||
<-ch
|
||||
return missingMock, nil
|
||||
})
|
||||
syncer.Init()
|
||||
syncer.Run()
|
||||
err := syncer.SyncAll(context.Background(), peerId, []string{existingId}, []string{missingId + "1", missingId + "2"})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, syncer.requestPools[peerId])
|
||||
require.NotNil(t, syncer.headPools[peerId])
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
syncer.Close()
|
||||
for i := 0; i < 2; i++ {
|
||||
ch <- struct{}{}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("sync context cancel", func(t *testing.T) {
|
||||
var events []string
|
||||
syncer := newTreeSyncer(spaceId, objectcache.ObjectLoadTimeout, 1, managerMock)
|
||||
mutex := sync.Mutex{}
|
||||
managerMock.EXPECT().GetTree(gomock.Any(), spaceId, missingId).DoAndReturn(func(ctx context.Context, spaceId, treeId string) (objecttree.ObjectTree, error) {
|
||||
<-ctx.Done()
|
||||
mutex.Lock()
|
||||
events = append(events, "after done")
|
||||
mutex.Unlock()
|
||||
return missingMock, nil
|
||||
})
|
||||
syncer.Init()
|
||||
syncer.Run()
|
||||
err := syncer.SyncAll(context.Background(), peerId, nil, []string{missingId})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, syncer.requestPools[peerId])
|
||||
require.NotNil(t, syncer.headPools[peerId])
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
mutex.Lock()
|
||||
events = append(events, "before close")
|
||||
mutex.Unlock()
|
||||
syncer.Close()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
mutex.Lock()
|
||||
require.Equal(t, []string{"before close", "after done"}, events)
|
||||
mutex.Unlock()
|
||||
})
|
||||
}
|
|
@ -1,17 +1,22 @@
|
|||
package treemanager
|
||||
package treesyncer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/anyproto/any-sync/app/logger"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/synctree"
|
||||
"github.com/anyproto/any-sync/commonspace/object/treemanager"
|
||||
"github.com/anyproto/any-sync/commonspace/object/treesyncer"
|
||||
"github.com/anyproto/any-sync/net/peer"
|
||||
"github.com/anyproto/any-sync/net/streampool"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var log = logger.NewNamed(treemanager.CName)
|
||||
|
||||
type executor struct {
|
||||
pool *streampool.ExecPool
|
||||
objs map[string]struct{}
|
||||
|
@ -61,28 +66,51 @@ type treeSyncer struct {
|
|||
isRunning bool
|
||||
}
|
||||
|
||||
func newTreeSyncer(spaceId string, timeout time.Duration, concurrentReqs int, treeManager treemanager.TreeManager) *treeSyncer {
|
||||
func NewTreeSyncer(spaceId string) treesyncer.TreeSyncer {
|
||||
mainCtx, cancel := context.WithCancel(context.Background())
|
||||
return &treeSyncer{
|
||||
mainCtx: mainCtx,
|
||||
cancel: cancel,
|
||||
requests: concurrentReqs,
|
||||
requests: 10,
|
||||
spaceId: spaceId,
|
||||
timeout: timeout,
|
||||
timeout: time.Second * 30,
|
||||
requestPools: map[string]*executor{},
|
||||
headPools: map[string]*executor{},
|
||||
treeManager: treeManager,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *treeSyncer) Init() {
|
||||
func (t *treeSyncer) Init(a *app.App) (err error) {
|
||||
t.treeManager = app.MustComponent[treemanager.TreeManager](a)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *treeSyncer) Run() {
|
||||
func (t *treeSyncer) Name() (name string) {
|
||||
return treesyncer.CName
|
||||
}
|
||||
|
||||
func (t *treeSyncer) Run(ctx context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *treeSyncer) Close(ctx context.Context) (err error) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.cancel()
|
||||
t.isRunning = false
|
||||
for _, pool := range t.headPools {
|
||||
pool.close()
|
||||
}
|
||||
for _, pool := range t.requestPools {
|
||||
pool.close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *treeSyncer) StartSync() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.isRunning = true
|
||||
log.Info("starting request pool")
|
||||
log.Info("starting request pool", zap.String("spaceId", t.spaceId))
|
||||
for _, p := range t.requestPools {
|
||||
p.run()
|
||||
}
|
||||
|
@ -162,17 +190,3 @@ func (t *treeSyncer) updateTree(peerId, id string) {
|
|||
log.Debug("success synctree.SyncWithPeer")
|
||||
}
|
||||
}
|
||||
|
||||
func (t *treeSyncer) Close() error {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.cancel()
|
||||
t.isRunning = false
|
||||
for _, pool := range t.headPools {
|
||||
pool.close()
|
||||
}
|
||||
for _, pool := range t.requestPools {
|
||||
pool.close()
|
||||
}
|
||||
return nil
|
||||
}
|
156
core/block/object/treesyncer/treesyncer_test.go
Normal file
156
core/block/object/treesyncer/treesyncer_test.go
Normal file
|
@ -0,0 +1,156 @@
|
|||
package treesyncer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree/mock_objecttree"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/synctree/mock_synctree"
|
||||
"github.com/anyproto/any-sync/commonspace/object/treemanager/mock_treemanager"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"github.com/anyproto/anytype-heart/tests/testutil"
|
||||
)
|
||||
|
||||
type fixture struct {
|
||||
*treeSyncer
|
||||
|
||||
missingMock *mock_objecttree.MockObjectTree
|
||||
existingMock *mock_synctree.MockSyncTree
|
||||
treeManager *mock_treemanager.MockTreeManager
|
||||
}
|
||||
|
||||
func newFixture(t *testing.T, spaceId string) *fixture {
|
||||
ctrl := gomock.NewController(t)
|
||||
treeManager := mock_treemanager.NewMockTreeManager(ctrl)
|
||||
missingMock := mock_objecttree.NewMockObjectTree(ctrl)
|
||||
existingMock := mock_synctree.NewMockSyncTree(ctrl)
|
||||
|
||||
a := new(app.App)
|
||||
a.Register(testutil.PrepareMock(context.Background(), a, treeManager))
|
||||
syncer := NewTreeSyncer(spaceId)
|
||||
err := syncer.Init(a)
|
||||
require.NoError(t, err)
|
||||
|
||||
return &fixture{
|
||||
treeSyncer: syncer.(*treeSyncer),
|
||||
missingMock: missingMock,
|
||||
existingMock: existingMock,
|
||||
treeManager: treeManager,
|
||||
}
|
||||
}
|
||||
|
||||
func TestTreeSyncer(t *testing.T) {
|
||||
|
||||
spaceId := "spaceId"
|
||||
peerId := "peerId"
|
||||
existingId := "existing"
|
||||
missingId := "missing"
|
||||
|
||||
t.Run("delayed sync", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
fx := newFixture(t, spaceId)
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(fx.existingMock, nil)
|
||||
fx.existingMock.EXPECT().SyncWithPeer(gomock.Any(), peerId).Return(nil)
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(fx.missingMock, nil)
|
||||
err := fx.SyncAll(context.Background(), peerId, []string{existingId}, []string{missingId})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, fx.requestPools[peerId])
|
||||
require.NotNil(t, fx.headPools[peerId])
|
||||
|
||||
fx.StartSync()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
fx.Close(ctx)
|
||||
})
|
||||
|
||||
t.Run("sync after run", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
fx := newFixture(t, spaceId)
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(fx.existingMock, nil)
|
||||
fx.existingMock.EXPECT().SyncWithPeer(gomock.Any(), peerId).Return(nil)
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(fx.missingMock, nil)
|
||||
fx.StartSync()
|
||||
err := fx.SyncAll(context.Background(), peerId, []string{existingId}, []string{missingId})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, fx.requestPools[peerId])
|
||||
require.NotNil(t, fx.headPools[peerId])
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
fx.Close(ctx)
|
||||
})
|
||||
|
||||
t.Run("sync same ids", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
fx := newFixture(t, spaceId)
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(fx.existingMock, nil)
|
||||
fx.existingMock.EXPECT().SyncWithPeer(gomock.Any(), peerId).Return(nil)
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId).Return(fx.missingMock, nil)
|
||||
fx.StartSync()
|
||||
err := fx.SyncAll(context.Background(), peerId, []string{existingId, existingId}, []string{missingId, missingId, missingId})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, fx.requestPools[peerId])
|
||||
require.NotNil(t, fx.headPools[peerId])
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
fx.Close(ctx)
|
||||
})
|
||||
|
||||
t.Run("sync concurrent ids", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ch := make(chan struct{}, 2)
|
||||
fx := newFixture(t, spaceId)
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, existingId).Return(fx.existingMock, nil)
|
||||
fx.existingMock.EXPECT().SyncWithPeer(gomock.Any(), peerId).Return(nil)
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId+"1").DoAndReturn(func(ctx context.Context, spaceId, treeId string) (objecttree.ObjectTree, error) {
|
||||
<-ch
|
||||
return fx.missingMock, nil
|
||||
})
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId+"2").DoAndReturn(func(ctx context.Context, spaceId, treeId string) (objecttree.ObjectTree, error) {
|
||||
<-ch
|
||||
return fx.missingMock, nil
|
||||
})
|
||||
fx.StartSync()
|
||||
err := fx.SyncAll(context.Background(), peerId, []string{existingId}, []string{missingId + "1", missingId + "2"})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, fx.requestPools[peerId])
|
||||
require.NotNil(t, fx.headPools[peerId])
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
fx.Close(ctx)
|
||||
for i := 0; i < 2; i++ {
|
||||
ch <- struct{}{}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("sync context cancel", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
var events []string
|
||||
fx := newFixture(t, spaceId)
|
||||
mutex := sync.Mutex{}
|
||||
fx.treeManager.EXPECT().GetTree(gomock.Any(), spaceId, missingId).DoAndReturn(func(ctx context.Context, spaceId, treeId string) (objecttree.ObjectTree, error) {
|
||||
<-ctx.Done()
|
||||
mutex.Lock()
|
||||
events = append(events, "after done")
|
||||
mutex.Unlock()
|
||||
return fx.missingMock, nil
|
||||
})
|
||||
fx.StartSync()
|
||||
err := fx.SyncAll(context.Background(), peerId, nil, []string{missingId})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, fx.requestPools[peerId])
|
||||
require.NotNil(t, fx.headPools[peerId])
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
mutex.Lock()
|
||||
events = append(events, "before close")
|
||||
mutex.Unlock()
|
||||
fx.Close(ctx)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
mutex.Lock()
|
||||
require.Equal(t, []string{"before close", "after done"}, events)
|
||||
mutex.Unlock()
|
||||
})
|
||||
}
|
|
@ -39,7 +39,6 @@ func TestService_DataviewRestrictions(t *testing.T) {
|
|||
|
||||
t.Run("ordinary objects don't have restrictions", func(t *testing.T) {
|
||||
objectTypeID := "derivedFrom(page)"
|
||||
s.systemObjectServiceMock.EXPECT().HasObjectType(objectTypeID).Return(true, nil)
|
||||
restrictions := s.GetRestrictions(
|
||||
newRestrictionHolder(
|
||||
smartblock.SmartBlockTypePage,
|
||||
|
|
|
@ -7,19 +7,19 @@ import (
|
|||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"context"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/system_object/mock_system_object"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore/mock_objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider/mock_typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider/mock_typeprovider"
|
||||
"github.com/anyproto/anytype-heart/tests/testutil"
|
||||
)
|
||||
|
||||
type fixture struct {
|
||||
Service
|
||||
objectStoreMock *mock_objectstore.MockObjectStore
|
||||
systemObjectServiceMock *mock_system_object.MockService
|
||||
objectStoreMock *mock_objectstore.MockObjectStore
|
||||
}
|
||||
|
||||
func newFixture(t *testing.T) *fixture {
|
||||
|
@ -34,14 +34,13 @@ func newFixture(t *testing.T) *fixture {
|
|||
a := &app.App{}
|
||||
a.Register(objectStore)
|
||||
a.Register(sbtProvider)
|
||||
a.Register(testutil.PrepareMock(a, systemObjectService))
|
||||
a.Register(testutil.PrepareMock(context.Background(), a, systemObjectService))
|
||||
s := New()
|
||||
err := s.Init(a)
|
||||
require.NoError(t, err)
|
||||
return &fixture{
|
||||
Service: s,
|
||||
objectStoreMock: objectStore,
|
||||
systemObjectServiceMock: systemObjectService,
|
||||
Service: s,
|
||||
objectStoreMock: objectStore,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package restriction
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogo/protobuf/types"
|
||||
|
@ -210,13 +209,6 @@ func (s *service) getObjectRestrictions(rh RestrictionHolder) (r ObjectRestricti
|
|||
r = ObjectRestrictions{}
|
||||
}
|
||||
}
|
||||
|
||||
if !errors.Is(r.Check(model.Restrictions_Template), ErrRestricted) {
|
||||
if ok, err := s.systemObjectService.HasObjectType(rh.ObjectTypeID()); err != nil || !ok {
|
||||
r = append(r, model.Restrictions_Template)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -3,18 +3,15 @@ package restriction
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
coresb "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TODO Use constructors instead for initializing restrictionHolder structures by hand. See givenObjectType and givenRelation
|
||||
func TestService_ObjectRestrictionsById(t *testing.T) {
|
||||
rest := newFixture(t)
|
||||
rest.systemObjectServiceMock.EXPECT().HasObjectType(mock.Anything).Return(false, nil)
|
||||
|
||||
assert.ErrorIs(t, rest.GetRestrictions(&restrictionHolder{
|
||||
sbType: coresb.SmartBlockTypeAnytypeProfile,
|
||||
|
@ -93,8 +90,6 @@ func TestService_ObjectRestrictionsById(t *testing.T) {
|
|||
// TODO Use constructors instead for initializing restrictionHolder structures by hand. See givenObjectType and givenRelation
|
||||
func TestTemplateRestriction(t *testing.T) {
|
||||
rs := newFixture(t)
|
||||
rs.systemObjectServiceMock.EXPECT().HasObjectType(bundle.TypeKeyPage.URL()).Return(false, nil)
|
||||
rs.systemObjectServiceMock.EXPECT().HasObjectType(bundle.TypeKeyContact.URL()).Return(true, nil)
|
||||
|
||||
assert.ErrorIs(t, rs.GetRestrictions(&restrictionHolder{
|
||||
// id: "cannot make template from Template smartblock type",
|
||||
|
@ -123,15 +118,6 @@ func TestTemplateRestriction(t *testing.T) {
|
|||
model.Restrictions_Template,
|
||||
), ErrRestricted)
|
||||
|
||||
assert.ErrorIs(t, rs.GetRestrictions(&restrictionHolder{
|
||||
// id: "cannot make template from object with objectType not added to space",
|
||||
sbType: coresb.SmartBlockTypePage,
|
||||
layout: model.ObjectType_basic,
|
||||
objectTypeID: bundle.TypeKeyPage.URL(),
|
||||
}).Object.Check(
|
||||
model.Restrictions_Template,
|
||||
), ErrRestricted)
|
||||
|
||||
assert.NoError(t, rs.GetRestrictions(&restrictionHolder{
|
||||
// id: "make template from object with objectType added to space",
|
||||
sbType: coresb.SmartBlockTypePage,
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/template"
|
||||
"github.com/anyproto/anytype-heart/core/block/history"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/block/process"
|
||||
"github.com/anyproto/anytype-heart/core/block/restriction"
|
||||
|
@ -49,7 +50,8 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/internalflag"
|
||||
"github.com/anyproto/anytype-heart/util/linkpreview"
|
||||
"github.com/anyproto/anytype-heart/util/mutex"
|
||||
|
@ -105,7 +107,6 @@ type objectCreator interface {
|
|||
CreateSmartBlockFromState(ctx context.Context, spaceID string, sbType coresb.SmartBlockType, objectTypeKeys []domain.TypeKey, details *types.Struct, createState *state.State) (id string, newDetails *types.Struct, err error)
|
||||
CreateObject(ctx context.Context, spaceID string, req DetailsGetter, objectTypeKey domain.TypeKey) (id string, details *types.Struct, err error)
|
||||
}
|
||||
|
||||
type DetailsGetter interface {
|
||||
GetDetails() *types.Struct
|
||||
}
|
||||
|
@ -115,34 +116,27 @@ type InternalFlagsGetter interface {
|
|||
type TemplateIDGetter interface {
|
||||
GetTemplateId() string
|
||||
}
|
||||
|
||||
type indexer interface {
|
||||
EnsurePreinstalledObjects(spaceID string) error
|
||||
}
|
||||
|
||||
type builtinObjects interface {
|
||||
CreateObjectsForUseCase(ctx session.Context, spaceID string, req pb.RpcObjectImportUseCaseRequestUseCase) (code pb.RpcObjectImportUseCaseResponseErrorCode, err error)
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
anytype core.Service
|
||||
syncStatus syncstatus.Service
|
||||
eventSender event.Sender
|
||||
linkPreview linkpreview.LinkPreview
|
||||
process process.Service
|
||||
app *app.App
|
||||
source source.Service
|
||||
objectStore objectstore.ObjectStore
|
||||
restriction restriction.Service
|
||||
bookmark bookmarksvc.Service
|
||||
systemObjectService system_object.Service
|
||||
objectCache objectcache.Cache
|
||||
|
||||
indexer indexer
|
||||
|
||||
objectCreator objectCreator
|
||||
|
||||
spaceService space.Service
|
||||
anytype core.Service
|
||||
syncStatus syncstatus.Service
|
||||
eventSender event.Sender
|
||||
linkPreview linkpreview.LinkPreview
|
||||
process process.Service
|
||||
app *app.App
|
||||
source source.Service
|
||||
objectStore objectstore.ObjectStore
|
||||
restriction restriction.Service
|
||||
bookmark bookmarksvc.Service
|
||||
systemObjectService system_object.Service
|
||||
objectCache objectcache.Cache
|
||||
objectCreator objectCreator
|
||||
resolver idresolver.Resolver
|
||||
spaceService space.SpaceService
|
||||
spaceCore spacecore.SpaceCoreService
|
||||
commonAccount accountservice.Service
|
||||
fileStore filestore.FileStore
|
||||
tempDirProvider core.TempDirProvider
|
||||
|
@ -178,18 +172,19 @@ func (s *Service) Init(a *app.App) (err error) {
|
|||
s.bookmark = a.MustComponent("bookmark-importer").(bookmarksvc.Service)
|
||||
s.systemObjectService = a.MustComponent(system_object.CName).(system_object.Service)
|
||||
s.objectCreator = a.MustComponent("objectCreator").(objectCreator)
|
||||
s.spaceService = a.MustComponent(space.CName).(space.Service)
|
||||
s.spaceService = a.MustComponent(space.CName).(space.SpaceService)
|
||||
s.commonAccount = a.MustComponent(accountservice.CName).(accountservice.Service)
|
||||
s.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
s.fileSync = app.MustComponent[filesync.FileSync](a)
|
||||
s.fileService = app.MustComponent[files.Service](a)
|
||||
s.objectCache = app.MustComponent[objectcache.Cache](a)
|
||||
s.resolver = a.MustComponent(idresolver.CName).(idresolver.Resolver)
|
||||
s.spaceCore = app.MustComponent[spacecore.SpaceCoreService](a)
|
||||
|
||||
s.tempDirProvider = app.MustComponent[core.TempDirProvider](a)
|
||||
s.sbtProvider = app.MustComponent[typeprovider.SmartBlockTypeProvider](a)
|
||||
s.layoutConverter = app.MustComponent[converter.LayoutConverter](a)
|
||||
|
||||
s.indexer = app.MustComponent[indexer](a)
|
||||
s.builtinObjectService = app.MustComponent[builtinObjects](a)
|
||||
s.app = a
|
||||
return
|
||||
|
@ -199,12 +194,23 @@ func (s *Service) Run(ctx context.Context) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (s *Service) PickBlock(ctx context.Context, objectID string) (sb smartblock.SmartBlock, err error) {
|
||||
return s.objectCache.PickBlock(ctx, objectID)
|
||||
func (s *Service) GetObject(ctx context.Context, objectID string) (sb smartblock.SmartBlock, err error) {
|
||||
spaceID, err := s.resolver.ResolveSpaceID(objectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.objectCache.GetObject(ctx, domain.FullID{
|
||||
ObjectID: objectID,
|
||||
SpaceID: spaceID,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) GetObjectByFullID(ctx context.Context, id domain.FullID) (sb smartblock.SmartBlock, err error) {
|
||||
return s.objectCache.GetObject(ctx, id)
|
||||
}
|
||||
|
||||
func (s *Service) OpenBlock(sctx session.Context, id string, includeRelationsAsDependentObjects bool) (obj *model.ObjectView, err error) {
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(id)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve space id: %w", err)
|
||||
}
|
||||
|
@ -358,7 +364,7 @@ func (s *Service) prepareDetailsForInstallingObject(ctx context.Context, spaceID
|
|||
// should never happen
|
||||
return nil, err
|
||||
}
|
||||
id, err := s.anytype.DeriveObjectId(ctx, spaceID, uniqueKey)
|
||||
id, err := s.objectCache.DeriveObjectID(ctx, spaceID, uniqueKey)
|
||||
if err != nil {
|
||||
// should never happen
|
||||
return nil, err
|
||||
|
@ -378,7 +384,7 @@ func (s *Service) prepareDetailsForInstallingObject(ctx context.Context, spaceID
|
|||
// should never happen
|
||||
return nil, err
|
||||
}
|
||||
id, err := s.anytype.DeriveObjectId(ctx, spaceID, uniqueKey)
|
||||
id, err := s.objectCache.DeriveObjectID(ctx, spaceID, uniqueKey)
|
||||
if err != nil {
|
||||
// should never happen
|
||||
return nil, err
|
||||
|
@ -617,60 +623,19 @@ func (s *Service) SelectWorkspace(req *pb.RpcWorkspaceSelectRequest) error {
|
|||
}
|
||||
|
||||
func (s *Service) GetCurrentWorkspace(req *pb.RpcWorkspaceGetCurrentRequest) (string, error) {
|
||||
return "", nil
|
||||
panic("should be removed")
|
||||
}
|
||||
|
||||
func (s *Service) GetAllWorkspaces(req *pb.RpcWorkspaceGetAllRequest) ([]string, error) {
|
||||
return nil, nil
|
||||
panic("should be removed")
|
||||
}
|
||||
|
||||
func (s *Service) SetIsHighlighted(req *pb.RpcWorkspaceSetIsHighlightedRequest) error {
|
||||
panic("is not implemented")
|
||||
// workspaceId, _ := s.anytype.GetWorkspaceIdForObject(req.ObjectId)
|
||||
// return Do(s,ctx, workspaceId, func(b smartblock.SmartBlock) error {
|
||||
// workspace, ok := b.(*editor.Workspaces)
|
||||
// if !ok {
|
||||
// return fmt.Errorf("incorrect object with workspace id")
|
||||
// }
|
||||
// return workspace.SetIsHighlighted(req.ObjectId, req.IsHighlighted)
|
||||
// })
|
||||
panic("should be removed")
|
||||
}
|
||||
|
||||
func (s *Service) ObjectShareByLink(req *pb.RpcObjectShareByLinkRequest) (link string, err error) {
|
||||
return "", fmt.Errorf("not implemented")
|
||||
// workspaceId, err := s.anytype.GetWorkspaceIdForObject(req.ObjectId)
|
||||
// if err == core.ErrObjectDoesNotBelongToWorkspace {
|
||||
// workspaceId = s.Anytype().AccountObjects().Account
|
||||
// }
|
||||
// var key string
|
||||
// var addrs []string
|
||||
// err = Do(s,ctx, workspaceId, func(b smartblock.SmartBlock) error {
|
||||
// workspace, ok := b.(*editor.Workspaces)
|
||||
// if !ok {
|
||||
// return fmt.Errorf("incorrect object with workspace id")
|
||||
// }
|
||||
// key, addrs, err = workspace.GetObjectKeyAddrs(req.ObjectId)
|
||||
// return err
|
||||
// })
|
||||
// if err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
// payload := &model.ThreadDeeplinkPayload{
|
||||
// Key: key,
|
||||
// Addrs: addrs,
|
||||
// }
|
||||
// marshalledPayload, err := proto.Marshal(payload)
|
||||
// if err != nil {
|
||||
// return "", fmt.Errorf("failed to marshal deeplink payload: %w", err)
|
||||
// }
|
||||
// encodedPayload := base64.RawStdEncoding.EncodeToString(marshalledPayload)
|
||||
//
|
||||
// params := url.Values{}
|
||||
// params.Add("id", req.ObjectId)
|
||||
// params.Add("payload", encodedPayload)
|
||||
// encoded := params.Encode()
|
||||
//
|
||||
// return fmt.Sprintf("%s%s", linkObjectShare, encoded), nil
|
||||
panic("should be removed")
|
||||
}
|
||||
|
||||
func (s *Service) SetPagesIsArchived(ctx session.Context, req pb.RpcObjectListSetIsArchivedRequest) error {
|
||||
|
@ -743,7 +708,7 @@ func (s *Service) setIsArchivedForObjects(spaceID string, objectIDs []string, is
|
|||
func (s *Service) partitionObjectIDsBySpaceID(objectIDs []string) (map[string][]string, error) {
|
||||
res := map[string][]string{}
|
||||
for _, objectID := range objectIDs {
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(objectID)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(objectID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -797,7 +762,7 @@ func (s *Service) objectLinksCollectionModify(collectionId string, objectId stri
|
|||
}
|
||||
|
||||
func (s *Service) SetPageIsFavorite(req pb.RpcObjectSetIsFavoriteRequest) (err error) {
|
||||
spaceID, err := s.ResolveSpaceID(req.ContextId)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(req.ContextId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -805,7 +770,7 @@ func (s *Service) SetPageIsFavorite(req pb.RpcObjectSetIsFavoriteRequest) (err e
|
|||
}
|
||||
|
||||
func (s *Service) SetPageIsArchived(req pb.RpcObjectSetIsArchivedRequest) (err error) {
|
||||
spaceID, err := s.ResolveSpaceID(req.ContextId)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(req.ContextId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -895,7 +860,7 @@ func (s *Service) ObjectsDuplicate(ctx context.Context, ids []string) (newIds []
|
|||
}
|
||||
|
||||
func (s *Service) DeleteArchivedObject(id string) (err error) {
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(id)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -987,10 +952,6 @@ func (s *Service) Close(ctx context.Context) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) ResolveSpaceID(objectID string) (spaceID string, err error) {
|
||||
return s.spaceService.ResolveSpaceID(objectID)
|
||||
}
|
||||
|
||||
func (s *Service) StateFromTemplate(templateID, name string) (st *state.State, err error) {
|
||||
if templateID == BlankTemplateID || templateID == "" {
|
||||
return s.BlankTemplateState(), nil
|
||||
|
@ -1009,7 +970,7 @@ func (s *Service) StateFromTemplate(templateID, name string) (st *state.State, e
|
|||
}
|
||||
|
||||
func (s *Service) DoFileNonLock(id string, apply func(b file.File) error) error {
|
||||
sb, err := s.PickBlock(context.Background(), id)
|
||||
sb, err := s.GetObject(context.Background(), id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1057,7 +1018,7 @@ func (s *Service) ResetToState(pageID string, st *state.State) (err error) {
|
|||
}
|
||||
|
||||
func (s *Service) ObjectBookmarkFetch(req pb.RpcObjectBookmarkFetchRequest) (err error) {
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(req.ContextId)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(req.ContextId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -1075,7 +1036,7 @@ func (s *Service) ObjectBookmarkFetch(req pb.RpcObjectBookmarkFetchRequest) (err
|
|||
}
|
||||
|
||||
func (s *Service) ObjectToBookmark(ctx context.Context, id string, url string) (objectId string, err error) {
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(id)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(id)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"
|
||||
"github.com/anyproto/any-sync/commonspace/object/tree/synctree/updatelistener"
|
||||
"github.com/anyproto/any-sync/commonspace/objecttreebuilder"
|
||||
"github.com/anyproto/any-sync/commonspace/spacestorage"
|
||||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
|
@ -22,8 +23,9 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/addr"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/storage"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
)
|
||||
|
||||
const CName = "source"
|
||||
|
@ -32,6 +34,11 @@ func New() Service {
|
|||
return &service{}
|
||||
}
|
||||
|
||||
type idResolver interface {
|
||||
BindSpaceID(spaceID string, objectID string) error
|
||||
ResolveSpaceID(objectID string) (spaceID string, err error)
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
NewSource(ctx context.Context, id string, spaceID string, buildOptions BuildOptions) (source Source, err error)
|
||||
RegisterStaticSource(s Source) error
|
||||
|
@ -48,7 +55,8 @@ type service struct {
|
|||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
account accountservice.Service
|
||||
fileStore filestore.FileStore
|
||||
spaceService space.Service
|
||||
spaceService spacecore.SpaceCoreService
|
||||
storageService storage.ClientStorage
|
||||
fileService files.Service
|
||||
systemObjectService system_object.Service
|
||||
|
||||
|
@ -64,7 +72,8 @@ func (s *service) Init(a *app.App) (err error) {
|
|||
s.sbtProvider = a.MustComponent(typeprovider.CName).(typeprovider.SmartBlockTypeProvider)
|
||||
s.account = a.MustComponent(accountservice.CName).(accountservice.Service)
|
||||
s.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
s.spaceService = app.MustComponent[space.Service](a)
|
||||
s.spaceService = app.MustComponent[spacecore.SpaceCoreService](a)
|
||||
s.storageService = a.MustComponent(spacestorage.CName).(storage.ClientStorage)
|
||||
s.systemObjectService = app.MustComponent[system_object.Service](a)
|
||||
|
||||
s.fileService = app.MustComponent[files.Service](a)
|
||||
|
@ -92,7 +101,7 @@ func (s *service) NewSource(ctx context.Context, id string, spaceID string, buil
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = s.spaceService.StoreSpaceID(src.Id(), src.SpaceID())
|
||||
err = s.storageService.BindSpaceID(src.SpaceID(), src.Id())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("store space id for object: %w", err)
|
||||
}
|
||||
|
@ -125,7 +134,7 @@ func (s *service) newSource(ctx context.Context, id string, spaceID string, buil
|
|||
return staticSrc, nil
|
||||
}
|
||||
|
||||
spc, err := s.spaceService.GetSpace(ctx, spaceID)
|
||||
spc, err := s.spaceService.Get(ctx, spaceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get space: %w", err)
|
||||
}
|
||||
|
@ -197,7 +206,7 @@ func (s *service) RegisterStaticSource(src Source) error {
|
|||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.staticIds[src.Id()] = src
|
||||
err := s.spaceService.StoreSpaceID(src.Id(), src.SpaceID())
|
||||
err := s.storageService.BindSpaceID(src.SpaceID(), src.Id())
|
||||
if err != nil {
|
||||
return fmt.Errorf("store space id for object: %w", err)
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
)
|
||||
|
||||
|
@ -83,7 +83,7 @@ type sourceDeps struct {
|
|||
|
||||
coreService core.Service
|
||||
accountService accountservice.Service
|
||||
spaceService space.Service
|
||||
spaceService spacecore.SpaceCoreService
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
fileService files.Service
|
||||
systemObjectService system_object.Service
|
||||
|
@ -125,7 +125,7 @@ type source struct {
|
|||
coreService core.Service
|
||||
fileService files.Service
|
||||
accountService accountservice.Service
|
||||
spaceService space.Service
|
||||
spaceService spacecore.SpaceCoreService
|
||||
sbtProvider typeprovider.SmartBlockTypeProvider
|
||||
systemObjectService system_object.Service
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ func checkChangeSize(data []byte, maxSize int) error {
|
|||
}
|
||||
|
||||
func (s *source) ListIds() (ids []string, err error) {
|
||||
spc, err := s.spaceService.GetSpace(context.Background(), s.spaceID)
|
||||
spc, err := s.spaceService.Get(context.Background(), s.spaceID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
)
|
||||
|
||||
var log = logging.Logger("anytype-mw-configfetcher")
|
||||
|
@ -47,6 +47,10 @@ type ConfigFetcher interface {
|
|||
Refetch()
|
||||
}
|
||||
|
||||
type personalSpaceIDGetter interface {
|
||||
PersonalSpaceID() string
|
||||
}
|
||||
|
||||
type configFetcher struct {
|
||||
store objectstore.ObjectStore
|
||||
eventSender event.Sender
|
||||
|
@ -55,7 +59,8 @@ type configFetcher struct {
|
|||
|
||||
periodicSync periodicsync.PeriodicSync
|
||||
client coordinatorclient.CoordinatorClient
|
||||
spaceService space.Service
|
||||
spaceService spacecore.SpaceCoreService
|
||||
account personalSpaceIDGetter
|
||||
wallet wallet.Wallet
|
||||
lastStatus model.AccountStatusType
|
||||
}
|
||||
|
@ -91,7 +96,8 @@ func (c *configFetcher) Init(a *app.App) (err error) {
|
|||
c.eventSender = a.MustComponent(event.CName).(event.Sender)
|
||||
c.periodicSync = periodicsync.NewPeriodicSync(refreshIntervalSecs, timeout, c.updateStatus, logger.CtxLogger{Logger: log.Desugar()})
|
||||
c.client = a.MustComponent(coordinatorclient.CName).(coordinatorclient.CoordinatorClient)
|
||||
c.spaceService = a.MustComponent(space.CName).(space.Service)
|
||||
c.spaceService = a.MustComponent(spacecore.CName).(spacecore.SpaceCoreService)
|
||||
c.account = app.MustComponent[personalSpaceIDGetter](a)
|
||||
c.fetched = make(chan struct{})
|
||||
return nil
|
||||
}
|
||||
|
@ -106,9 +112,10 @@ func (c *configFetcher) updateStatus(ctx context.Context) (err error) {
|
|||
close(c.fetched)
|
||||
})
|
||||
}()
|
||||
res, err := c.client.StatusCheck(ctx, c.spaceService.AccountId())
|
||||
personalSpaceID := c.account.PersonalSpaceID()
|
||||
res, err := c.client.StatusCheck(ctx, personalSpaceID)
|
||||
if err == coordinatorproto.ErrSpaceNotExists {
|
||||
sp, cErr := c.spaceService.GetSpace(ctx, c.spaceService.AccountId())
|
||||
sp, cErr := c.spaceService.Get(ctx, personalSpaceID)
|
||||
if cErr != nil {
|
||||
return cErr
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/converter"
|
||||
"github.com/anyproto/anytype-heart/core/system_object"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
)
|
||||
|
||||
func NewMultiConverter(format int, _ typeprovider.SmartBlockTypeProvider, _ system_object.Service) converter.MultiConverter {
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
|
16
core/core.go
16
core/core.go
|
@ -17,7 +17,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
utildebug "github.com/anyproto/anytype-heart/util/debug"
|
||||
)
|
||||
|
||||
|
@ -64,13 +63,6 @@ func (mw *Middleware) getBlockService() (bs *block.Service, err error) {
|
|||
return nil, ErrNotLoggedIn
|
||||
}
|
||||
|
||||
func (mw *Middleware) getAccountService() (a space.Service, err error) {
|
||||
if a := mw.applicationService.GetApp(); a != nil {
|
||||
return a.MustComponent(space.CName).(space.Service), nil
|
||||
}
|
||||
return nil, ErrNotLoggedIn
|
||||
}
|
||||
|
||||
func (mw *Middleware) doBlockService(f func(bs *block.Service) error) (err error) {
|
||||
bs, err := mw.getBlockService()
|
||||
if err != nil {
|
||||
|
@ -99,14 +91,6 @@ func requireApp(a *app.App) {
|
|||
}
|
||||
}
|
||||
|
||||
func (mw *Middleware) doAccountService(f func(a space.Service) error) (err error) {
|
||||
bs, err := mw.getAccountService()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return f(bs)
|
||||
}
|
||||
|
||||
func (mw *Middleware) GetAnytype() core.Service {
|
||||
if a := mw.applicationService.GetApp(); a != nil {
|
||||
return a.MustComponent("anytype").(core.Service)
|
||||
|
|
|
@ -59,7 +59,7 @@ func (mw *Middleware) DebugTreeHeads(cctx context.Context, req *pb.RpcDebugTreeH
|
|||
}
|
||||
|
||||
dbg := app.MustComponent(debug.CName).(debug.Debug)
|
||||
treeInfo, err := dbg.TreeHeads(req.TreeId)
|
||||
treeInfo, err := dbg.TreeHeads(cctx, req.TreeId)
|
||||
if err != nil {
|
||||
return response(err, debug.TreeInfo{})
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ func (mw *Middleware) DebugSpaceSummary(cctx context.Context, req *pb.RpcDebugSp
|
|||
return response(ErrNotLoggedIn, debug.SpaceSummary{})
|
||||
}
|
||||
dbg := app.MustComponent(debug.CName).(debug.Debug)
|
||||
spaceSummary, err := dbg.SpaceSummary()
|
||||
spaceSummary, err := dbg.SpaceSummary(cctx, req.SpaceId)
|
||||
if err != nil {
|
||||
return response(err, debug.SpaceSummary{})
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ func (mw *Middleware) DebugExportLocalstore(cctx context.Context, req *pb.RpcDeb
|
|||
)
|
||||
err = mw.doBlockService(func(s *block.Service) error {
|
||||
dbg := mw.applicationService.GetApp().MustComponent(debug.CName).(debug.Debug)
|
||||
path, err = dbg.DumpLocalstore(req.SpaceId, req.DocIds, req.Path)
|
||||
path, err = dbg.DumpLocalstore(cctx, req.SpaceId, req.DocIds, req.Path)
|
||||
return err
|
||||
})
|
||||
return response(path, err)
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
|
@ -36,16 +37,16 @@ func New() Debug {
|
|||
type Debug interface {
|
||||
app.Component
|
||||
DumpTree(ctx context.Context, objectID string, path string, anonymize bool, withSvg bool) (filename string, err error)
|
||||
DumpLocalstore(spaceID string, objectIds []string, path string) (filename string, err error)
|
||||
SpaceSummary() (summary SpaceSummary, err error)
|
||||
TreeHeads(id string) (info TreeInfo, err error)
|
||||
DumpLocalstore(ctx context.Context, spaceID string, objectIds []string, path string) (filename string, err error)
|
||||
SpaceSummary(ctx context.Context, spaceID string) (summary SpaceSummary, err error)
|
||||
TreeHeads(ctx context.Context, id string) (info TreeInfo, err error)
|
||||
}
|
||||
|
||||
type debug struct {
|
||||
block *block.Service
|
||||
store objectstore.ObjectStore
|
||||
clientService space.Service
|
||||
spaceService space.Service
|
||||
block *block.Service
|
||||
store objectstore.ObjectStore
|
||||
spaceService space.SpaceService
|
||||
resolver idresolver.Resolver
|
||||
|
||||
server *http.Server
|
||||
}
|
||||
|
@ -56,9 +57,9 @@ type Debuggable interface {
|
|||
|
||||
func (d *debug) Init(a *app.App) (err error) {
|
||||
d.store = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
d.clientService = a.MustComponent(space.CName).(space.Service)
|
||||
d.block = a.MustComponent(block.CName).(*block.Service)
|
||||
d.spaceService = app.MustComponent[space.Service](a)
|
||||
d.spaceService = app.MustComponent[space.SpaceService](a)
|
||||
d.resolver = app.MustComponent[idresolver.Resolver](a)
|
||||
|
||||
d.initHandlers(a)
|
||||
return nil
|
||||
|
@ -123,12 +124,12 @@ type SpaceSummary struct {
|
|||
TreeInfos []TreeInfo
|
||||
}
|
||||
|
||||
func (d *debug) SpaceSummary() (summary SpaceSummary, err error) {
|
||||
spc, err := d.clientService.AccountSpace(context.Background())
|
||||
func (d *debug) SpaceSummary(ctx context.Context, spaceID string) (summary SpaceSummary, err error) {
|
||||
spc, err := d.spaceService.Get(ctx, spaceID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
summary.SpaceId = spc.Id()
|
||||
summary.SpaceId = spaceID
|
||||
for _, t := range spc.DebugAllHeads() {
|
||||
summary.TreeInfos = append(summary.TreeInfos, TreeInfo{
|
||||
Heads: t.Heads,
|
||||
|
@ -138,42 +139,45 @@ func (d *debug) SpaceSummary() (summary SpaceSummary, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (d *debug) TreeHeads(id string) (info TreeInfo, err error) {
|
||||
spc, err := d.clientService.AccountSpace(context.Background())
|
||||
func (d *debug) TreeHeads(ctx context.Context, id string) (info TreeInfo, err error) {
|
||||
spcID, err := d.resolver.ResolveSpaceID(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tree, err := spc.TreeBuilder().BuildHistoryTree(context.Background(), id, objecttreebuilder.HistoryTreeOpts{})
|
||||
spc, err := d.spaceService.Get(ctx, spcID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tree, err := spc.TreeBuilder().BuildHistoryTree(ctx, id, objecttreebuilder.HistoryTreeOpts{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
info = TreeInfo{
|
||||
Id: id,
|
||||
Heads: tree.Heads(),
|
||||
SpaceId: spc.Id(),
|
||||
SpaceId: spcID,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *debug) DumpTree(ctx context.Context, objectID string, path string, anonymize bool, withSvg bool) (filename string, err error) {
|
||||
// 0 - get space and tree
|
||||
spc, err := d.clientService.AccountSpace(context.Background())
|
||||
// 0 - get space
|
||||
spcID, err := d.resolver.ResolveSpaceID(objectID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tree, err := spc.TreeBuilder().BuildHistoryTree(context.Background(), objectID, objecttreebuilder.HistoryTreeOpts{BuildFullTree: true})
|
||||
spc, err := d.spaceService.Get(ctx, spcID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tree, err := spc.TreeBuilder().BuildHistoryTree(ctx, objectID, objecttreebuilder.HistoryTreeOpts{BuildFullTree: true})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 1 - create ZIP file
|
||||
// <path>/at.dbg.bafkudtugh626rrqzah3kam4yj4lqbaw4bjayn2rz4ah4n5fpayppbvmq.20220322.121049.23.zip
|
||||
spaceID, err := d.spaceService.ResolveSpaceID(objectID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
exporter := &treeExporter{s: d.store, anonymized: anonymize, id: domain.FullID{
|
||||
SpaceID: spaceID,
|
||||
SpaceID: spcID,
|
||||
ObjectID: objectID,
|
||||
}}
|
||||
zipFilename, err := exporter.Export(ctx, path, tree)
|
||||
|
@ -208,7 +212,7 @@ func (d *debug) DumpTree(ctx context.Context, objectID string, path string, anon
|
|||
return zipFilename, nil
|
||||
}
|
||||
|
||||
func (d *debug) DumpLocalstore(spaceID string, objIds []string, path string) (filename string, err error) {
|
||||
func (d *debug) DumpLocalstore(ctx context.Context, spaceID string, objIds []string, path string) (filename string, err error) {
|
||||
if len(objIds) == 0 {
|
||||
objIds, err = d.store.ListIds()
|
||||
if err != nil {
|
||||
|
|
|
@ -19,6 +19,7 @@ var smartBlockTypeToKey = map[smartblock.SmartBlockType]string{
|
|||
smartblock.SmartBlockTypeArchive: "archive",
|
||||
smartblock.SmartBlockTypeProfilePage: "profile",
|
||||
smartblock.SmartBlockTypeWidget: "widget",
|
||||
smartblock.SmartBlockTypeSpaceView: "spaceview",
|
||||
}
|
||||
|
||||
// UniqueKey is unique key composed of two parts: smartblock type and internal key.
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
package files
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
ipld "github.com/ipfs/go-ipld-format"
|
||||
)
|
||||
|
||||
// Test dag. Copied from github.com/ipfs/go-ipld-format tests
|
||||
type testDag struct {
|
||||
mu sync.Mutex
|
||||
nodes map[string]ipld.Node
|
||||
}
|
||||
|
||||
func newTestDag() *testDag {
|
||||
return &testDag{nodes: make(map[string]ipld.Node)}
|
||||
}
|
||||
|
||||
func (d *testDag) Get(ctx context.Context, cid cid.Cid) (ipld.Node, error) {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
if n, ok := d.nodes[cid.KeyString()]; ok {
|
||||
return n, nil
|
||||
}
|
||||
return nil, ipld.ErrNotFound{Cid: cid}
|
||||
}
|
||||
|
||||
func (d *testDag) GetMany(ctx context.Context, cids []cid.Cid) <-chan *ipld.NodeOption {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
out := make(chan *ipld.NodeOption, len(cids))
|
||||
for _, c := range cids {
|
||||
if n, ok := d.nodes[c.KeyString()]; ok {
|
||||
out <- &ipld.NodeOption{Node: n}
|
||||
} else {
|
||||
out <- &ipld.NodeOption{Err: ipld.ErrNotFound{c}}
|
||||
}
|
||||
}
|
||||
close(out)
|
||||
return out
|
||||
}
|
||||
|
||||
func (d *testDag) Add(ctx context.Context, node ipld.Node) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
d.nodes[node.Cid().KeyString()] = node
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *testDag) AddMany(ctx context.Context, nodes []ipld.Node) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
for _, n := range nodes {
|
||||
d.nodes[n.Cid().KeyString()] = n
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *testDag) Remove(ctx context.Context, c cid.Cid) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
delete(d.nodes, c.KeyString())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *testDag) RemoveMany(ctx context.Context, cids []cid.Cid) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
for _, c := range cids {
|
||||
delete(d.nodes, c.KeyString())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ ipld.DAGService = new(testDag)
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/multiformats/go-base32"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/filestorage"
|
||||
"github.com/anyproto/anytype-heart/core/filestorage/filesync"
|
||||
|
@ -40,7 +41,6 @@ import (
|
|||
m "github.com/anyproto/anytype-heart/pkg/lib/mill"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/mill/schema"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/storage"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
@ -75,7 +75,7 @@ type service struct {
|
|||
commonFile fileservice.FileService
|
||||
fileSync filesync.FileSync
|
||||
dagService ipld.DAGService
|
||||
spaceService space.Service
|
||||
resolver idresolver.Resolver
|
||||
fileStorage filestorage.FileStorage
|
||||
syncStatusWatcher SyncStatusWatcher
|
||||
objectStore objectstore.ObjectStore
|
||||
|
@ -90,11 +90,11 @@ func (s *service) Init(a *app.App) (err error) {
|
|||
s.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
s.commonFile = app.MustComponent[fileservice.FileService](a)
|
||||
s.fileSync = app.MustComponent[filesync.FileSync](a)
|
||||
s.spaceService = app.MustComponent[space.Service](a)
|
||||
s.coreService = app.MustComponent[core.Service](a)
|
||||
|
||||
s.dagService = s.commonFile.DAGService()
|
||||
s.fileStorage = app.MustComponent[filestorage.FileStorage](a)
|
||||
s.resolver = app.MustComponent[idresolver.Resolver](a)
|
||||
s.objectStore = app.MustComponent[objectstore.ObjectStore](a)
|
||||
s.syncStatusWatcher = app.MustComponent[SyncStatusWatcher](a)
|
||||
return nil
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/datastore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/space/mock_space"
|
||||
"github.com/anyproto/anytype-heart/tests/testutil"
|
||||
)
|
||||
|
||||
|
@ -29,13 +28,27 @@ type dummySyncStatusWatcher struct{}
|
|||
func (w *dummySyncStatusWatcher) Watch(spaceID string, id string, fileFunc func() []string) (new bool, err error) {
|
||||
return false, nil
|
||||
}
|
||||
func (w *dummySyncStatusWatcher) Init(a *app.App) error { return nil }
|
||||
func (w *dummySyncStatusWatcher) Name() string { return "dummySyncStatusWatcher" }
|
||||
|
||||
func (w *dummySyncStatusWatcher) Init(a *app.App) error {
|
||||
return nil
|
||||
type personalSpaceIdStub struct {
|
||||
personalSpaceId string
|
||||
}
|
||||
|
||||
func (w *dummySyncStatusWatcher) Name() string {
|
||||
return "dummySyncStatusWatcher"
|
||||
func (s *personalSpaceIdStub) Name() string { return "personalSpaceIdStub" }
|
||||
func (s *personalSpaceIdStub) Init(a *app.App) error { return nil }
|
||||
func (s *personalSpaceIdStub) PersonalSpaceID() string {
|
||||
return s.personalSpaceId
|
||||
}
|
||||
|
||||
type spaceResolverStub struct {
|
||||
spaceId string
|
||||
}
|
||||
|
||||
func (s *spaceResolverStub) Name() string { return "spaceResolverStub" }
|
||||
func (s *spaceResolverStub) Init(a *app.App) error { return nil }
|
||||
func (s *spaceResolverStub) ResolveSpaceID(objectID string) (string, error) {
|
||||
return s.spaceId, nil
|
||||
}
|
||||
|
||||
func TestFileAdd(t *testing.T) {
|
||||
|
@ -50,8 +63,8 @@ func TestFileAdd(t *testing.T) {
|
|||
fileSyncService := filesync.New()
|
||||
|
||||
spaceId := "space1"
|
||||
spaceService := mock_space.NewMockService(t)
|
||||
spaceService.EXPECT().AccountId().Return(spaceId).Maybe()
|
||||
personalSpaceIdGetter := &personalSpaceIdStub{personalSpaceId: spaceId}
|
||||
spaceIdResolver := &spaceResolverStub{spaceId: spaceId}
|
||||
|
||||
coreService := mock_core.NewMockService(t)
|
||||
objectStore := objectstore.NewStoreFixture(t)
|
||||
|
@ -64,11 +77,12 @@ func TestFileAdd(t *testing.T) {
|
|||
a.Register(filestore.New())
|
||||
a.Register(commonFileService)
|
||||
a.Register(fileSyncService)
|
||||
a.Register(testutil.PrepareRunnableMock(ctx, a, spaceService))
|
||||
a.Register(testutil.PrepareRunnableMock(ctx, a, coreService))
|
||||
a.Register(testutil.PrepareMock(a, eventSender))
|
||||
a.Register(testutil.PrepareMock(ctx, a, coreService))
|
||||
a.Register(testutil.PrepareMock(ctx, a, eventSender))
|
||||
a.Register(blockStorage)
|
||||
a.Register(objectStore)
|
||||
a.Register(personalSpaceIdGetter)
|
||||
a.Register(spaceIdResolver)
|
||||
a.Register(&dummySyncStatusWatcher{})
|
||||
a.Register(rpcStorage)
|
||||
err := a.Start(ctx)
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
)
|
||||
|
||||
func (s *service) FileOffload(ctx context.Context, fileID string, includeNotPinned bool) (totalSize uint64, err error) {
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(fileID)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(fileID)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("resolve spaceID for file %s: %w", fileID, err)
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func (s *service) FileListOffload(ctx context.Context, fileIDs []string, include
|
|||
}
|
||||
|
||||
for _, fileID := range fileIDs {
|
||||
spaceID, err := s.spaceService.ResolveSpaceID(fileID)
|
||||
spaceID, err := s.resolver.ResolveSpaceID(fileID)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("resolve spaceID for file %s: %w", fileID, err)
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/filestorage/rpcstore"
|
||||
"github.com/anyproto/anytype-heart/core/wallet"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/datastore"
|
||||
"github.com/anyproto/anytype-heart/space/storage"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/storage"
|
||||
)
|
||||
|
||||
const CName = fileblockstore.CName
|
||||
|
|
|
@ -13,11 +13,10 @@ import (
|
|||
reflect "reflect"
|
||||
|
||||
app "github.com/anyproto/any-sync/app"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
|
||||
localstore "github.com/anyproto/anytype-heart/pkg/lib/localstore"
|
||||
filestore "github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
storage "github.com/anyproto/anytype-heart/pkg/lib/pb/storage"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockFileStore is a mock of FileStore interface.
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/datastore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
)
|
||||
|
||||
const CName = "filesync"
|
||||
|
@ -54,23 +53,27 @@ type QueueInfo struct {
|
|||
RemovingQueue []*QueueItem
|
||||
}
|
||||
|
||||
type personalSpaceIDGetter interface {
|
||||
PersonalSpaceID() string
|
||||
}
|
||||
|
||||
type SyncStatus struct {
|
||||
QueueLen int
|
||||
}
|
||||
|
||||
type fileSync struct {
|
||||
dbProvider datastore.Datastore
|
||||
rpcStore rpcstore.RpcStore
|
||||
queue *fileSyncStore
|
||||
loopCtx context.Context
|
||||
loopCancel context.CancelFunc
|
||||
uploadPingCh chan struct{}
|
||||
removePingCh chan struct{}
|
||||
dagService ipld.DAGService
|
||||
fileStore filestore.FileStore
|
||||
eventSender event.Sender
|
||||
onUpload func(spaceID, fileID string) error
|
||||
spaceService space.Service
|
||||
dbProvider datastore.Datastore
|
||||
rpcStore rpcstore.RpcStore
|
||||
queue *fileSyncStore
|
||||
loopCtx context.Context
|
||||
loopCancel context.CancelFunc
|
||||
uploadPingCh chan struct{}
|
||||
removePingCh chan struct{}
|
||||
dagService ipld.DAGService
|
||||
fileStore filestore.FileStore
|
||||
eventSender event.Sender
|
||||
onUpload func(spaceID, fileID string) error
|
||||
personalIDGetter personalSpaceIDGetter
|
||||
|
||||
spaceStatsLock sync.Mutex
|
||||
spaceStats map[string]SpaceStat
|
||||
|
@ -89,7 +92,7 @@ func (f *fileSync) Init(a *app.App) (err error) {
|
|||
f.rpcStore = a.MustComponent(rpcstore.CName).(rpcstore.Service).NewStore()
|
||||
f.dagService = a.MustComponent(fileservice.CName).(fileservice.FileService).DAGService()
|
||||
f.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
f.spaceService = app.MustComponent[space.Service](a)
|
||||
f.personalIDGetter = app.MustComponent[personalSpaceIDGetter](a)
|
||||
f.eventSender = app.MustComponent[event.Sender](a)
|
||||
f.removePingCh = make(chan struct{})
|
||||
f.uploadPingCh = make(chan struct{})
|
||||
|
@ -128,7 +131,8 @@ func (f *fileSync) Run(ctx context.Context) (err error) {
|
|||
|
||||
func (f *fileSync) precacheSpaceStats() {
|
||||
// TODO multi-spaces: init for each space: GO-1681
|
||||
spaceID := f.spaceService.AccountId()
|
||||
// TODO: [MR] adapt to multi-spaces
|
||||
spaceID := f.personalIDGetter.PersonalSpaceID()
|
||||
_, err := f.SpaceStat(context.Background(), spaceID)
|
||||
if err != nil {
|
||||
// Don't confuse users with 0B limit in case of error, so set default 1GB limit
|
||||
|
@ -136,7 +140,7 @@ func (f *fileSync) precacheSpaceStats() {
|
|||
SpaceId: spaceID,
|
||||
BytesLimit: 1024 * 1024 * 1024, // 1 GB
|
||||
})
|
||||
log.Error("can't init space stats", zap.String("spaceID", f.spaceService.AccountId()), zap.Error(err))
|
||||
log.Error("can't init space stats", zap.String("spaceID", f.personalIDGetter.PersonalSpaceID()), zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/anyproto/any-sync/commonfile/fileproto"
|
||||
"github.com/anyproto/any-sync/commonfile/fileservice"
|
||||
"github.com/anyproto/any-sync/commonspace/syncstatus"
|
||||
"github.com/dgraph-io/badger/v3"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/samber/lo"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
@ -29,8 +28,6 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/datastore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/storage"
|
||||
"github.com/anyproto/anytype-heart/space/mock_space"
|
||||
"github.com/anyproto/anytype-heart/tests/testutil"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
@ -81,6 +78,16 @@ func TestFileSync_RemoveFile(t *testing.T) {
|
|||
fx.waitEmptyQueue(t, time.Second*5)
|
||||
}
|
||||
|
||||
type personalSpaceIdStub struct {
|
||||
personalSpaceId string
|
||||
}
|
||||
|
||||
func (s *personalSpaceIdStub) Name() string { return "personalSpaceIdStub" }
|
||||
func (s *personalSpaceIdStub) Init(a *app.App) error { return nil }
|
||||
func (s *personalSpaceIdStub) PersonalSpaceID() string {
|
||||
return s.personalSpaceId
|
||||
}
|
||||
|
||||
func newFixture(t *testing.T) *fixture {
|
||||
fx := &fixture{
|
||||
FileSync: New(),
|
||||
|
@ -88,12 +95,6 @@ func newFixture(t *testing.T) *fixture {
|
|||
ctrl: gomock.NewController(t),
|
||||
a: new(app.App),
|
||||
}
|
||||
var err error
|
||||
bp := &badgerProvider{}
|
||||
fx.tmpDir, err = os.MkdirTemp("", "*")
|
||||
require.NoError(t, err)
|
||||
bp.db, err = badger.Open(badger.DefaultOptions(fx.tmpDir))
|
||||
require.NoError(t, err)
|
||||
|
||||
fx.rpcStore = mock_rpcstore.NewMockRpcStore(fx.ctrl)
|
||||
fx.rpcStore.EXPECT().SpaceInfo(gomock.Any(), "space1").Return(&fileproto.SpaceInfoResponse{LimitBytes: 2 * 1024 * 1024}, nil).AnyTimes()
|
||||
|
@ -110,20 +111,21 @@ func newFixture(t *testing.T) *fixture {
|
|||
fileStoreMock.EXPECT().Close(gomock.Any()).AnyTimes()
|
||||
fx.fileStoreMock = fileStoreMock
|
||||
|
||||
spaceService := mock_space.NewMockService(t)
|
||||
spaceService.EXPECT().AccountId().Return("space1").Maybe()
|
||||
personalSpaceIdGetter := &personalSpaceIdStub{personalSpaceId: "space1"}
|
||||
|
||||
sender := mock_event.NewMockSender(t)
|
||||
sender.EXPECT().Name().Return("event")
|
||||
sender.EXPECT().Init(mock.Anything).Return(nil)
|
||||
sender.EXPECT().Broadcast(mock.Anything).Return().Maybe()
|
||||
|
||||
fx.a.Register(fx.fileService).
|
||||
Register(filestorage.NewInMemory()).
|
||||
Register(bp).
|
||||
Register(datastore.NewInMemory()).
|
||||
Register(mockRpcStoreService).
|
||||
Register(fx.FileSync).
|
||||
Register(fileStoreMock).
|
||||
Register(testutil.PrepareRunnableMock(ctx, fx.a, spaceService)).
|
||||
Register(testutil.PrepareMock(fx.a, sender))
|
||||
Register(personalSpaceIdGetter).
|
||||
Register(sender)
|
||||
require.NoError(t, fx.a.Start(ctx))
|
||||
return fx
|
||||
}
|
||||
|
@ -155,31 +157,3 @@ func (f *fixture) Finish(t *testing.T) {
|
|||
defer os.RemoveAll(f.tmpDir)
|
||||
require.NoError(t, f.a.Close(ctx))
|
||||
}
|
||||
|
||||
type badgerProvider struct {
|
||||
db *badger.DB
|
||||
}
|
||||
|
||||
func (b *badgerProvider) Init(a *app.App) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *badgerProvider) Name() (name string) {
|
||||
return datastore.CName
|
||||
}
|
||||
|
||||
func (b *badgerProvider) Run(ctx context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *badgerProvider) Close(ctx context.Context) (err error) {
|
||||
return b.db.Close()
|
||||
}
|
||||
|
||||
func (b *badgerProvider) LocalStorage() (*badger.DB, error) {
|
||||
return b.db, nil
|
||||
}
|
||||
|
||||
func (b *badgerProvider) SpaceStorage() (*badger.DB, error) {
|
||||
return b.db, nil
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/anyproto/any-sync/commonfile/fileproto/fileprotoerr"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/anyproto/anytype-heart/space/storage"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/storage"
|
||||
)
|
||||
|
||||
type rpcHandler struct {
|
||||
|
|
|
@ -14,11 +14,10 @@ import (
|
|||
|
||||
app "github.com/anyproto/any-sync/app"
|
||||
fileproto "github.com/anyproto/any-sync/commonfile/fileproto"
|
||||
rpcstore "github.com/anyproto/anytype-heart/core/filestorage/rpcstore"
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
|
||||
rpcstore "github.com/anyproto/anytype-heart/core/filestorage/rpcstore"
|
||||
)
|
||||
|
||||
// MockService is a mock of Service interface.
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/anyproto/any-sync/net/pool"
|
||||
"github.com/anyproto/any-sync/nodeconf"
|
||||
|
||||
"github.com/anyproto/anytype-heart/space/peerstore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/peerstore"
|
||||
)
|
||||
|
||||
const CName = "common.commonfile.rpcstore"
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"github.com/anyproto/anytype-heart/space/peerstore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/peerstore"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/history"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
|
@ -36,7 +37,8 @@ func (mw *Middleware) HistoryShowVersion(cctx context.Context, req *pb.RpcHistor
|
|||
)
|
||||
if err = mw.doBlockService(func(bs *block.Service) (err error) {
|
||||
hs := mw.applicationService.GetApp().MustComponent(history.CName).(history.History)
|
||||
spaceID, err := bs.ResolveSpaceID(req.ObjectId)
|
||||
res := mw.applicationService.GetApp().MustComponent(idresolver.CName).(idresolver.Resolver)
|
||||
spaceID, err := res.ResolveSpaceID(req.ObjectId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -74,7 +76,8 @@ func (mw *Middleware) HistoryGetVersions(cctx context.Context, req *pb.RpcHistor
|
|||
)
|
||||
if err = mw.doBlockService(func(bs *block.Service) (err error) {
|
||||
hs := mw.applicationService.GetApp().MustComponent(history.CName).(history.History)
|
||||
spaceID, err := bs.ResolveSpaceID(req.ObjectId)
|
||||
res := mw.applicationService.GetApp().MustComponent(idresolver.CName).(idresolver.Resolver)
|
||||
spaceID, err := res.ResolveSpaceID(req.ObjectId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
@ -105,7 +108,8 @@ func (mw *Middleware) HistorySetVersion(cctx context.Context, req *pb.RpcHistory
|
|||
}
|
||||
return response(mw.doBlockService(func(bs *block.Service) (err error) {
|
||||
hs := mw.applicationService.GetApp().MustComponent(history.CName).(history.History)
|
||||
spaceID, err := bs.ResolveSpaceID(req.ObjectId)
|
||||
res := mw.applicationService.GetApp().MustComponent(idresolver.CName).(idresolver.Resolver)
|
||||
spaceID, err := res.ResolveSpaceID(req.ObjectId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve spaceID: %w", err)
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
)
|
||||
|
@ -49,18 +49,18 @@ type History interface {
|
|||
|
||||
type history struct {
|
||||
a core.Service
|
||||
picker block.Picker
|
||||
picker block.ObjectGetter
|
||||
objectStore objectstore.ObjectStore
|
||||
systemObjectService system_object.Service
|
||||
spaceService space.Service
|
||||
spaceService spacecore.SpaceCoreService
|
||||
}
|
||||
|
||||
func (h *history) Init(a *app.App) (err error) {
|
||||
h.a = a.MustComponent(core.CName).(core.Service)
|
||||
h.picker = app.MustComponent[block.Picker](a)
|
||||
h.picker = app.MustComponent[block.ObjectGetter](a)
|
||||
h.objectStore = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
h.systemObjectService = a.MustComponent(system_object.CName).(system_object.Service)
|
||||
h.spaceService = a.MustComponent(space.CName).(space.Service)
|
||||
h.spaceService = a.MustComponent(spacecore.CName).(spacecore.SpaceCoreService)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,7 @@ func (h *history) SetVersion(id domain.FullID, versionId string) (err error) {
|
|||
}
|
||||
|
||||
func (h *history) treeWithId(id domain.FullID, beforeId string, includeBeforeId bool) (ht objecttree.HistoryTree, sbt smartblock.SmartBlockType, err error) {
|
||||
spc, err := h.spaceService.GetSpace(context.Background(), id.SpaceID)
|
||||
spc, err := h.spaceService.Get(context.Background(), id.SpaceID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -75,7 +75,6 @@ func (i *indexer) runFullTextIndexer() {
|
|||
func (i *indexer) prepareSearchDocument(id string) (ftDoc ftsearch.SearchDoc, err error) {
|
||||
// ctx := context.WithValue(context.Background(), ocache.CacheTimeout, cacheTimeout)
|
||||
ctx := context.WithValue(context.Background(), metrics.CtxKeyEntrypoint, "index_fulltext")
|
||||
|
||||
err = block.DoContext(i.picker, ctx, id, func(sb smartblock2.SmartBlock) error {
|
||||
sbType, err := i.typeProvider.Type(sb.SpaceID(), id)
|
||||
if err != nil {
|
||||
|
|
|
@ -10,25 +10,26 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/anyproto/any-sync/app"
|
||||
"github.com/anyproto/any-sync/commonspace/spacestorage"
|
||||
"github.com/gogo/protobuf/types"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/anytype/config"
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
smartblock2 "github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
editorsb "github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/source"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/files"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/filestore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/ftsearch"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/storage"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
)
|
||||
|
||||
|
@ -46,8 +47,10 @@ func New() Indexer {
|
|||
|
||||
type Indexer interface {
|
||||
ForceFTIndex()
|
||||
Index(ctx context.Context, info smartblock2.DocInfo, options ...smartblock2.IndexOption) error
|
||||
EnsurePreinstalledObjects(spaceID string) error
|
||||
StartFullTextIndex() error
|
||||
ReindexCommonObjects() error
|
||||
ReindexSpace(spaceID string) error
|
||||
Index(ctx context.Context, info editorsb.DocInfo, options ...editorsb.IndexOption) error
|
||||
app.ComponentRunnable
|
||||
}
|
||||
|
||||
|
@ -64,20 +67,19 @@ type objectCreator interface {
|
|||
) (ids []string, objects []*types.Struct, err error)
|
||||
}
|
||||
|
||||
type syncStarter interface {
|
||||
StartSync()
|
||||
type personalIDProvider interface {
|
||||
PersonalSpaceID() string
|
||||
}
|
||||
|
||||
type indexer struct {
|
||||
store objectstore.ObjectStore
|
||||
fileStore filestore.FileStore
|
||||
anytype core.Service
|
||||
source source.Service
|
||||
picker block.Picker
|
||||
ftsearch ftsearch.FTSearch
|
||||
objectCreator objectCreator
|
||||
syncStarter syncStarter
|
||||
fileService files.Service
|
||||
store objectstore.ObjectStore
|
||||
fileStore filestore.FileStore
|
||||
source source.Service
|
||||
picker block.ObjectGetter
|
||||
ftsearch ftsearch.FTSearch
|
||||
storageService storage.ClientStorage
|
||||
objectCreator objectCreator
|
||||
fileService files.Service
|
||||
|
||||
quit chan struct{}
|
||||
btHash Hasher
|
||||
|
@ -85,25 +87,28 @@ type indexer struct {
|
|||
forceFt chan struct{}
|
||||
|
||||
typeProvider typeprovider.SmartBlockTypeProvider
|
||||
spaceService space.Service
|
||||
spaceCore spacecore.SpaceCoreService
|
||||
provider personalIDProvider
|
||||
|
||||
indexedFiles *sync.Map
|
||||
reindexLogFields []zap.Field
|
||||
|
||||
flags reindexFlags
|
||||
}
|
||||
|
||||
func (i *indexer) Init(a *app.App) (err error) {
|
||||
i.newAccount = a.MustComponent(config.CName).(*config.Config).NewAccount
|
||||
i.anytype = a.MustComponent(core.CName).(core.Service)
|
||||
i.store = a.MustComponent(objectstore.CName).(objectstore.ObjectStore)
|
||||
i.storageService = a.MustComponent(spacestorage.CName).(storage.ClientStorage)
|
||||
i.typeProvider = a.MustComponent(typeprovider.CName).(typeprovider.SmartBlockTypeProvider)
|
||||
i.source = a.MustComponent(source.CName).(source.Service)
|
||||
i.btHash = a.MustComponent("builtintemplate").(Hasher)
|
||||
i.fileStore = app.MustComponent[filestore.FileStore](a)
|
||||
i.ftsearch = app.MustComponent[ftsearch.FTSearch](a)
|
||||
i.objectCreator = app.MustComponent[objectCreator](a)
|
||||
i.syncStarter = app.MustComponent[syncStarter](a)
|
||||
i.picker = app.MustComponent[block.Picker](a)
|
||||
i.spaceService = app.MustComponent[space.Service](a)
|
||||
i.picker = app.MustComponent[block.ObjectGetter](a)
|
||||
i.spaceCore = app.MustComponent[spacecore.SpaceCoreService](a)
|
||||
i.provider = app.MustComponent[personalIDProvider](a)
|
||||
i.fileService = app.MustComponent[files.Service](a)
|
||||
i.quit = make(chan struct{})
|
||||
i.forceFt = make(chan struct{})
|
||||
|
@ -115,13 +120,13 @@ func (i *indexer) Name() (name string) {
|
|||
}
|
||||
|
||||
func (i *indexer) Run(context.Context) (err error) {
|
||||
return i.StartFullTextIndex()
|
||||
}
|
||||
|
||||
func (i *indexer) StartFullTextIndex() (err error) {
|
||||
if ftErr := i.ftInit(); ftErr != nil {
|
||||
log.Errorf("can't init ft: %v", ftErr)
|
||||
}
|
||||
err = i.reindexIfNeeded()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go i.ftLoop()
|
||||
return
|
||||
}
|
||||
|
@ -131,18 +136,22 @@ func (i *indexer) Close(ctx context.Context) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (i *indexer) Index(ctx context.Context, info smartblock2.DocInfo, options ...smartblock2.IndexOption) error {
|
||||
func (i *indexer) Index(ctx context.Context, info editorsb.DocInfo, options ...editorsb.IndexOption) error {
|
||||
// options are stored in smartblock pkg because of cyclic dependency :(
|
||||
startTime := time.Now()
|
||||
opts := &smartblock2.IndexOptions{}
|
||||
opts := &editorsb.IndexOptions{}
|
||||
for _, o := range options {
|
||||
o(opts)
|
||||
}
|
||||
err := i.storageService.BindSpaceID(info.SpaceID, info.Id)
|
||||
if err != nil {
|
||||
log.Error("failed to bind space id", zap.Error(err), zap.String("id", info.Id))
|
||||
return err
|
||||
}
|
||||
sbType, err := i.typeProvider.Type(info.SpaceID, info.Id)
|
||||
if err != nil {
|
||||
sbType = smartblock.SmartBlockTypePage
|
||||
}
|
||||
|
||||
headHashToIndex := headsHash(info.Heads)
|
||||
saveIndexedHash := func() {
|
||||
if headHashToIndex == "" {
|
||||
|
@ -262,13 +271,13 @@ func (i *indexer) indexLinkedFiles(ctx context.Context, spaceID string, fileHash
|
|||
if ok {
|
||||
return
|
||||
}
|
||||
storeErr := i.spaceService.StoreSpaceID(id, spaceID)
|
||||
if storeErr != nil {
|
||||
log.With("id", id).Errorf("failed to store space id: %v", storeErr)
|
||||
err := i.storageService.BindSpaceID(spaceID, id)
|
||||
if err != nil {
|
||||
log.Error("failed to bind space id", zap.Error(err), zap.String("id", id))
|
||||
return
|
||||
}
|
||||
// file's hash is id
|
||||
idxErr := i.reindexDoc(ctx, id)
|
||||
idxErr := i.reindexDoc(ctx, spaceID, id)
|
||||
if idxErr != nil && !errors.Is(idxErr, domain.ErrFileNotFound) {
|
||||
log.With("id", id).Errorf("failed to reindex file: %s", idxErr)
|
||||
}
|
||||
|
@ -280,14 +289,6 @@ func (i *indexer) indexLinkedFiles(ctx context.Context, spaceID string, fileHash
|
|||
}
|
||||
}
|
||||
|
||||
func (i *indexer) getObjectInfo(ctx context.Context, id string) (info smartblock2.DocInfo, err error) {
|
||||
err = block.DoContext(i.picker, ctx, id, func(sb smartblock2.SmartBlock) error {
|
||||
info = sb.GetDocInfo()
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func headsHash(heads []string) string {
|
||||
if len(heads) == 0 {
|
||||
return ""
|
||||
|
|
421
core/indexer/mock_indexer/mock_Indexer.go
Normal file
421
core/indexer/mock_indexer/mock_Indexer.go
Normal file
|
@ -0,0 +1,421 @@
|
|||
// Code generated by mockery v2.26.1. DO NOT EDIT.
|
||||
|
||||
package mock_indexer
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
app "github.com/anyproto/any-sync/app"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
smartblock "github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
)
|
||||
|
||||
// MockIndexer is an autogenerated mock type for the Indexer type
|
||||
type MockIndexer struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type MockIndexer_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockIndexer) EXPECT() *MockIndexer_Expecter {
|
||||
return &MockIndexer_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// Close provides a mock function with given fields: ctx
|
||||
func (_m *MockIndexer) Close(ctx context.Context) error {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockIndexer_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
|
||||
type MockIndexer_Close_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Close is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *MockIndexer_Expecter) Close(ctx interface{}) *MockIndexer_Close_Call {
|
||||
return &MockIndexer_Close_Call{Call: _e.mock.On("Close", ctx)}
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Close_Call) Run(run func(ctx context.Context)) *MockIndexer_Close_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Close_Call) Return(err error) *MockIndexer_Close_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Close_Call) RunAndReturn(run func(context.Context) error) *MockIndexer_Close_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ForceFTIndex provides a mock function with given fields:
|
||||
func (_m *MockIndexer) ForceFTIndex() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// MockIndexer_ForceFTIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ForceFTIndex'
|
||||
type MockIndexer_ForceFTIndex_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ForceFTIndex is a helper method to define mock.On call
|
||||
func (_e *MockIndexer_Expecter) ForceFTIndex() *MockIndexer_ForceFTIndex_Call {
|
||||
return &MockIndexer_ForceFTIndex_Call{Call: _e.mock.On("ForceFTIndex")}
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_ForceFTIndex_Call) Run(run func()) *MockIndexer_ForceFTIndex_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_ForceFTIndex_Call) Return() *MockIndexer_ForceFTIndex_Call {
|
||||
_c.Call.Return()
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_ForceFTIndex_Call) RunAndReturn(run func()) *MockIndexer_ForceFTIndex_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Index provides a mock function with given fields: ctx, info, options
|
||||
func (_m *MockIndexer) Index(ctx context.Context, info smartblock.DocInfo, options ...smartblock.IndexOption) error {
|
||||
_va := make([]interface{}, len(options))
|
||||
for _i := range options {
|
||||
_va[_i] = options[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, info)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, smartblock.DocInfo, ...smartblock.IndexOption) error); ok {
|
||||
r0 = rf(ctx, info, options...)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockIndexer_Index_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Index'
|
||||
type MockIndexer_Index_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Index is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - info smartblock.DocInfo
|
||||
// - options ...smartblock.IndexOption
|
||||
func (_e *MockIndexer_Expecter) Index(ctx interface{}, info interface{}, options ...interface{}) *MockIndexer_Index_Call {
|
||||
return &MockIndexer_Index_Call{Call: _e.mock.On("Index",
|
||||
append([]interface{}{ctx, info}, options...)...)}
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Index_Call) Run(run func(ctx context.Context, info smartblock.DocInfo, options ...smartblock.IndexOption)) *MockIndexer_Index_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]smartblock.IndexOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(smartblock.IndexOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(smartblock.DocInfo), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Index_Call) Return(_a0 error) *MockIndexer_Index_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Index_Call) RunAndReturn(run func(context.Context, smartblock.DocInfo, ...smartblock.IndexOption) error) *MockIndexer_Index_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Init provides a mock function with given fields: a
|
||||
func (_m *MockIndexer) Init(a *app.App) error {
|
||||
ret := _m.Called(a)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*app.App) error); ok {
|
||||
r0 = rf(a)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockIndexer_Init_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Init'
|
||||
type MockIndexer_Init_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Init is a helper method to define mock.On call
|
||||
// - a *app.App
|
||||
func (_e *MockIndexer_Expecter) Init(a interface{}) *MockIndexer_Init_Call {
|
||||
return &MockIndexer_Init_Call{Call: _e.mock.On("Init", a)}
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Init_Call) Run(run func(a *app.App)) *MockIndexer_Init_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(*app.App))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Init_Call) Return(err error) *MockIndexer_Init_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Init_Call) RunAndReturn(run func(*app.App) error) *MockIndexer_Init_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Name provides a mock function with given fields:
|
||||
func (_m *MockIndexer) Name() string {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func() string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockIndexer_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name'
|
||||
type MockIndexer_Name_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Name is a helper method to define mock.On call
|
||||
func (_e *MockIndexer_Expecter) Name() *MockIndexer_Name_Call {
|
||||
return &MockIndexer_Name_Call{Call: _e.mock.On("Name")}
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Name_Call) Run(run func()) *MockIndexer_Name_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Name_Call) Return(name string) *MockIndexer_Name_Call {
|
||||
_c.Call.Return(name)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Name_Call) RunAndReturn(run func() string) *MockIndexer_Name_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ReindexCommonObjects provides a mock function with given fields:
|
||||
func (_m *MockIndexer) ReindexCommonObjects() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockIndexer_ReindexCommonObjects_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReindexCommonObjects'
|
||||
type MockIndexer_ReindexCommonObjects_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ReindexCommonObjects is a helper method to define mock.On call
|
||||
func (_e *MockIndexer_Expecter) ReindexCommonObjects() *MockIndexer_ReindexCommonObjects_Call {
|
||||
return &MockIndexer_ReindexCommonObjects_Call{Call: _e.mock.On("ReindexCommonObjects")}
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_ReindexCommonObjects_Call) Run(run func()) *MockIndexer_ReindexCommonObjects_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_ReindexCommonObjects_Call) Return(_a0 error) *MockIndexer_ReindexCommonObjects_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_ReindexCommonObjects_Call) RunAndReturn(run func() error) *MockIndexer_ReindexCommonObjects_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ReindexSpace provides a mock function with given fields: spaceID
|
||||
func (_m *MockIndexer) ReindexSpace(spaceID string) error {
|
||||
ret := _m.Called(spaceID)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string) error); ok {
|
||||
r0 = rf(spaceID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockIndexer_ReindexSpace_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReindexSpace'
|
||||
type MockIndexer_ReindexSpace_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ReindexSpace is a helper method to define mock.On call
|
||||
// - spaceID string
|
||||
func (_e *MockIndexer_Expecter) ReindexSpace(spaceID interface{}) *MockIndexer_ReindexSpace_Call {
|
||||
return &MockIndexer_ReindexSpace_Call{Call: _e.mock.On("ReindexSpace", spaceID)}
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_ReindexSpace_Call) Run(run func(spaceID string)) *MockIndexer_ReindexSpace_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(string))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_ReindexSpace_Call) Return(_a0 error) *MockIndexer_ReindexSpace_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_ReindexSpace_Call) RunAndReturn(run func(string) error) *MockIndexer_ReindexSpace_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Run provides a mock function with given fields: ctx
|
||||
func (_m *MockIndexer) Run(ctx context.Context) error {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockIndexer_Run_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Run'
|
||||
type MockIndexer_Run_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// Run is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *MockIndexer_Expecter) Run(ctx interface{}) *MockIndexer_Run_Call {
|
||||
return &MockIndexer_Run_Call{Call: _e.mock.On("Run", ctx)}
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Run_Call) Run(run func(ctx context.Context)) *MockIndexer_Run_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Run_Call) Return(err error) *MockIndexer_Run_Call {
|
||||
_c.Call.Return(err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_Run_Call) RunAndReturn(run func(context.Context) error) *MockIndexer_Run_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// StartFullTextIndex provides a mock function with given fields:
|
||||
func (_m *MockIndexer) StartFullTextIndex() error {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func() error); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// MockIndexer_StartFullTextIndex_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StartFullTextIndex'
|
||||
type MockIndexer_StartFullTextIndex_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// StartFullTextIndex is a helper method to define mock.On call
|
||||
func (_e *MockIndexer_Expecter) StartFullTextIndex() *MockIndexer_StartFullTextIndex_Call {
|
||||
return &MockIndexer_StartFullTextIndex_Call{Call: _e.mock.On("StartFullTextIndex")}
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_StartFullTextIndex_Call) Run(run func()) *MockIndexer_StartFullTextIndex_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run()
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_StartFullTextIndex_Call) Return(_a0 error) *MockIndexer_StartFullTextIndex_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *MockIndexer_StartFullTextIndex_Call) RunAndReturn(run func() error) *MockIndexer_StartFullTextIndex_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewMockIndexer interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewMockIndexer creates a new instance of MockIndexer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewMockIndexer(t mockConstructorTestingTNewMockIndexer) *MockIndexer {
|
||||
mock := &MockIndexer{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/metrics"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
|
||||
smartblock2 "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
||||
|
@ -21,7 +22,6 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
|
||||
// ForceObjectsReindexCounter reindex thread-based objects
|
||||
ForceObjectsReindexCounter int32 = 8
|
||||
|
||||
|
@ -42,24 +42,38 @@ const (
|
|||
ForceFilestoreKeysReindexCounter int32 = 2
|
||||
)
|
||||
|
||||
func (i *indexer) reindexIfNeeded() error {
|
||||
checksums, err := i.store.GetChecksums()
|
||||
func (i *indexer) buildFlags(spaceID string) (reindexFlags, error) {
|
||||
var (
|
||||
checksums *model.ObjectStoreChecksums
|
||||
flags reindexFlags
|
||||
err error
|
||||
)
|
||||
if spaceID == "" {
|
||||
checksums, err = i.store.GetGlobalChecksums()
|
||||
} else {
|
||||
checksums, err = i.store.GetChecksums(spaceID)
|
||||
}
|
||||
if err != nil && !errors.Is(err, badger.ErrKeyNotFound) {
|
||||
return err
|
||||
return reindexFlags{}, err
|
||||
}
|
||||
if checksums == nil {
|
||||
// TODO: [MR] split object store checksums for space and common?
|
||||
checksums = &model.ObjectStoreChecksums{
|
||||
// do no add bundled relations checksums, because we want to index them for new accounts
|
||||
ObjectsForceReindexCounter: ForceObjectsReindexCounter,
|
||||
FilesForceReindexCounter: ForceFilesReindexCounter,
|
||||
IdxRebuildCounter: ForceIdxRebuildCounter,
|
||||
// per space
|
||||
ObjectsForceReindexCounter: ForceObjectsReindexCounter,
|
||||
// ?
|
||||
FilesForceReindexCounter: ForceFilesReindexCounter,
|
||||
// global
|
||||
IdxRebuildCounter: ForceIdxRebuildCounter,
|
||||
// per space
|
||||
FilestoreKeysForceReindexCounter: ForceFilestoreKeysReindexCounter,
|
||||
FulltextRebuild: ForceFulltextIndexCounter,
|
||||
BundledObjects: ForceBundledObjectsReindexCounter,
|
||||
// per space
|
||||
FulltextRebuild: ForceFulltextIndexCounter,
|
||||
// global
|
||||
BundledObjects: ForceBundledObjectsReindexCounter,
|
||||
}
|
||||
}
|
||||
|
||||
var flags reindexFlags
|
||||
if checksums.BundledRelations != bundle.RelationChecksum {
|
||||
flags.bundledRelations = true
|
||||
}
|
||||
|
@ -87,132 +101,38 @@ func (i *indexer) reindexIfNeeded() error {
|
|||
if checksums.IdxRebuildCounter != ForceIdxRebuildCounter {
|
||||
flags.enableAll()
|
||||
}
|
||||
|
||||
return i.reindex(flags)
|
||||
return flags, nil
|
||||
}
|
||||
|
||||
func (i *indexer) reindex(flags reindexFlags) (err error) {
|
||||
if flags.any() {
|
||||
log.Infof("start store reindex (%s)", flags.String())
|
||||
}
|
||||
|
||||
if flags.objects && flags.fileObjects {
|
||||
// files will be indexed within object indexing (see indexLinkedFiles)
|
||||
// because we need to do it in the background.
|
||||
// otherwise it will lead to the situation when files loading called from the reindex with DisableRemoteFlag
|
||||
// will be waiting for the linkedFiles background indexing without this flag
|
||||
flags.fileObjects = false
|
||||
}
|
||||
|
||||
if flags.fileKeys {
|
||||
err = i.fileStore.RemoveEmptyFileKeys()
|
||||
if err != nil {
|
||||
log.Errorf("reindex failed to RemoveEmptyFileKeys: %v", err.Error())
|
||||
} else {
|
||||
log.Infof("RemoveEmptyFileKeys filekeys succeed")
|
||||
}
|
||||
}
|
||||
|
||||
if flags.removeAllIndexedObjects {
|
||||
ids, err := i.store.ListIds()
|
||||
if err != nil {
|
||||
log.Errorf("reindex failed to get all ids(removeAllIndexedObjects): %v", err.Error())
|
||||
}
|
||||
for _, id := range ids {
|
||||
err = i.store.DeleteDetails(id)
|
||||
if err != nil {
|
||||
log.Errorf("reindex failed to delete details(removeAllIndexedObjects): %v", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
if flags.eraseIndexes {
|
||||
err = i.store.EraseIndexes()
|
||||
if err != nil {
|
||||
log.Errorf("reindex failed to erase indexes: %v", err.Error())
|
||||
} else {
|
||||
log.Infof("all store indexes successfully erased")
|
||||
}
|
||||
}
|
||||
|
||||
err = i.reindexBundledObjects(flags)
|
||||
func (i *indexer) ReindexSpace(spaceID string) (err error) {
|
||||
flags, err := i.buildFlags(spaceID)
|
||||
if err != nil {
|
||||
log.Errorf("failed to reindex bundled objects: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// We derive or init predefined blocks here in order to ensure consistency of object store.
|
||||
// If we call this method before removing objects from store, we will end up with inconsistent state
|
||||
// because indexing of predefined objects will not run again
|
||||
predefinedObjectIDs, err := i.anytype.EnsurePredefinedBlocks(context.Background(), i.spaceService.AccountId())
|
||||
if err != nil {
|
||||
return fmt.Errorf("ensure predefined objects: %w", err)
|
||||
}
|
||||
spaceIDs := []string{i.spaceService.AccountId()}
|
||||
|
||||
// spaceID => workspaceID
|
||||
spacesToInit := map[string]string{}
|
||||
err = block.Do(i.picker, predefinedObjectIDs.Workspace, func(sb smartblock.SmartBlock) error {
|
||||
st := sb.NewState()
|
||||
spaces := st.Store().GetFields()["spaces"]
|
||||
for k, v := range spaces.GetStructValue().GetFields() {
|
||||
spacesToInit[k] = v.GetStringValue()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
for spaceID, _ := range spacesToInit {
|
||||
spaceIDs = append(spaceIDs, spaceID)
|
||||
_, err = i.anytype.EnsurePredefinedBlocks(context.Background(), spaceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ensure predefined objects for child space %s: %w", spaceID, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, spaceID := range spaceIDs {
|
||||
err = i.EnsurePreinstalledObjects(spaceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ensure preinstalled objects: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// starting sync of all other objects later, because we don't want to have problems with loading of derived objects
|
||||
// due to parallel load which can overload the stream
|
||||
i.syncStarter.StartSync()
|
||||
|
||||
for _, spaceID := range spaceIDs {
|
||||
err = i.reindexSpace(spaceID, flags)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reindex space %s: %w", spaceID, err)
|
||||
}
|
||||
}
|
||||
|
||||
err = i.saveLatestChecksums()
|
||||
if err != nil {
|
||||
return fmt.Errorf("save latest checksums: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *indexer) reindexSpace(spaceID string, flags reindexFlags) (err error) {
|
||||
ctx := objectcache.CacheOptsWithRemoteLoadDisabled(context.Background())
|
||||
// for all ids except home and archive setting cache timeout for reindexing
|
||||
// ctx = context.WithValue(ctx, ocache.CacheTimeout, cacheTimeout)
|
||||
if flags.objects {
|
||||
ids, err := i.getIdsForTypes(
|
||||
spaceID,
|
||||
types := []smartblock2.SmartBlockType{
|
||||
smartblock2.SmartBlockTypePage,
|
||||
smartblock2.SmartBlockTypeProfilePage,
|
||||
smartblock2.SmartBlockTypeTemplate,
|
||||
smartblock2.SmartBlockTypeArchive,
|
||||
smartblock2.SmartBlockTypeHome,
|
||||
smartblock2.SmartBlockTypeWorkspace,
|
||||
smartblock2.SmartBlockTypeObjectType,
|
||||
smartblock2.SmartBlockTypeRelation,
|
||||
smartblock2.SmartBlockTypeSpaceView,
|
||||
smartblock2.SmartBlockTypeProfilePage,
|
||||
}
|
||||
ids, err := i.getIdsForTypes(
|
||||
spaceID,
|
||||
types...,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
start := time.Now()
|
||||
successfullyReindexed := i.reindexIdsIgnoreErr(ctx, ids...)
|
||||
successfullyReindexed := i.reindexIdsIgnoreErr(ctx, spaceID, ids...)
|
||||
|
||||
i.logFinishedReindexStat(metrics.ReindexTypeThreads, len(ids), successfullyReindexed, time.Since(start))
|
||||
|
||||
|
@ -263,10 +183,15 @@ func (i *indexer) reindexSpace(spaceID string, flags reindexFlags) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return i.saveLatestChecksums(spaceID)
|
||||
}
|
||||
|
||||
func (i *indexer) reindexBundledObjects(flags reindexFlags) error {
|
||||
func (i *indexer) ReindexCommonObjects() error {
|
||||
flags, err := i.buildFlags("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = i.removeGlobalIndexes(flags)
|
||||
ctx := context.Background()
|
||||
spaceID := addr.AnytypeMarketplaceWorkspace
|
||||
|
||||
|
@ -286,7 +211,7 @@ func (i *indexer) reindexBundledObjects(flags reindexFlags) error {
|
|||
if flags.bundledObjects {
|
||||
// hardcoded for now
|
||||
ids := []string{addr.AnytypeProfileId, addr.MissingObject}
|
||||
err := i.reindexIDs(ctx, metrics.ReindexTypeBundledObjects, ids)
|
||||
err := i.reindexIDs(ctx, addr.AnytypeMarketplaceWorkspace, metrics.ReindexTypeBundledObjects, ids)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reindex profile and missing object: %w", err)
|
||||
}
|
||||
|
@ -310,7 +235,51 @@ func (i *indexer) reindexBundledObjects(flags reindexFlags) error {
|
|||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return i.saveLatestChecksums("")
|
||||
}
|
||||
|
||||
func (i *indexer) removeGlobalIndexes(flags reindexFlags) (err error) {
|
||||
if flags.any() {
|
||||
log.Infof("start store reindex (%s)", flags.String())
|
||||
}
|
||||
if flags.objects && flags.fileObjects {
|
||||
// files will be indexed within object indexing (see indexLinkedFiles)
|
||||
// because we need to do it in the background.
|
||||
// otherwise it will lead to the situation when files loading called from the reindex with DisableRemoteFlag
|
||||
// will be waiting for the linkedFiles background indexing without this flag
|
||||
flags.fileObjects = false
|
||||
}
|
||||
|
||||
if flags.fileKeys {
|
||||
err = i.fileStore.RemoveEmptyFileKeys()
|
||||
if err != nil {
|
||||
log.Errorf("reindex failed to RemoveEmptyFileKeys: %v", err.Error())
|
||||
} else {
|
||||
log.Infof("RemoveEmptyFileKeys filekeys succeed")
|
||||
}
|
||||
}
|
||||
|
||||
if flags.removeAllIndexedObjects {
|
||||
ids, err := i.store.ListIds()
|
||||
if err != nil {
|
||||
log.Errorf("reindex failed to get all ids(removeAllIndexedObjects): %v", err.Error())
|
||||
}
|
||||
for _, id := range ids {
|
||||
err = i.store.DeleteDetails(id)
|
||||
if err != nil {
|
||||
log.Errorf("reindex failed to delete details(removeAllIndexedObjects): %v", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
if flags.eraseIndexes {
|
||||
err = i.store.EraseIndexes()
|
||||
if err != nil {
|
||||
log.Errorf("reindex failed to erase indexes: %v", err.Error())
|
||||
} else {
|
||||
log.Infof("all store indexes successfully erased")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (i *indexer) reindexIDsForSmartblockTypes(ctx context.Context, spaceID string, reindexType metrics.ReindexType, sbTypes ...smartblock2.SmartBlockType) error {
|
||||
|
@ -318,19 +287,19 @@ func (i *indexer) reindexIDsForSmartblockTypes(ctx context.Context, spaceID stri
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return i.reindexIDs(ctx, reindexType, ids)
|
||||
return i.reindexIDs(ctx, spaceID, reindexType, ids)
|
||||
}
|
||||
|
||||
func (i *indexer) reindexIDs(ctx context.Context, reindexType metrics.ReindexType, ids []string) error {
|
||||
func (i *indexer) reindexIDs(ctx context.Context, spaceID string, reindexType metrics.ReindexType, ids []string) error {
|
||||
start := time.Now()
|
||||
successfullyReindexed := i.reindexIdsIgnoreErr(ctx, ids...)
|
||||
successfullyReindexed := i.reindexIdsIgnoreErr(ctx, spaceID, ids...)
|
||||
i.logFinishedReindexStat(reindexType, len(ids), successfullyReindexed, time.Since(start))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *indexer) reindexOutdatedObjects(ctx context.Context, spaceID string) (toReindex, success int, err error) {
|
||||
// reindex of subobject collection always leads to reindex of the all subobjects reindexing
|
||||
spc, err := i.spaceService.GetSpace(ctx, spaceID)
|
||||
spc, err := i.spaceCore.Get(ctx, spaceID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -367,20 +336,22 @@ func (i *indexer) reindexOutdatedObjects(ctx context.Context, spaceID string) (t
|
|||
}
|
||||
}
|
||||
|
||||
success = i.reindexIdsIgnoreErr(ctx, idsToReindex...)
|
||||
success = i.reindexIdsIgnoreErr(ctx, spaceID, idsToReindex...)
|
||||
return len(idsToReindex), success, nil
|
||||
}
|
||||
|
||||
func (i *indexer) reindexDoc(ctx context.Context, id string) error {
|
||||
err := block.DoContext(i.picker, ctx, id, func(sb smartblock.SmartBlock) error {
|
||||
func (i *indexer) reindexDoc(ctx context.Context, spaceID, id string) error {
|
||||
return block.DoContextFullID(i.picker, ctx, domain.FullID{
|
||||
ObjectID: id,
|
||||
SpaceID: spaceID,
|
||||
}, func(sb smartblock.SmartBlock) error {
|
||||
return i.Index(ctx, sb.GetDocInfo())
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *indexer) reindexIdsIgnoreErr(ctx context.Context, ids ...string) (successfullyReindexed int) {
|
||||
func (i *indexer) reindexIdsIgnoreErr(ctx context.Context, spaceID string, ids ...string) (successfullyReindexed int) {
|
||||
for _, id := range ids {
|
||||
err := i.reindexDoc(ctx, id)
|
||||
err := i.reindexDoc(ctx, spaceID, id)
|
||||
if err != nil {
|
||||
log.With("objectID", id).Errorf("failed to reindex: %v", err)
|
||||
} else {
|
||||
|
@ -390,40 +361,22 @@ func (i *indexer) reindexIdsIgnoreErr(ctx context.Context, ids ...string) (succe
|
|||
return
|
||||
}
|
||||
|
||||
func (i *indexer) EnsurePreinstalledObjects(spaceID string) error {
|
||||
start := time.Now()
|
||||
ids := make([]string, 0, len(bundle.SystemTypes)+len(bundle.SystemRelations))
|
||||
for _, ot := range bundle.SystemTypes {
|
||||
ids = append(ids, ot.BundledURL())
|
||||
}
|
||||
|
||||
for _, rk := range bundle.SystemRelations {
|
||||
ids = append(ids, rk.BundledURL())
|
||||
}
|
||||
_, _, err := i.objectCreator.InstallBundledObjects(context.Background(), spaceID, ids)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.logFinishedReindexStat(metrics.ReindexTypeSystem, len(ids), len(ids), time.Since(start))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *indexer) saveLatestChecksums() error {
|
||||
func (i *indexer) saveLatestChecksums(spaceID string) error {
|
||||
checksums := model.ObjectStoreChecksums{
|
||||
BundledObjectTypes: bundle.TypeChecksum,
|
||||
BundledRelations: bundle.RelationChecksum,
|
||||
BundledTemplates: i.btHash.Hash(),
|
||||
ObjectsForceReindexCounter: ForceObjectsReindexCounter,
|
||||
FilesForceReindexCounter: ForceFilesReindexCounter,
|
||||
|
||||
BundledObjectTypes: bundle.TypeChecksum,
|
||||
BundledRelations: bundle.RelationChecksum,
|
||||
BundledTemplates: i.btHash.Hash(),
|
||||
ObjectsForceReindexCounter: ForceObjectsReindexCounter,
|
||||
FilesForceReindexCounter: ForceFilesReindexCounter,
|
||||
IdxRebuildCounter: ForceIdxRebuildCounter,
|
||||
FulltextRebuild: ForceFulltextIndexCounter,
|
||||
BundledObjects: ForceBundledObjectsReindexCounter,
|
||||
FilestoreKeysForceReindexCounter: ForceFilestoreKeysReindexCounter,
|
||||
}
|
||||
return i.store.SaveChecksums(&checksums)
|
||||
if spaceID == "" {
|
||||
return i.store.SaveGlobalChecksums(&checksums)
|
||||
}
|
||||
return i.store.SaveChecksums(spaceID, &checksums)
|
||||
}
|
||||
|
||||
func (i *indexer) getIdsForTypes(spaceID string, sbt ...smartblock2.SmartBlockType) ([]string, error) {
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/ftsearch"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider/mock_typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider/mock_typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
)
|
||||
|
||||
|
|
|
@ -8,10 +8,10 @@ import (
|
|||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
)
|
||||
|
||||
func (mw *Middleware) NavigationListObjects(cctx context.Context, req *pb.RpcNavigationListObjectsRequest) *pb.RpcNavigationListObjectsResponse {
|
||||
|
@ -51,9 +51,9 @@ func (mw *Middleware) NavigationGetObjectInfoWithLinks(cctx context.Context, req
|
|||
return filtered
|
||||
}
|
||||
|
||||
spaceService := getService[space.Service](mw)
|
||||
resolver := getService[idresolver.Resolver](mw)
|
||||
store := app.MustComponent[objectstore.ObjectStore](mw.applicationService.GetApp())
|
||||
spaceID, err := spaceService.ResolveSpaceID(req.ObjectId)
|
||||
spaceID, err := resolver.ResolveSpaceID(req.ObjectId)
|
||||
if err != nil {
|
||||
return response(pb.RpcNavigationGetObjectInfoWithLinksResponseError_UNKNOWN_ERROR, nil, fmt.Errorf("resolve spaceID: %w", err))
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/gogo/protobuf/types"
|
||||
|
||||
"github.com/anyproto/anytype-heart/core/block"
|
||||
"github.com/anyproto/anytype-heart/core/block/object/idresolver"
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/core/system_object"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
|
@ -68,7 +69,8 @@ func (mw *Middleware) ObjectTypeRelationAdd(cctx context.Context, req *pb.RpcObj
|
|||
}
|
||||
|
||||
err := mw.doBlockService(func(bs *block.Service) (err error) {
|
||||
spaceId, err := bs.ResolveSpaceID(req.ObjectTypeUrl)
|
||||
res := mw.applicationService.GetApp().MustComponent(idresolver.CName).(idresolver.Resolver)
|
||||
spaceId, err := res.ResolveSpaceID(req.ObjectTypeUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/core/system_object/mock_system_object"
|
||||
"github.com/anyproto/anytype-heart/pb"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider/mock_typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider/mock_typeprovider"
|
||||
"github.com/anyproto/anytype-heart/tests/testutil"
|
||||
"github.com/anyproto/anytype-heart/util/testMock"
|
||||
)
|
||||
|
@ -56,7 +56,7 @@ func newFixture(t *testing.T) *fixture {
|
|||
a.Register(sbtProvider)
|
||||
|
||||
systemObjectService := mock_system_object.NewMockService(t)
|
||||
a.Register(testutil.PrepareMock(a, systemObjectService))
|
||||
a.Register(testutil.PrepareMock(context.Background(), a, systemObjectService))
|
||||
|
||||
collectionService := &collectionServiceMock{MockCollectionService: mock_subscription.NewMockCollectionService(t)}
|
||||
a.Register(collectionService)
|
||||
|
@ -107,7 +107,7 @@ func newFixtureWithRealObjectStore(t *testing.T) *fixtureRealStore {
|
|||
sbtProvider.EXPECT().Init(mock.Anything).Return(nil)
|
||||
a.Register(sbtProvider)
|
||||
systemObjectService := mock_system_object.NewMockService(t)
|
||||
a.Register(testutil.PrepareMock(a, systemObjectService))
|
||||
a.Register(testutil.PrepareMock(context.Background(), a, systemObjectService))
|
||||
fx := &fixtureRealStore{
|
||||
Service: New(),
|
||||
a: a,
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/logging"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
||||
"github.com/anyproto/anytype-heart/space/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/space/spacecore/typeprovider"
|
||||
"github.com/anyproto/anytype-heart/util/pbtypes"
|
||||
"github.com/anyproto/anytype-heart/util/slice"
|
||||
)
|
||||
|
|
|
@ -33,7 +33,7 @@ const (
|
|||
type fileStatusRegistry struct {
|
||||
fileSyncService filesync.FileSync
|
||||
fileStore filestore.FileStore
|
||||
picker getblock.Picker
|
||||
picker getblock.ObjectGetter
|
||||
|
||||
sync.Mutex
|
||||
|
||||
|
@ -44,7 +44,7 @@ type fileStatusRegistry struct {
|
|||
func newFileStatusRegistry(
|
||||
fileSyncService filesync.FileSync,
|
||||
fileStore filestore.FileStore,
|
||||
picker getblock.Picker,
|
||||
picker getblock.ObjectGetter,
|
||||
updateInterval time.Duration,
|
||||
) *fileStatusRegistry {
|
||||
return &fileStatusRegistry{
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
|
||||
"github.com/anyproto/anytype-heart/core/domain"
|
||||
"github.com/anyproto/anytype-heart/pkg/lib/datastore"
|
||||
"github.com/anyproto/anytype-heart/space"
|
||||
)
|
||||
|
||||
type fileWithSpace struct {
|
||||
|
@ -28,16 +27,20 @@ type fileStatus struct {
|
|||
updatedAt time.Time
|
||||
}
|
||||
|
||||
type personalIDProvider interface {
|
||||
PersonalSpaceID() string
|
||||
}
|
||||
|
||||
type fileWatcher struct {
|
||||
filesToWatchLock *sync.Mutex
|
||||
filesToWatch map[fileWithSpace]struct{}
|
||||
|
||||
dbProvider datastore.Datastore
|
||||
badger *badger.DB
|
||||
spaceService space.Service
|
||||
registry *fileStatusRegistry
|
||||
updateCh chan fileWithSpace
|
||||
closeCh chan struct{}
|
||||
dbProvider datastore.Datastore
|
||||
badger *badger.DB
|
||||
provider personalIDProvider
|
||||
registry *fileStatusRegistry
|
||||
updateCh chan fileWithSpace
|
||||
closeCh chan struct{}
|
||||
|
||||
updateReceiver syncstatus.UpdateReceiver
|
||||
|
||||
|
@ -45,7 +48,7 @@ type fileWatcher struct {
|
|||
}
|
||||
|
||||
func newFileWatcher(
|
||||
spaceService space.Service,
|
||||
provider personalIDProvider,
|
||||
dbProvider datastore.Datastore,
|
||||
registry *fileStatusRegistry,
|
||||
updateReceiver syncstatus.UpdateReceiver,
|
||||
|
@ -60,7 +63,7 @@ func newFileWatcher(
|
|||
updateReceiver: updateReceiver,
|
||||
registry: registry,
|
||||
dbProvider: dbProvider,
|
||||
spaceService: spaceService,
|
||||
provider: provider,
|
||||
}
|
||||
return watcher
|
||||
}
|
||||
|
@ -69,7 +72,7 @@ const filesToWatchPrefix = "/files_to_watch/"
|
|||
|
||||
func (s *fileWatcher) loadFilesToWatch() error {
|
||||
return s.badger.View(func(txn *badger.Txn) error {
|
||||
defaultSpaceID := s.spaceService.AccountId()
|
||||
defaultSpaceID := s.provider.PersonalSpaceID()
|
||||
iter := txn.NewIterator(badger.IteratorOptions{
|
||||
Prefix: []byte(filesToWatchPrefix),
|
||||
})
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue