1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-09 17:44:59 +09:00

GO-4192 app start improvements

This commit is contained in:
Roman Khafizianov 2024-10-04 17:22:57 +02:00
parent 95da8f56cc
commit af377b369f
No known key found for this signature in database
GPG key ID: F07A7D55A2684852
5 changed files with 96 additions and 31 deletions

View file

@ -26,7 +26,7 @@ func (s *service) BundledObjectsIdsToInstall(
ctx context.Context,
space clientspace.Space,
sourceObjectIds []string,
) (objectIds []string, err error) {
) (ids domain.BundledObjectIds, err error) {
marketplaceSpace, err := s.spaceService.Get(ctx, addr.AnytypeMarketplaceWorkspace)
if err != nil {
return nil, fmt.Errorf("get marketplace space: %w", err)
@ -51,7 +51,10 @@ func (s *service) BundledObjectsIdsToInstall(
if err != nil {
return err
}
objectIds = append(objectIds, objectId)
ids = append(ids, domain.BundledObjectId{
SourceId: sourceObjectId,
DerivedObjectId: objectId,
})
return nil
})
if err != nil {

View file

@ -0,0 +1,38 @@
package domain
type BundledObjectId struct {
SourceId string
DerivedObjectId string
}
type BundledObjectIds []BundledObjectId
func (b BundledObjectIds) Len() int {
return len(b)
}
func (b BundledObjectIds) SourceIds() []string {
var ids = make([]string, 0, len(b))
for _, bo := range b {
ids = append(ids, bo.SourceId)
}
return ids
}
func (b BundledObjectIds) DerivedObjectIds() []string {
var ids = make([]string, 0, len(b))
for _, bo := range b {
ids = append(ids, bo.DerivedObjectId)
}
return ids
}
func (b BundledObjectIds) Filter(f func(bo BundledObjectId) bool) BundledObjectIds {
var res = make([]BundledObjectId, 0, len(b))
for _, bo := range b {
if f(bo) {
res = append(res, bo)
}
}
return res
}

View file

@ -15,6 +15,7 @@ import (
"github.com/anyproto/any-sync/util/crypto"
"github.com/gogo/protobuf/types"
"go.uber.org/zap"
"golang.org/x/exp/slices"
"github.com/anyproto/anytype-heart/core/block/editor/profilemigration"
"github.com/anyproto/anytype-heart/core/block/editor/smartblock"
@ -28,7 +29,6 @@ import (
"github.com/anyproto/anytype-heart/space/spacecore"
"github.com/anyproto/anytype-heart/space/spacecore/peermanager"
"github.com/anyproto/anytype-heart/space/spacecore/storage"
"github.com/anyproto/anytype-heart/util/slice"
)
type Space interface {
@ -67,7 +67,7 @@ type spaceIndexer interface {
type bundledObjectsInstaller interface {
InstallBundledObjects(ctx context.Context, spc Space, ids []string, isNewSpace bool) ([]string, []*types.Struct, error)
BundledObjectsIdsToInstall(ctx context.Context, spc Space, sourceObjectIds []string) (objectIds []string, err error)
BundledObjectsIdsToInstall(ctx context.Context, spc Space, sourceObjectIds []string) (ids domain.BundledObjectIds, err error)
}
var log = logger.NewNamed("client.space")
@ -88,6 +88,9 @@ type space struct {
loadMandatoryObjectsCh chan struct{}
loadMandatoryObjectsErr error
loadMissingBundledObjectsCtx context.Context
loadMissingBundledObjectsCtxCancel context.CancelFunc
}
type SpaceDeps struct {
@ -113,6 +116,7 @@ func BuildSpace(ctx context.Context, deps SpaceDeps) (Space, error) {
myIdentity: deps.AccountService.Account().SignKey.GetPublic(),
loadMandatoryObjectsCh: make(chan struct{}),
}
sp.loadMissingBundledObjectsCtx, sp.loadMissingBundledObjectsCtxCancel = context.WithCancel(context.Background())
sp.Cache = objectcache.New(deps.AccountService, deps.ObjectFactory, deps.PersonalSpaceId, sp)
sp.ObjectProvider = objectprovider.NewObjectProvider(deps.CommonSpace.Id(), deps.PersonalSpaceId, sp.Cache)
var err error
@ -129,7 +133,8 @@ func BuildSpace(ctx context.Context, deps SpaceDeps) (Space, error) {
if err != nil {
return nil, fmt.Errorf("unmark space created: %w", err)
}
if err = sp.InstallBundledObjects(ctx); err != nil {
ids := getBundledObjectsToInstall()
if _, _, err = sp.installer.InstallBundledObjects(ctx, sp, ids, true); err != nil {
return nil, fmt.Errorf("install bundled objects: %w", err)
}
}
@ -137,6 +142,19 @@ func BuildSpace(ctx context.Context, deps SpaceDeps) (Space, error) {
return sp, nil
}
func (s *space) tryLoadBundledAndInstallIfMissing() {
ctxWithPeerTimeout := context.WithValue(s.loadMissingBundledObjectsCtx, peermanager.ContextPeerFindDeadlineKey, time.Now().Add(BundledObjectsPeerFindTimeout))
missingSourceIds, err := s.TryLoadBundledObjects(ctxWithPeerTimeout)
if err != nil {
log.Error("failed to load bundled objects", zap.Error(err))
}
_, _, err = s.installer.InstallBundledObjects(s.loadMissingBundledObjectsCtx, s, missingSourceIds, true)
if err != nil {
log.Error("failed to install bundled objects", zap.Error(err))
}
}
func (s *space) mandatoryObjectsLoad(ctx context.Context, disableRemoteLoad bool) {
defer close(s.loadMandatoryObjectsCh)
s.loadMandatoryObjectsErr = s.indexer.ReindexSpace(s)
@ -151,11 +169,7 @@ func (s *space) mandatoryObjectsLoad(ctx context.Context, disableRemoteLoad bool
if s.loadMandatoryObjectsErr != nil {
return
}
ctxWithPeerTimeout := context.WithValue(loadCtx, peermanager.ContextPeerFindDeadlineKey, time.Now().Add(BundledObjectsPeerFindTimeout))
if err := s.TryLoadBundledObjects(ctxWithPeerTimeout); err != nil {
log.Error("failed to load bundled objects", zap.Error(err))
}
s.loadMandatoryObjectsErr = s.InstallBundledObjects(ctx)
go s.tryLoadBundledAndInstallIfMissing()
if s.loadMandatoryObjectsErr != nil {
return
}
@ -258,7 +272,7 @@ func (s *space) Close(ctx context.Context) error {
return s.common.Close()
}
func (s *space) InstallBundledObjects(ctx context.Context) error {
func getBundledObjectsToInstall() []string {
ids := make([]string, 0, len(bundle.SystemTypes)+len(bundle.SystemRelations))
for _, ot := range bundle.SystemTypes {
ids = append(ids, ot.BundledURL())
@ -266,14 +280,10 @@ func (s *space) InstallBundledObjects(ctx context.Context) error {
for _, rk := range bundle.SystemRelations {
ids = append(ids, rk.BundledURL())
}
_, _, err := s.installer.InstallBundledObjects(ctx, s, ids, true)
if err != nil {
return err
}
return nil
return ids
}
func (s *space) TryLoadBundledObjects(ctx context.Context) error {
func (s *space) TryLoadBundledObjects(ctx context.Context) (missingSourceIds []string, err error) {
st := time.Now()
defer func() {
if dur := time.Since(st); dur > time.Millisecond*200 {
@ -281,25 +291,34 @@ func (s *space) TryLoadBundledObjects(ctx context.Context) error {
}
}()
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())
}
objectIds, err := s.installer.BundledObjectsIdsToInstall(ctx, s, ids)
ids := getBundledObjectsToInstall()
bundledObjectIds, err := s.installer.BundledObjectsIdsToInstall(ctx, s, ids)
if err != nil {
return err
return nil, err
}
storedIds, err := s.Storage().StoredIds()
if err != nil {
return err
return nil, err
}
missingIds := bundledObjectIds.Filter(func(bo domain.BundledObjectId) bool {
return !slices.Contains(storedIds, bo.DerivedObjectId)
})
// only load objects that are not already stored
objectIds = slice.Difference(objectIds, storedIds)
s.LoadObjectsIgnoreErrs(ctx, objectIds)
return nil
s.LoadObjectsIgnoreErrs(ctx, missingIds.DerivedObjectIds())
// todo: make LoadObjectsIgnoreErrs return list of loaded ids
storedIds, err = s.Storage().StoredIds()
if err != nil {
return nil, err
}
missingIds = bundledObjectIds.Filter(func(bo domain.BundledObjectId) bool {
return !slices.Contains(storedIds, bo.DerivedObjectId)
})
return missingIds.SourceIds(), nil
}
func (s *space) migrationProfileObject(ctx context.Context) error {

View file

@ -5,10 +5,11 @@ import (
"github.com/gogo/protobuf/types"
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/space/clientspace"
)
type BundledObjectsInstaller interface {
InstallBundledObjects(ctx context.Context, spc clientspace.Space, ids []string, isNewSpace bool) ([]string, []*types.Struct, error)
BundledObjectsIdsToInstall(ctx context.Context, spc clientspace.Space, sourceObjectIds []string) (objectIds []string, err error)
BundledObjectsIdsToInstall(ctx context.Context, spc clientspace.Space, sourceObjectIds []string) (ids domain.BundledObjectIds, err error)
}

View file

@ -138,6 +138,8 @@ func (o *objectProvider) loadObjectsAsync(ctx context.Context, objIDs []string)
for _, id := range objIDs {
select {
case <-ctx.Done():
log.ErrorCtx(ctx, "loadObjectsAsync context done", zap.Error(ctx.Err()), zap.String("spaceId", o.spaceId), zap.String("objectId", id))
results <- ctx.Err()
continue
case limiter <- struct{}{}:
@ -148,6 +150,8 @@ func (o *objectProvider) loadObjectsAsync(ctx context.Context, objIDs []string)
}()
_, err := o.cache.GetObject(ctx, id)
if err != nil {
log.ErrorCtx(ctx, "loadObjectsAsync failed", zap.Error(ctx.Err()), zap.String("spaceId", o.spaceId), zap.String("objectId", id))
// we had a bug that allowed some users to remove their profile
// this workaround is to allow these users to load their accounts without errors and export their anytype data
if id == o.derivedObjectIds.Profile {