1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-11 18:20:33 +09:00
anytype-heart/space/service.go
2023-10-13 10:16:16 +05:00

184 lines
4.4 KiB
Go

package space
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"sync"
"github.com/anyproto/any-sync/accountservice"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/app/logger"
"github.com/gogo/protobuf/types"
"go.uber.org/zap"
"github.com/anyproto/anytype-heart/core/block/object/objectcache"
"github.com/anyproto/anytype-heart/space/spacecore"
"github.com/anyproto/anytype-heart/space/spaceinfo"
"github.com/anyproto/anytype-heart/space/techspace"
)
const CName = "client.space"
var log = logger.NewNamed(CName)
var (
ErrIncorrectSpaceID = errors.New("incorrect space id")
ErrSpaceNotExists = errors.New("space not exists")
)
func New() Service {
return &service{}
}
type spaceIndexer interface {
ReindexMarketplaceSpace(space Space) error
ReindexSpace(space Space) error
}
type isNewAccount interface {
IsNewAccount() bool
app.Component
}
type Service interface {
Create(ctx context.Context) (space Space, err error)
Get(ctx context.Context, id string) (space Space, err error)
GetPersonalSpace(ctx context.Context) (space Space, err error)
SpaceViewId(spaceId string) (spaceViewId string, err error)
app.ComponentRunnable
}
type service struct {
indexer spaceIndexer
spaceCore spacecore.SpaceCoreService
techSpace techspace.TechSpace
marketplaceSpace Space
bundledObjectsInstaller bundledObjectsInstaller
accountService accountservice.Service
objectFactory objectcache.ObjectFactory
personalSpaceID string
newAccount bool
statuses map[string]spaceinfo.SpaceInfo
loading map[string]*loadingSpace
loaded map[string]Space
mu sync.Mutex
ctx context.Context
ctxCancel context.CancelFunc
repKey uint64
}
func (s *service) Init(a *app.App) (err error) {
s.indexer = app.MustComponent[spaceIndexer](a)
s.spaceCore = app.MustComponent[spacecore.SpaceCoreService](a)
s.objectFactory = app.MustComponent[objectcache.ObjectFactory](a)
s.accountService = app.MustComponent[accountservice.Service](a)
s.bundledObjectsInstaller = app.MustComponent[bundledObjectsInstaller](a)
s.newAccount = app.MustComponent[isNewAccount](a).IsNewAccount()
s.techSpace = techspace.New()
s.statuses = map[string]spaceinfo.SpaceInfo{}
s.loading = map[string]*loadingSpace{}
s.loaded = map[string]Space{}
return err
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) Run(ctx context.Context) (err error) {
s.ctx, s.ctxCancel = context.WithCancel(context.Background())
err = s.initMarketplaceSpace()
if err != nil {
return fmt.Errorf("init marketplace space: %w", err)
}
err = s.initTechSpace()
if err != nil {
return fmt.Errorf("init tech space: %w", err)
}
err = s.initPersonalSpace()
if err != nil {
return fmt.Errorf("init personal space: %w", err)
}
return nil
}
func (s *service) Create(ctx context.Context) (Space, error) {
coreSpace, err := s.spaceCore.Create(ctx, s.repKey)
if err != nil {
return nil, err
}
return s.create(ctx, coreSpace)
}
func (s *service) Get(ctx context.Context, spaceID string) (sp Space, err error) {
if err = s.startLoad(ctx, spaceID); err != nil {
return nil, err
}
return s.waitLoad(ctx, spaceID)
}
func (s *service) GetPersonalSpace(ctx context.Context) (sp Space, err error) {
return s.Get(ctx, s.personalSpaceID)
}
func (s *service) open(ctx context.Context, spaceID string) (sp Space, err error) {
coreSpace, err := s.spaceCore.Get(ctx, spaceID)
if err != nil {
return nil, err
}
return s.newSpace(ctx, coreSpace)
}
func (s *service) IsPersonal(id string) bool {
return s.personalSpaceID == id
}
func (s *service) OnViewCreated(spaceID string) {
go func() {
if err := s.startLoad(s.ctx, spaceID); err != nil {
log.Warn("OnViewCreated.startLoad error", zap.Error(err))
}
}()
}
func (s *service) OnWorkspaceChanged(spaceId string, details *types.Struct) {
go func() {
if err := s.techSpace.SpaceViewSetData(s.ctx, spaceId, details); err != nil {
log.Warn("OnWorkspaceChanged error", zap.Error(err))
}
}()
}
func (s *service) SpaceViewId(spaceId string) (spaceViewId string, err error) {
return s.techSpace.SpaceViewId(spaceId)
}
func (s *service) Close(ctx context.Context) (err error) {
if s.ctxCancel != nil {
s.ctxCancel()
}
return s.techSpace.Close(ctx)
}
func getRepKey(spaceID string) (uint64, error) {
sepIdx := strings.Index(spaceID, ".")
if sepIdx == -1 {
return 0, ErrIncorrectSpaceID
}
return strconv.ParseUint(spaceID[sepIdx+1:], 36, 64)
}