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

GO-3153 merge

This commit is contained in:
Sergey Cherepanov 2024-04-18 12:57:40 +02:00
commit d08e3aed19
No known key found for this signature in database
GPG key ID: 87F8EDE8FBDF637C
25 changed files with 278 additions and 48 deletions

View file

@ -387,7 +387,7 @@ func (a *aclService) ViewInvite(ctx context.Context, inviteCid cid.Cid, inviteFi
if err != nil {
return inviteservice.InviteView{}, convertedOrAclRequestError(err)
}
lst, err := list.BuildAclList(store, list.NoOpAcceptorVerifier{})
lst, err := list.BuildAclListWithIdentity(a.accountService.Keys(), store, list.NoOpAcceptorVerifier{})
if err != nil {
return inviteservice.InviteView{}, convertedOrAclRequestError(err)
}

View file

@ -282,6 +282,7 @@ func TestService_ViewInvite(t *testing.T) {
defer fx.finish(t)
keys, err := accountdata.NewRandom()
require.NoError(t, err)
fx.mockAccountService.EXPECT().Keys().Return(keys)
aclList, err := list.NewTestDerivedAcl("spaceId", keys)
require.NoError(t, err)
inv, err := aclList.RecordBuilder().BuildInvite()
@ -312,6 +313,7 @@ func TestService_ViewInvite(t *testing.T) {
defer fx.finish(t)
keys, err := accountdata.NewRandom()
require.NoError(t, err)
fx.mockAccountService.EXPECT().Keys().Return(keys)
aclList, err := list.NewTestDerivedAcl("spaceId", keys)
require.NoError(t, err)
inv, err := aclList.RecordBuilder().BuildInvite()

View file

@ -3,9 +3,11 @@
package mock_account
import (
app "github.com/anyproto/any-sync/app"
accountdata "github.com/anyproto/any-sync/commonspace/object/accountdata"
account "github.com/anyproto/anytype-heart/core/anytype/account"
app "github.com/anyproto/any-sync/app"
context "context"
mock "github.com/stretchr/testify/mock"
@ -232,6 +234,53 @@ func (_c *MockService_Init_Call) RunAndReturn(run func(*app.App) error) *MockSer
return _c
}
// Keys provides a mock function with given fields:
func (_m *MockService) Keys() *accountdata.AccountKeys {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Keys")
}
var r0 *accountdata.AccountKeys
if rf, ok := ret.Get(0).(func() *accountdata.AccountKeys); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*accountdata.AccountKeys)
}
}
return r0
}
// MockService_Keys_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Keys'
type MockService_Keys_Call struct {
*mock.Call
}
// Keys is a helper method to define mock.On call
func (_e *MockService_Expecter) Keys() *MockService_Keys_Call {
return &MockService_Keys_Call{Call: _e.mock.On("Keys")}
}
func (_c *MockService_Keys_Call) Run(run func()) *MockService_Keys_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockService_Keys_Call) Return(_a0 *accountdata.AccountKeys) *MockService_Keys_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockService_Keys_Call) RunAndReturn(run func() *accountdata.AccountKeys) *MockService_Keys_Call {
_c.Call.Return(run)
return _c
}
// MyParticipantId provides a mock function with given fields: _a0
func (_m *MockService) MyParticipantId(_a0 string) string {
ret := _m.Called(_a0)

View file

@ -6,7 +6,9 @@ import (
"path/filepath"
"sync"
"github.com/anyproto/any-sync/accountservice"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/object/accountdata"
"github.com/anyproto/any-sync/coordinator/coordinatorclient"
"github.com/anyproto/any-sync/coordinator/coordinatorproto"
"github.com/anyproto/any-sync/nodeconf"
@ -42,6 +44,7 @@ type Service interface {
// ProfileObjectId returns id of Profile object stored in personal space
ProfileObjectId() (string, error)
ProfileInfo() (Profile, error)
Keys() *accountdata.AccountKeys
}
type service struct {
@ -51,9 +54,9 @@ type service struct {
gateway gateway.Gateway
config *config.Config
objectStore objectstore.ObjectStore
nodeConf nodeconf.Service
coordClient coordinatorclient.CoordinatorClient
keyProvider accountservice.Service
nodeConf nodeconf.Service
coordClient coordinatorclient.CoordinatorClient
picker cache.ObjectGetter
once sync.Once
@ -71,6 +74,7 @@ func (s *service) Init(a *app.App) (err error) {
s.gateway = app.MustComponent[gateway.Gateway](a)
s.nodeConf = app.MustComponent[nodeconf.Service](a)
s.coordClient = app.MustComponent[coordinatorclient.CoordinatorClient](a)
s.keyProvider = app.MustComponent[accountservice.Service](a)
s.config = app.MustComponent[*config.Config](a)
s.picker = app.MustComponent[cache.ObjectGetter](a)
s.objectStore = app.MustComponent[objectstore.ObjectStore](a)
@ -78,6 +82,10 @@ func (s *service) Init(a *app.App) (err error) {
return
}
func (s *service) Keys() *accountdata.AccountKeys {
return s.keyProvider.Account()
}
func (s *service) Delete(ctx context.Context) (toBeDeleted int64, err error) {
confirm, err := coordinatorproto.PrepareAccountDeleteConfirmation(s.wallet.GetAccountPrivkey(), s.wallet.GetDevicePrivkey().GetPublic().PeerId(), s.nodeConf.Configuration().NetworkId)
if err != nil {

View file

@ -82,7 +82,7 @@ func (p *participant) TryClose(objectTTL time.Duration) (bool, error) {
func (p *participant) modifyDetails(newDetails *types.Struct) (err error) {
return p.DetailsUpdatable.UpdateDetails(func(current *types.Struct) (*types.Struct, error) {
return pbtypes.StructMerge(p.CombinedDetails(), newDetails, false), nil
return pbtypes.StructMerge(current, newDetails, false), nil
})
}

View file

@ -124,7 +124,7 @@ func ReplaceRelationsInDataView(st *state.State, rel *model.RelationLink) error
err := dv.ReplaceViewRelation(view.Id, rel.Key, &model.BlockContentDataviewRelation{
Key: rel.Key,
IsVisible: true,
Width: 192,
Width: simpleDataview.DefaultViewRelationWidth,
})
if err != nil {
return true

View file

@ -346,7 +346,7 @@ func AddRelationsToDataView(collectionState *state.State, relationLink *model.Re
err := dataView.AddViewRelation(view.GetId(), &model.BlockContentDataviewRelation{
Key: relationLink.Key,
IsVisible: true,
Width: 192,
Width: dataview.DefaultViewRelationWidth,
})
if err != nil {
return true

View file

@ -1,6 +1,7 @@
package csv
import (
"github.com/globalsign/mgo/bson"
"github.com/google/uuid"
"github.com/anyproto/anytype-heart/core/block/editor/state"
@ -97,7 +98,7 @@ func (c *TableStrategy) createEmptyHeader(st *state.State, tableID string, colum
}
for _, colID := range columnIDs {
textBlock := &model.Block{
Id: uuid.New().String(),
Id: bson.NewObjectId().Hex(),
Content: &model.BlockContentOfText{
Text: &model.BlockContentText{Text: ""},
},
@ -123,7 +124,7 @@ func (c *TableStrategy) createCells(columns []string, st *state.State, rowID str
continue
}
textBlock := &model.Block{
Id: uuid.New().String(),
Id: bson.NewObjectId().Hex(),
Content: &model.BlockContentOfText{
Text: &model.BlockContentText{Text: columns[i]},
},

View file

@ -10,7 +10,6 @@ import (
"github.com/globalsign/mgo/bson"
"github.com/gogo/protobuf/types"
"github.com/google/uuid"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/text"
@ -125,7 +124,7 @@ func (r *blocksRenderer) OpenNewTextBlock(style model.BlockContentTextStyle, fie
r.curStyledBlock = style
}
id := uuid.New().String()
id := bson.NewObjectId().Hex()
newBlock := model.Block{
Id: id,
@ -277,7 +276,7 @@ func (r *blocksRenderer) CloseTextBlock(content model.BlockContentTextStyle) {
var closingBlock *textBlock
var parentBlock *textBlock
id := uuid.New().String()
id := bson.NewObjectId().Hex()
if len(r.openedTextBlocks) > 0 {
closingBlock = r.openedTextBlocks[len(r.openedTextBlocks)-1]

View file

@ -9,7 +9,6 @@ import (
"github.com/globalsign/mgo/bson"
"github.com/gogo/protobuf/types"
"github.com/google/uuid"
"github.com/anyproto/anytype-heart/core/block/collection"
"github.com/anyproto/anytype-heart/core/block/import/common"
@ -524,7 +523,7 @@ func (m *Markdown) setNewID(files map[string]*FileInfo, progress process.Progres
}
if strings.EqualFold(filepath.Ext(name), ".md") || strings.EqualFold(filepath.Ext(name), ".csv") {
file.PageID = uuid.New().String()
file.PageID = bson.NewObjectId().Hex()
m.setDetails(file, name, details)
}

View file

@ -5,7 +5,7 @@ import (
"sync"
"time"
"github.com/google/uuid"
"github.com/globalsign/mgo/bson"
"github.com/anyproto/anytype-heart/core/block/import/common"
"github.com/anyproto/anytype-heart/core/block/import/common/workerpool"
@ -152,7 +152,7 @@ func (ds *Service) fillNotionImportContext(pages []Page, progress process.Progre
if err := progress.TryStep(1); err != nil {
return common.NewCancelError(err)
}
importContext.NotionPageIdsToAnytype[p.ID] = uuid.New().String()
importContext.NotionPageIdsToAnytype[p.ID] = bson.NewObjectId().Hex()
if p.Parent.PageID != "" {
importContext.PageTree.ParentPageToChildIDs[p.Parent.PageID] = append(importContext.PageTree.ParentPageToChildIDs[p.Parent.PageID], p.ID)
}

View file

@ -2,11 +2,14 @@ package dataview
import (
"github.com/globalsign/mgo/bson"
"golang.org/x/exp/slices"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/slice"
)
const DefaultViewRelationWidth = 192
func (l *Dataview) AddFilter(viewID string, filter *model.BlockContentDataviewFilter) error {
l.resetObjectOrderForView(viewID)
@ -155,6 +158,7 @@ func (l *Dataview) AddViewRelation(viewID string, relation *model.BlockContentDa
if err != nil {
return err
}
l.syncViewRelationWithRelationLinks(view)
view.Relations = append(view.Relations, relation)
return nil
@ -165,6 +169,7 @@ func (l *Dataview) RemoveViewRelations(viewID string, relationKeys []string) err
if err != nil {
return err
}
l.syncViewRelationWithRelationLinks(view)
view.Relations = slice.Filter(view.Relations, func(f *model.BlockContentDataviewRelation) bool {
return slice.FindPos(relationKeys, f.Key) == -1
@ -177,6 +182,7 @@ func (l *Dataview) ReplaceViewRelation(viewID string, relationKey string, relati
if err != nil {
return err
}
l.syncViewRelationWithRelationLinks(view)
idx := slice.Find(view.Relations, func(f *model.BlockContentDataviewRelation) bool {
return f.Key == relationKey
@ -195,21 +201,58 @@ func (l *Dataview) ReorderViewRelations(viewID string, relationKeys []string) er
if err != nil {
return err
}
l.syncViewRelationWithRelationLinks(view)
relationsMap := make(map[string]*model.BlockContentDataviewRelation)
for _, r := range view.Relations {
relationsMap[r.Key] = r
}
view.Relations = view.Relations[:0]
for _, key := range relationKeys {
if r, ok := relationsMap[key]; ok {
view.Relations = append(view.Relations, r)
// Add missing relation keys to requested order
if !slices.Contains(relationKeys, r.Key) {
relationKeys = append(relationKeys, r.Key)
}
}
newRelations := make([]*model.BlockContentDataviewRelation, 0, len(view.Relations))
for _, key := range relationKeys {
// Ignore relations that don't present in view's relations
if r, ok := relationsMap[key]; ok {
newRelations = append(newRelations, r)
}
}
view.Relations = newRelations
return nil
}
func (l *Dataview) syncViewRelationWithRelationLinks(view *model.BlockContentDataviewView) {
relationLinksKeys := map[string]struct{}{}
for _, relLink := range l.content.RelationLinks {
relationLinksKeys[relLink.Key] = struct{}{}
}
currentViewKeys := map[string]struct{}{}
newViewRelations := view.Relations[:0]
for _, rel := range view.Relations {
// Don't add relations that are not in relation links
if _, ok := relationLinksKeys[rel.Key]; ok {
newViewRelations = append(newViewRelations, rel)
currentViewKeys[rel.Key] = struct{}{}
}
}
for _, relLink := range l.content.RelationLinks {
_, ok := currentViewKeys[relLink.Key]
if !ok {
newViewRelations = append(newViewRelations, &model.BlockContentDataviewRelation{
Key: relLink.Key,
Width: DefaultViewRelationWidth,
IsVisible: false,
})
}
}
view.Relations = newViewRelations
}
func (l *Dataview) setRelationFormat(filter *model.BlockContentDataviewFilter) {
for _, relLink := range l.content.RelationLinks {
if relLink.Key == filter.RelationKey {

View file

@ -0,0 +1,93 @@
package dataview
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
)
const testViewId = "viewId"
func makeDataviewForReorderTest(relationLinks []*model.RelationLink, relations []*model.BlockContentDataviewRelation) Block {
return NewDataview(&model.Block{
Content: &model.BlockContentOfDataview{
Dataview: &model.BlockContentDataview{
RelationLinks: relationLinks,
Views: []*model.BlockContentDataviewView{
{
Id: testViewId,
Relations: relations,
},
},
},
},
}).(Block)
}
func TestReorderViewRelations(t *testing.T) {
t.Run("reorder: add missing relation from relation links", func(t *testing.T) {
dv := makeDataviewForReorderTest(
[]*model.RelationLink{
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
{Key: bundle.RelationKeyCreator.String(), Format: model.RelationFormat_object},
{Key: bundle.RelationKeyCreatedDate.String(), Format: model.RelationFormat_date},
},
[]*model.BlockContentDataviewRelation{
{Key: bundle.RelationKeyName.String(), IsVisible: true, Width: DefaultViewRelationWidth},
},
)
err := dv.ReorderViewRelations(testViewId, []string{bundle.RelationKeyCreator.String(), bundle.RelationKeyName.String()})
require.NoError(t, err)
want := makeDataviewForReorderTest(
[]*model.RelationLink{
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
{Key: bundle.RelationKeyCreator.String(), Format: model.RelationFormat_object},
{Key: bundle.RelationKeyCreatedDate.String(), Format: model.RelationFormat_date},
},
[]*model.BlockContentDataviewRelation{
{Key: bundle.RelationKeyCreator.String(), IsVisible: false, Width: DefaultViewRelationWidth},
{Key: bundle.RelationKeyName.String(), IsVisible: true, Width: DefaultViewRelationWidth},
{Key: bundle.RelationKeyCreatedDate.String(), IsVisible: false, Width: DefaultViewRelationWidth},
},
)
assert.Equal(t, want, dv)
})
t.Run("reorder: remove extra relation that don't exist in relation links", func(t *testing.T) {
dv := makeDataviewForReorderTest(
[]*model.RelationLink{
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
{Key: bundle.RelationKeyCreatedDate.String(), Format: model.RelationFormat_date},
},
[]*model.BlockContentDataviewRelation{
{Key: bundle.RelationKeyCreator.String(), IsVisible: false, Width: DefaultViewRelationWidth},
{Key: bundle.RelationKeyName.String(), IsVisible: true, Width: DefaultViewRelationWidth},
{Key: bundle.RelationKeyCreatedDate.String(), IsVisible: false, Width: DefaultViewRelationWidth},
},
)
err := dv.ReorderViewRelations(testViewId, []string{bundle.RelationKeyName.String(), bundle.RelationKeyCreator.String(), bundle.RelationKeyDescription.String()})
require.NoError(t, err)
want := makeDataviewForReorderTest(
[]*model.RelationLink{
{Key: bundle.RelationKeyName.String(), Format: model.RelationFormat_longtext},
{Key: bundle.RelationKeyCreatedDate.String(), Format: model.RelationFormat_date},
},
[]*model.BlockContentDataviewRelation{
{Key: bundle.RelationKeyName.String(), IsVisible: true, Width: DefaultViewRelationWidth},
{Key: bundle.RelationKeyCreatedDate.String(), IsVisible: false, Width: DefaultViewRelationWidth},
},
)
assert.Equal(t, want, dv)
})
}

View file

@ -95,6 +95,10 @@ func UnmarshalChange(treeChange *objecttree.Change, data []byte) (result any, er
return
}
func UnmarshalChangeWithDataType(dataType string, decrypted []byte) (res any, err error) {
return UnmarshalChange(&objecttree.Change{DataType: dataType}, decrypted)
}
type ChangeReceiver interface {
StateAppend(func(d state.Doc) (s *state.State, changes []*pb.ChangeContent, err error)) error
StateRebuild(d state.Doc) (err error)

View file

@ -3,8 +3,7 @@ package debug
import (
"fmt"
"github.com/gogo/protobuf/proto"
"github.com/anyproto/anytype-heart/core/block/source"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/util/anonymize"
)
@ -13,22 +12,18 @@ type changeDataConverter struct {
anonymize bool
}
func (c *changeDataConverter) Unmarshall(decrypted []byte) (res any, err error) {
ch := &pb.Change{}
err = proto.Unmarshal(decrypted, ch)
if err != nil {
return nil, err
}
return ch, nil
func (c *changeDataConverter) Unmarshall(dataType string, decrypted []byte) (res any, err error) {
return source.UnmarshalChangeWithDataType(dataType, decrypted)
}
func (c *changeDataConverter) Marshall(model any) ([]byte, error) {
func (c *changeDataConverter) Marshall(model any) (data []byte, dataType string, err error) {
ch, ok := model.(*pb.Change)
if !ok {
return nil, fmt.Errorf("can't convert the model")
return nil, "", fmt.Errorf("can't convert the model")
}
if c.anonymize {
ch = anonymize.Change(ch)
}
return ch.Marshal()
data, err = ch.Marshal()
return
}

View file

@ -60,6 +60,7 @@ func newFixture(t *testing.T) *fixture {
commonFileService := fileservice.New()
fileSyncService := filesync.New()
eventSender := mock_event.NewMockSender(t)
eventSender.EXPECT().Broadcast(mock.Anything).Return().Maybe()
fileService := files.New()
spaceService := mock_space.NewMockService(t)
spaceIdResolver := mock_idresolver.NewMockResolver(t)

View file

@ -56,6 +56,7 @@ func newFixture(t *testing.T) *fixture {
fileSyncService := filesync.New()
objectStore := objectstore.NewStoreFixture(t)
eventSender := mock_event.NewMockSender(t)
eventSender.EXPECT().Broadcast(mock.Anything).Return().Maybe()
ctx := context.Background()
a := new(app.App)

View file

@ -187,6 +187,7 @@ func newFileServiceFixture(t *testing.T) files.Service {
fileSyncService := filesync.New()
objectStore := objectstore.NewStoreFixture(t)
eventSender := mock_event.NewMockSender(t)
eventSender.EXPECT().Broadcast(mock.Anything).Return().Maybe()
ctx := context.Background()
a := new(app.App)

View file

@ -185,14 +185,15 @@ func (s *fileSync) getAndUpdateNodeUsage(ctx context.Context) (NodeUsage, error)
return NodeUsage{}, fmt.Errorf("save node usage info to store: %w", err)
}
if !prevUsageFound || prevUsage.AccountBytesLimit != usage.AccountBytesLimit {
s.sendLimitUpdatedEvent(uint64(usage.AccountBytesLimit))
}
for _, space := range spaces {
if !prevUsageFound || prevUsage.GetSpaceUsage(space.SpaceId).SpaceBytesUsage != space.SpaceBytesUsage {
s.sendSpaceUsageEvent(space.SpaceId, uint64(space.SpaceBytesUsage))
}
}
if !prevUsageFound || prevUsage.AccountBytesLimit != usage.AccountBytesLimit {
s.sendLimitUpdatedEvent(uint64(usage.AccountBytesLimit))
}
return usage, nil
}

View file

@ -9,6 +9,10 @@ import (
"github.com/anyproto/anytype-heart/pb"
)
type limitSetter interface {
SetLimit(limit int)
}
func TestSpaceUsageUpdate(t *testing.T) {
const limit = 1024 * 1024 * 1024
fx := newFixture(t, limit)
@ -71,13 +75,27 @@ func TestSpaceUsageUpdate(t *testing.T) {
assert.Equal(t, fileSize2, uint64(spaceUsage.SpaceBytesUsage))
})
t.Run("update limit", func(t *testing.T) {
setter, ok := fx.rpcStore.(limitSetter)
require.True(t, ok)
setter.SetLimit(limit * 10)
err = fx.UpdateNodeUsage(ctx)
require.NoError(t, err)
// Event is expected to be sent
})
t.Run("events sent", func(t *testing.T) {
fx.eventsLock.Lock()
defer fx.eventsLock.Unlock()
wantEvents := []*pb.Event{
makeLimitUpdatedEvent(limit),
makeSpaceUsageEvent("space1", fileSize1),
makeSpaceUsageEvent("space2", fileSize2),
makeLimitUpdatedEvent(limit * 10),
}
assert.Equal(t, wantEvents, fx.events)

View file

@ -180,6 +180,12 @@ func (t *inMemoryStore) SpaceInfo(ctx context.Context, spaceId string) (*filepro
panic("not implemented")
}
func (t *inMemoryStore) SetLimit(limit int) {
t.mu.Lock()
defer t.mu.Unlock()
t.limit = limit
}
func (t *inMemoryStore) AccountInfo(ctx context.Context) (*fileproto.AccountInfoResponse, error) {
var info fileproto.AccountInfoResponse
t.mu.Lock()

2
go.mod
View file

@ -7,7 +7,7 @@ require (
github.com/PuerkitoBio/goquery v1.9.1
github.com/VividCortex/ewma v1.2.0
github.com/adrium/goheif v0.0.0-20230113233934-ca402e77a786
github.com/anyproto/any-sync v0.4.5-0.20240417114039-321a9ca30bd1
github.com/anyproto/any-sync v0.4.5
github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
github.com/avast/retry-go/v4 v4.5.1

10
go.sum
View file

@ -89,12 +89,10 @@ github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxB
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/anyproto/any-sync v0.4.4 h1:/nlgv8oItRptlmvM2ctn7WyriQ4U4ztW5fhfAiWBJtU=
github.com/anyproto/any-sync v0.4.4/go.mod h1:C/byc9JTwLSqhaHd0wCf1+ncU4iDQCMaXuZj4yOKDYw=
github.com/anyproto/any-sync v0.4.5-0.20240417104247-8514732467b2 h1:wQND3pN/cLiy2EDVE9dheAvRYDWSh0xU4soGgRyQRKs=
github.com/anyproto/any-sync v0.4.5-0.20240417104247-8514732467b2/go.mod h1:C/byc9JTwLSqhaHd0wCf1+ncU4iDQCMaXuZj4yOKDYw=
github.com/anyproto/any-sync v0.4.5-0.20240417114039-321a9ca30bd1 h1:MPFx7ra5wK7ANu8n0WSPOh7/J4U3Neq4VXhWUbvDVRA=
github.com/anyproto/any-sync v0.4.5-0.20240417114039-321a9ca30bd1/go.mod h1:C/byc9JTwLSqhaHd0wCf1+ncU4iDQCMaXuZj4yOKDYw=
github.com/anyproto/any-sync v0.4.5-0.20240417164638-dcc4a1124a13 h1:wpBInpIoNS0xLH8m7dw7GaH2skDEh/6sOD6RfK42lSk=
github.com/anyproto/any-sync v0.4.5-0.20240417164638-dcc4a1124a13/go.mod h1:C/byc9JTwLSqhaHd0wCf1+ncU4iDQCMaXuZj4yOKDYw=
github.com/anyproto/any-sync v0.4.5 h1:E+FATSRxMpaBt1GgmHfi3VkNKSC5SftpwgLa883Wy3M=
github.com/anyproto/any-sync v0.4.5/go.mod h1:C/byc9JTwLSqhaHd0wCf1+ncU4iDQCMaXuZj4yOKDYw=
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=

View file

@ -42,7 +42,8 @@ type clientds struct {
repoPath string
spaceStoreWasMissing, localStoreWasMissing bool
spentOnInit time.Duration
closed chan struct{}
closing chan struct{}
syncerFinished chan struct{}
}
type Config struct {
@ -106,7 +107,8 @@ func openBadgerWithRecover(opts badger.Options) (db *badger.DB, err error) {
func (r *clientds) Init(a *app.App) (err error) {
// TODO: looks like we do a lot of stuff on Init here. We should consider moving it to the Run
r.closed = make(chan struct{})
r.closing = make(chan struct{})
r.syncerFinished = make(chan struct{})
start := time.Now()
wl := a.Component(wallet.CName)
if wl == nil {
@ -204,7 +206,9 @@ func (r *clientds) Name() (name string) {
}
func (r *clientds) Close(ctx context.Context) (err error) {
close(r.closed)
close(r.closing)
// wait syncer goroutine to finish to make sure we don't have in-progress requests, because it may cause panics
<-r.syncerFinished
if r.localstoreDS != nil {
err2 := r.localstoreDS.Close()
if err2 != nil {

View file

@ -54,6 +54,7 @@ func newDbSyncer(db *badger.DB) *dbSyncer {
}
func (r *clientds) syncer() error {
defer close(r.syncerFinished)
var syncers []*dbSyncer
if r.spaceDS != nil {
syncers = append(syncers, newDbSyncer(r.spaceDS))
@ -64,10 +65,16 @@ func (r *clientds) syncer() error {
for {
select {
case <-r.closed:
case <-r.closing:
return nil
case <-time.After(SyncDbAfterInactivity):
for _, syncer := range syncers {
select {
case <-r.closing:
// exit fast in case Close() is already called
return nil
default:
}
maxVersion := syncer.db.MaxVersion()
if syncer.LastMaxVersionSynced == maxVersion {
continue