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:
commit
d08e3aed19
25 changed files with 278 additions and 48 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]},
|
||||
},
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
93
core/block/simple/dataview/views_test.go
Normal file
93
core/block/simple/dataview/views_test.go
Normal 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)
|
||||
})
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
2
go.mod
|
@ -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
10
go.sum
|
@ -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=
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue