Skip to content

Commit

Permalink
Merge pull request #1914 from anyproto/GO-4653-account-object-not-exi…
Browse files Browse the repository at this point in the history
…sts-logs

GO-4653: Simplify analytics id logic and add more verbose errors
  • Loading branch information
requilence authored Dec 7, 2024
2 parents e79eb9a + bbdf576 commit 000ee08
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 169 deletions.
73 changes: 29 additions & 44 deletions core/anytype/account/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package account

import (
"context"
"errors"
"fmt"
"path/filepath"
"time"
Expand All @@ -25,9 +24,14 @@ import (
"github.com/anyproto/anytype-heart/space"
"github.com/anyproto/anytype-heart/space/spacecore"
"github.com/anyproto/anytype-heart/space/techspace"
"github.com/anyproto/anytype-heart/util/metricsid"
)

const CName = "account"
const (
CName = "account"

analyticsWaitTimeout = time.Second * 30
)

var log = logging.Logger(CName)

Expand Down Expand Up @@ -173,55 +177,36 @@ func (s *service) GetSpaceInfo(ctx context.Context, spaceId string) (*model.Acco
}

func (s *service) getAnalyticsId(ctx context.Context, techSpace techspace.TechSpace) (analyticsId string, err error) {
if s.config.AnalyticsId != "" {
return s.config.AnalyticsId, nil
}
err = techSpace.DoAccountObject(ctx, func(accountObject techspace.AccountObject) error {
var innerErr error
analyticsId, innerErr = accountObject.GetAnalyticsId()
if innerErr != nil {
log.Debug("failed to get analytics id: %s", innerErr)
start := time.Now()
for {
err = techSpace.DoAccountObject(ctx, func(accountObject techspace.AccountObject) error {
var innerErr error
analyticsId, innerErr = accountObject.GetAnalyticsId()
if innerErr != nil {
log.Debug("failed to get analytics id: %s", innerErr)
}
return nil
})
if err != nil {
return
}
return nil
})
if err != nil {
return
}
if analyticsId == "" {
for {
// waiting for personal space
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
persErr := s.spaceService.WaitPersonalSpaceMigration(ctx)
cancel()
if persErr != nil && !errors.Is(persErr, ctx.Err()) {
return "", persErr
if analyticsId != "" {
return analyticsId, nil
}
if time.Since(start) > analyticsWaitTimeout {
metricsId, err := metricsid.DeriveMetricsId(s.keyProvider.Account().SignKey)
if err != nil {
return "", err
}
// there is also this case that account object could be unsynced on start
// because we can't distinguish between accounts without account object (i.e. old accounts)
// and new ones which have the account object
// so it may be the case that it will sync but a little bit later
err = techSpace.DoAccountObject(ctx, func(accountObject techspace.AccountObject) error {
var innerErr error
analyticsId, innerErr = accountObject.GetAnalyticsId()
if innerErr != nil {
log.Debug("failed to get analytics id: %s", err)
}
return nil
return accountObject.SetAnalyticsId(metricsId)
})
if err != nil {
return
}
if analyticsId != "" {
return analyticsId, nil
}
if persErr == nil {
return "", fmt.Errorf("failed to get analytics id, but migrated successfully")
return "", err
}
// adding sleep just in case to avoid infinite loops if we have some unforeseen issues
time.Sleep(time.Second)
return metricsId, nil
}
} else {
return analyticsId, nil
time.Sleep(time.Second)
}
}

Expand Down
6 changes: 5 additions & 1 deletion core/application/account_create_from_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/anyproto/anytype-heart/util/anyerror"
"github.com/anyproto/anytype-heart/util/builtinobjects"
"github.com/anyproto/anytype-heart/util/constant"
"github.com/anyproto/anytype-heart/util/metricsid"
"github.com/anyproto/anytype-heart/util/pbtypes"
)

Expand Down Expand Up @@ -104,7 +105,10 @@ func (s *Service) RecoverFromLegacy(req *pb.RpcAccountRecoverFromLegacyExportReq
if profile.AnalyticsId != "" {
cfg.AnalyticsId = profile.AnalyticsId
} else {
cfg.AnalyticsId = metrics.GenerateAnalyticsId()
cfg.AnalyticsId, err = metricsid.DeriveMetricsId(res.Identity)
if err != nil {
return RecoverFromLegacyResponse{}, err
}
}

err = s.startApp(cfg, res)
Expand Down
47 changes: 15 additions & 32 deletions core/block/editor/accountobject/accountobject.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
anystore "github.com/anyproto/any-store"
"github.com/anyproto/any-store/anyenc"
"github.com/anyproto/any-sync/app/logger"
"github.com/anyproto/any-sync/commonspace/object/accountdata"
"github.com/anyproto/any-sync/util/crypto"
"github.com/gogo/protobuf/types"
"go.uber.org/zap"
Expand All @@ -32,18 +33,18 @@ import (
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore/spaceindex"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/metricsid"
"github.com/anyproto/anytype-heart/util/pbtypes"
)

var log = logger.NewNamedSugared("common.editor.accountobject")

const (
collectionName = "account"
accountDocumentId = "accountObject"
idKey = "id"
analyticsKey = "analyticsId"
iconMigrationKey = "iconMigration"
privateAnalyticsIdKey = "privateAnalyticsId"
collectionName = "account"
accountDocumentId = "accountObject"
idKey = "id"
analyticsKey = "analyticsId"
iconMigrationKey = "iconMigration"
)

type ProfileDetails struct {
Expand All @@ -63,7 +64,6 @@ type AccountObject interface {
IsIconMigrated() (bool, error)
SetAnalyticsId(analyticsId string) (err error)
GetAnalyticsId() (string, error)
GetPrivateAnalyticsId() string
}

type StoreDbProvider interface {
Expand All @@ -75,6 +75,7 @@ var _ AccountObject = (*accountObject)(nil)
type accountObject struct {
anystoredebug.AnystoreDebug
smartblock.SmartBlock
keys *accountdata.AccountKeys
bs basic.DetailsSettable
state *storestate.StoreState
storeSource source.Store
Expand All @@ -95,6 +96,7 @@ func (a *accountObject) SetDetailsAndUpdateLastUsed(ctx session.Context, details

func New(
sb smartblock.SmartBlock,
keys *accountdata.AccountKeys,
spaceObjects spaceindex.Store,
layoutConverter converter.LayoutConverter,
fileObjectService fileobject.Service,
Expand All @@ -103,6 +105,7 @@ func New(
cfg *config.Config) AccountObject {
return &accountObject{
crdtDb: crdtDb,
keys: keys,
bs: basic.NewBasic(sb, spaceObjects, layoutConverter, fileObjectService, lastUsedUpdater),
SmartBlock: sb,
cfg: cfg,
Expand All @@ -127,7 +130,6 @@ func (a *accountObject) Init(ctx *smartblock.InitContext) error {
a.state = stateStore

a.AnystoreDebug = anystoredebug.New(a.SmartBlock, stateStore)

storeSource, ok := ctx.Source.(source.Store)
if !ok {
return fmt.Errorf("source is not a store")
Expand Down Expand Up @@ -179,27 +181,16 @@ func (a *accountObject) Init(ctx *smartblock.InitContext) error {
return a.SmartBlock.Apply(st, smartblock.NotPushChanges, smartblock.NoHistory, smartblock.SkipIfNoChanges)
}

// GetPrivateAnalyticsId returns the private analytics id of the account object, should not be used directly
// only when hashing it with other data, e.g. hash(privateAnalyticsId + someData)
func (a *accountObject) GetPrivateAnalyticsId() string {
val, err := a.getValue()
if err != nil {
return ""
}
return string(val.GetStringBytes(privateAnalyticsIdKey))
}

func (a *accountObject) genInitialDoc() (builder *storestate.Builder, err error) {
builder = &storestate.Builder{}
privateAnalytics, err := generatePrivateAnalyticsId()
analyticsId, err := metricsid.DeriveMetricsId(a.keys.SignKey)
if err != nil {
err = fmt.Errorf("generate private analytics id: %w", err)
return
}
newDocument := map[string]any{
idKey: accountDocumentId,
analyticsKey: a.cfg.AnalyticsId,
iconMigrationKey: "true",
privateAnalyticsIdKey: privateAnalytics,
idKey: accountDocumentId,
analyticsKey: analyticsId,
iconMigrationKey: "true",
}
for key, val := range newDocument {
if str, ok := val.(string); ok {
Expand Down Expand Up @@ -277,14 +268,6 @@ func (a *accountObject) SetAnalyticsId(id string) error {
if err != nil {
return nil
}
privateAnalyticsId, err := generatePrivateAnalyticsId()
if err != nil {
return fmt.Errorf("generate private analytics id: %w", err)
}
err = builder.Modify(collectionName, accountDocumentId, []string{privateAnalyticsIdKey}, pb.ModifyOp_Set, fmt.Sprintf(`"%s"`, privateAnalyticsId))
if err != nil {
return nil
}
_, err = a.storeSource.PushStoreChange(a.ctx, source.PushStoreChangeParams{
Changes: builder.ChangeSet,
State: a.state,
Expand Down
27 changes: 9 additions & 18 deletions core/block/editor/accountobject/accountobject_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

anystore "github.com/anyproto/any-store"
"github.com/anyproto/any-store/anyenc"
"github.com/anyproto/any-sync/commonspace/object/accountdata"
"github.com/globalsign/mgo/bson"
"github.com/gogo/protobuf/types"
"github.com/stretchr/testify/mock"
Expand All @@ -24,6 +25,7 @@ import (
"github.com/anyproto/anytype-heart/core/block/source/mock_source"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
"github.com/anyproto/anytype-heart/util/metricsid"
"github.com/anyproto/anytype-heart/util/pbtypes"
)

Expand All @@ -40,7 +42,6 @@ type fixture struct {
func newFixture(t *testing.T, isNewAccount bool, prepareDb func(db anystore.DB)) *fixture {
ctx := context.Background()
cfg := config.New(config.WithNewAccount(isNewAccount))
cfg.AnalyticsId = "analyticsId"
db, err := anystore.Open(ctx, filepath.Join(t.TempDir(), "crdt.db"), nil)
require.NoError(t, err)
if prepareDb != nil {
Expand All @@ -52,7 +53,9 @@ func newFixture(t *testing.T, isNewAccount bool, prepareDb func(db anystore.DB))
})
sb := smarttest.New("accountId1")
indexStore := objectstore.NewStoreFixture(t).SpaceIndex("spaceId")
object := New(sb, indexStore, nil, nil, nil, db, cfg)
keys, err := accountdata.NewRandom()
require.NoError(t, err)
object := New(sb, keys, indexStore, nil, nil, nil, db, cfg)
fx := &fixture{
storeFx: objectstore.NewStoreFixture(t),
db: db,
Expand Down Expand Up @@ -136,6 +139,8 @@ func (fx *fixture) assertStateValue(t *testing.T, val any, extract func(str *typ

func TestAccountNew(t *testing.T) {
fx := newFixture(t, true, nil)
expectedId, err := metricsid.DeriveMetricsId(fx.keys.SignKey)
require.NoError(t, err)
st := fx.SmartBlock.NewState()
assertBlock(t, st, "accountId1")
assertBlock(t, st, "title")
Expand All @@ -146,7 +151,8 @@ func TestAccountNew(t *testing.T) {
require.True(t, res)
id, err := fx.GetAnalyticsId()
require.NoError(t, err)
require.Equal(t, "analyticsId", id)
fmt.Println(id)
require.Equal(t, expectedId, id)
}

func TestAccountOldInitWithData(t *testing.T) {
Expand Down Expand Up @@ -209,21 +215,6 @@ func TestSetSharedSpacesLimit(t *testing.T) {
require.Equal(t, 10, res)
}

func TestAccountObject_GetPrivateAnalyticsId(t *testing.T) {
t.Run("new account", func(t *testing.T) {
fx := newFixture(t, true, nil)
res := fx.GetPrivateAnalyticsId()
require.NotEmpty(t, res)
})
t.Run("old account", func(t *testing.T) {
fx := newFixture(t, false, nil)
err := fx.SetAnalyticsId("analyticsId")
require.NoError(t, err)
res := fx.GetPrivateAnalyticsId()
require.NotEmpty(t, res)
})
}

func TestAnalyticsId(t *testing.T) {
fx := newFixture(t, true, nil)
err := fx.SetAnalyticsId("analyticsId")
Expand Down
4 changes: 3 additions & 1 deletion core/block/editor/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/object/accountdata"
"github.com/anyproto/any-sync/commonspace/object/tree/objecttree"

"github.com/anyproto/anytype-heart/core/anytype/config"
Expand Down Expand Up @@ -44,6 +45,7 @@ type accountService interface {
AccountID() string
PersonalSpaceID() string
MyParticipantId(spaceId string) string
Keys() *accountdata.AccountKeys
}

type deviceService interface {
Expand Down Expand Up @@ -213,7 +215,7 @@ func (f *ObjectFactory) New(space smartblock.Space, sbType coresb.SmartBlockType
case coresb.SmartBlockTypeChatDerivedObject:
return chatobject.New(sb, f.accountService, f.eventSender, f.objectStore.GetCrdtDb(space.Id())), nil
case coresb.SmartBlockTypeAccountObject:
return accountobject.New(sb, store, f.layoutConverter, f.fileObjectService, f.lastUsedUpdater, f.objectStore.GetCrdtDb(space.Id()), f.config), nil
return accountobject.New(sb, f.accountService.Keys(), store, f.layoutConverter, f.fileObjectService, f.lastUsedUpdater, f.objectStore.GetCrdtDb(space.Id()), f.config), nil
default:
return nil, fmt.Errorf("unexpected smartblock type: %v", sbType)
}
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ require (
github.com/VividCortex/ewma v1.2.0
github.com/adrium/goheif v0.0.0-20230113233934-ca402e77a786
github.com/anyproto/any-store v0.1.3
github.com/anyproto/any-sync v0.5.20
github.com/anyproto/any-sync v0.5.21
github.com/anyproto/go-chash v0.1.0
github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438
github.com/anyproto/go-slip10 v1.0.0
github.com/anyproto/lexid v0.0.4
github.com/anyproto/protobuf v1.3.3-0.20240814124528-72b8c7e0e0f5
github.com/anyproto/tantivy-go v0.3.0
Expand Down Expand Up @@ -122,7 +123,6 @@ require (
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/anyproto/go-slip10 v1.0.0 // indirect
github.com/anyproto/go-slip21 v1.0.0 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsVi
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/anyproto/any-store v0.1.3 h1:onWLP8tuWiUvYOyV3DoRODscTxAiGEjwQPm+NMxeq3M=
github.com/anyproto/any-store v0.1.3/go.mod h1:6/0OUKgSMWF/vYGoGYzQOl2CII5OdiuXbQlGDXYcNYc=
github.com/anyproto/any-sync v0.5.20 h1:5In7AoMBa8npGz0Zv3wEmd3jhiN6CWGiCaEmgB8rRSM=
github.com/anyproto/any-sync v0.5.20/go.mod h1:K53/whh/9tmGbXrkPS59XyqWU3SaxhsX9g6VIYnBIlU=
github.com/anyproto/any-sync v0.5.21 h1:+Qx69Pij3QbLh2nRZEamD2WaSSy1uWHlXGMCIFEiKW0=
github.com/anyproto/any-sync v0.5.21/go.mod h1:K53/whh/9tmGbXrkPS59XyqWU3SaxhsX9g6VIYnBIlU=
github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580 h1:Ba80IlCCxkZ9H1GF+7vFu/TSpPvbpDCxXJ5ogc4euYc=
github.com/anyproto/badger/v4 v4.2.1-0.20240110160636-80743fa3d580/go.mod h1:T/uWAYxrXdaXw64ihI++9RMbKTCpKd/yE9+saARew7k=
github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY=
Expand Down
Loading

0 comments on commit 000ee08

Please sign in to comment.