diff --git a/core/application/account_create.go b/core/application/account_create.go index 1ab65a446a..8e65aefd3a 100644 --- a/core/application/account_create.go +++ b/core/application/account_create.go @@ -106,14 +106,13 @@ func (s *Service) handleCustomStorageLocation(req *pb.RpcAccountCreateRequest, a func (s *Service) setAccountAndProfileDetails(ctx context.Context, req *pb.RpcAccountCreateRequest, newAcc *model.Account) error { spaceService := app.MustComponent[space.Service](s.app) techSpaceId := spaceService.TechSpaceId() - personalSpaceId := spaceService.PersonalSpaceId() var err error newAcc.Info, err = app.MustComponent[account.Service](s.app).GetInfo(ctx) if err != nil { return err } // TODO: remove it release 8, this is need for client to set "My First Space" as space name - newAcc.Info.AccountSpaceId = personalSpaceId + newAcc.Info.AccountSpaceId = spaceService.FirstCreatedSpaceId() bs := s.app.MustComponent(block.CName).(*block.Service) commonDetails := []*model.Detail{ diff --git a/core/files/fileobject/service.go b/core/files/fileobject/service.go index b1f1429705..5422164cd3 100644 --- a/core/files/fileobject/service.go +++ b/core/files/fileobject/service.go @@ -166,10 +166,7 @@ type objectArchiver interface { } func (s *service) deleteMigratedFilesInNonPersonalSpaces(ctx context.Context) error { - personalSpace, err := s.spaceService.GetPersonalSpace(ctx) - if err != nil { - return err - } + personalSpaceId := s.spaceService.PersonalSpaceId() records, err := s.objectStore.QueryCrossSpace(database.Query{ Filters: []*model.BlockContentDataviewFilter{ @@ -184,7 +181,7 @@ func (s *service) deleteMigratedFilesInNonPersonalSpaces(ctx context.Context) er { RelationKey: bundle.RelationKeySpaceId.String(), Condition: model.BlockContentDataviewFilter_NotEqual, - Value: pbtypes.String(personalSpace.Id()), + Value: pbtypes.String(personalSpaceId), }, }, }) diff --git a/core/files/fileobject/service_test.go b/core/files/fileobject/service_test.go index b8c2999e88..65abadad4c 100644 --- a/core/files/fileobject/service_test.go +++ b/core/files/fileobject/service_test.go @@ -97,6 +97,7 @@ func newFixture(t *testing.T) *fixture { fileService := files.New() spaceService := mock_space.NewMockService(t) spaceService.EXPECT().GetPersonalSpace(mock.Anything).Return(nil, fmt.Errorf("not needed")).Maybe() + spaceService.EXPECT().PersonalSpaceId().Return("personalSpaceId").Maybe() spaceIdResolver := mock_idresolver.NewMockResolver(t) svc := New(testResolveRetryDelay, testResolveRetryDelay) diff --git a/docs/proto.md b/docs/proto.md index 447a2bdea5..b8272ba1e0 100644 --- a/docs/proto.md +++ b/docs/proto.md @@ -28081,7 +28081,7 @@ Contains basic information about a user account | marketplaceWorkspaceId | [string](#string) | | marketplace workspace id | | workspaceObjectId | [string](#string) | | workspace object id. used for space-level chat | | deviceId | [string](#string) | | | -| accountSpaceId | [string](#string) | | | +| accountSpaceId | [string](#string) | | the first created private space. It's filled only when account is created | | widgetsId | [string](#string) | | | | spaceViewId | [string](#string) | | | | techSpaceId | [string](#string) | | | diff --git a/pkg/lib/pb/model/protos/models.proto b/pkg/lib/pb/model/protos/models.proto index ae203f44d2..86933635c5 100644 --- a/pkg/lib/pb/model/protos/models.proto +++ b/pkg/lib/pb/model/protos/models.proto @@ -661,7 +661,7 @@ message Account { string workspaceObjectId = 15; // workspace object id. used for space-level chat string deviceId = 8; - string accountSpaceId = 9; + string accountSpaceId = 9; // the first created private space. It's filled only when account is created string widgetsId = 10; string spaceViewId = 13; string techSpaceId = 14; diff --git a/space/create.go b/space/create.go index ffccf10252..efe5c2815e 100644 --- a/space/create.go +++ b/space/create.go @@ -7,32 +7,6 @@ import ( "github.com/anyproto/anytype-heart/space/internal/spaceprocess/loader" ) -func (s *service) createPersonalSpace(ctx context.Context) (err error) { - s.mu.Lock() - wait := make(chan struct{}) - s.waiting[s.personalSpaceId] = controllerWaiter{ - wait: wait, - } - s.mu.Unlock() - ctrl, err := s.factory.CreatePersonalSpace(ctx, s.accountMetadataPayload) - if err != nil { - return - } - _, err = ctrl.Current().(loader.LoadWaiter).WaitLoad(ctx) - s.mu.Lock() - defer s.mu.Unlock() - close(wait) - if err != nil { - s.waiting[s.personalSpaceId] = controllerWaiter{ - wait: wait, - err: err, - } - return - } - s.spaceControllers[s.personalSpaceId] = ctrl - return -} - func (s *service) create(ctx context.Context) (sp clientspace.Space, err error) { coreSpace, err := s.spaceCore.Create(ctx, s.repKey, s.AccountMetadataPayload()) if err != nil { diff --git a/space/mock_space/mock_Service.go b/space/mock_space/mock_Service.go index 6a38d0132c..03c2bc2938 100644 --- a/space/mock_space/mock_Service.go +++ b/space/mock_space/mock_Service.go @@ -318,6 +318,51 @@ func (_c *MockService_Delete_Call) RunAndReturn(run func(context.Context, string return _c } +// FirstCreatedSpaceId provides a mock function with given fields: +func (_m *MockService) FirstCreatedSpaceId() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for FirstCreatedSpaceId") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// MockService_FirstCreatedSpaceId_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FirstCreatedSpaceId' +type MockService_FirstCreatedSpaceId_Call struct { + *mock.Call +} + +// FirstCreatedSpaceId is a helper method to define mock.On call +func (_e *MockService_Expecter) FirstCreatedSpaceId() *MockService_FirstCreatedSpaceId_Call { + return &MockService_FirstCreatedSpaceId_Call{Call: _e.mock.On("FirstCreatedSpaceId")} +} + +func (_c *MockService_FirstCreatedSpaceId_Call) Run(run func()) *MockService_FirstCreatedSpaceId_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *MockService_FirstCreatedSpaceId_Call) Return(_a0 string) *MockService_FirstCreatedSpaceId_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MockService_FirstCreatedSpaceId_Call) RunAndReturn(run func() string) *MockService_FirstCreatedSpaceId_Call { + _c.Call.Return(run) + return _c +} + // Get provides a mock function with given fields: ctx, id func (_m *MockService) Get(ctx context.Context, id string) (clientspace.Space, error) { ret := _m.Called(ctx, id) diff --git a/space/service.go b/space/service.go index 8dd1f843d9..81e297edc4 100644 --- a/space/service.go +++ b/space/service.go @@ -63,6 +63,7 @@ type Service interface { Delete(ctx context.Context, id string) (err error) TechSpaceId() string PersonalSpaceId() string + FirstCreatedSpaceId() string TechSpace() *clientspace.TechSpace GetPersonalSpace(ctx context.Context) (space clientspace.Space, err error) GetTechSpace(ctx context.Context) (space clientspace.Space, err error) @@ -107,6 +108,8 @@ type service struct { ctx context.Context // use ctx for the long operations within the lifecycle of the service, excluding Run ctxCancel context.CancelFunc isClosing atomic.Bool + + firstCreatedSpaceId string } func (s *service) Delete(ctx context.Context, id string) (err error) { @@ -276,7 +279,7 @@ func (s *service) createAccount(ctx context.Context) (err error) { if err != nil { return fmt.Errorf("init tech space: %w", err) } - err = s.createPersonalSpace(ctx) + firstSpace, err := s.create(ctx) if err != nil { if errors.Is(err, spacesyncproto.ErrSpaceMissing) || errors.Is(err, treechangeproto.ErrGetTree) { err = ErrSpaceNotExists @@ -288,6 +291,9 @@ func (s *service) createAccount(ctx context.Context) (err error) { } return fmt.Errorf("init personal space: %w", err) } + + s.firstCreatedSpaceId = firstSpace.Id() + s.techSpace.WakeUpViews() // only persist networkId after successful space init err = s.config.PersistAccountNetworkId() @@ -481,6 +487,10 @@ func (s *service) PersonalSpaceId() string { return s.personalSpaceId } +func (s *service) FirstCreatedSpaceId() string { + return s.firstCreatedSpaceId +} + func (s *service) getTechSpace(ctx context.Context) (*clientspace.TechSpace, error) { select { case <-s.techSpaceReady: diff --git a/space/service_test.go b/space/service_test.go index c7469445b9..276a3b1923 100644 --- a/space/service_test.go +++ b/space/service_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/anyproto/any-sync/app" + "github.com/anyproto/any-sync/commonspace/mock_commonspace" "github.com/anyproto/any-sync/commonspace/object/accountdata" "github.com/anyproto/any-sync/commonspace/spacesyncproto" "github.com/anyproto/any-sync/coordinator/coordinatorclient/mock_coordinatorclient" @@ -46,7 +47,6 @@ const ( testPersonalSpaceID = "personal.12345" ) -// TODO Revive tests func TestService_Init(t *testing.T) { t.Run("tech space getter", func(t *testing.T) { serv := New().(*service) @@ -403,8 +403,13 @@ func (fx *fixture) expectRun(t *testing.T, expectOldAccount func(t *testing.T, f if expectOldAccount == nil { fx.factory.EXPECT().CreateAndSetTechSpace(mock.Anything).Return(&clientspace.TechSpace{TechSpace: ts}, nil) prCtrl := mock_spacecontroller.NewMockSpaceController(t) - fx.factory.EXPECT().CreatePersonalSpace(mock.Anything, mock.Anything).Return(prCtrl, nil) + prCtrl.EXPECT().SpaceId().Return(fx.spaceId) + commonSpace := mock_commonspace.NewMockSpace(fx.ctrl) + commonSpace.EXPECT().Id().Return(fx.spaceId).AnyTimes() + fx.spaceCore.EXPECT().Create(mock.Anything, mock.Anything, mock.Anything).Return(&spacecore.AnySpace{Space: commonSpace}, nil) + fx.factory.EXPECT().CreateShareableSpace(mock.Anything, mock.Anything).Return(prCtrl, nil) lw := lwMock{clientSpace} + clientSpace.EXPECT().Id().Return(fx.spaceId) prCtrl.EXPECT().Current().Return(lw) prCtrl.EXPECT().Close(mock.Anything).Return(nil) ts.EXPECT().WakeUpViews()