diff --git a/core/block/editor/smartblock/smartblock.go b/core/block/editor/smartblock/smartblock.go index cc6e14870a..cec8b1010f 100644 --- a/core/block/editor/smartblock/smartblock.go +++ b/core/block/editor/smartblock/smartblock.go @@ -926,16 +926,6 @@ func (sb *smartBlock) Apply(s *state.State, flags ...ApplyFlag) (err error) { func (sb *smartBlock) ResetToVersion(s *state.State) (err error) { source.NewSubObjectsAndProfileLinksMigration(sb.Type(), sb.space, sb.currentParticipantId, sb.spaceIndex, sb.formatFetcher).Migrate(s) - // Ensure bundled relation links are present for all bundled detail keys. - // Without this, imported states may lack relation links for details like setOf, - // producing a RelationRemove change that wipes the detail on replay (GO-7217). - var relKeys []domain.RelationKey - for k := range s.Details().Iterate() { - if bundle.HasRelation(k) { - relKeys = append(relKeys, k) - } - } - s.AddBundledRelationLinks(relKeys...) s.SetParent(sb.Doc.(*state.State)) sb.storeFileKeys(s) sb.injectLocalDetails(s) diff --git a/core/block/editor/state/change.go b/core/block/editor/state/change.go index 57bf97f26f..e1a43d6a95 100644 --- a/core/block/editor/state/change.go +++ b/core/block/editor/state/change.go @@ -82,7 +82,6 @@ func NewDocFromSnapshot(rootId string, snapshot *pb.ChangeSnapshot, opts ...Snap rootId: rootId, blocks: blocks, details: details, - relationLinks: snapshot.Data.RelationLinks, objectTypeKeys: migrateObjectTypeIDsToKeys(snapshot.Data.ObjectTypes), fileKeys: fileKeys, store: snapshot.Data.Collections, @@ -277,17 +276,14 @@ func (s *State) changeBlockDetailsUnset(unset *pb.ChangeDetailsUnset) error { return nil } +// changeRelationAdd is kept for backward compatibility to parse RelationAdd changes from +// existing trees. Object-level relationLinks were removed (GO-4284), so it is a no-op. func (s *State) changeRelationAdd(add *pb.ChangeRelationAdd) error { - rl := s.getRelationLinks() - for _, r := range add.RelationLinks { - if !rl.Has(r.Key) { - rl = rl.Append(r) - } - } - s.relationLinks = rl return nil } +// changeRelationRemove parses a legacy RelationRemove change. Relations are now tracked by +// details, so removing the relation removes its detail value (and featured entry). func (s *State) changeRelationRemove(rem *pb.ChangeRelationRemove) error { s.RemoveRelation(slice.StringsInto[domain.RelationKey](rem.RelationKey)...) return nil @@ -467,8 +463,7 @@ func (s *State) GetChanges() []*pb.ChangeContent { func (s *State) fillChanges(msgs []simple.EventMessage) { var updMsgs = make([]*pb.EventMessage, 0, len(msgs)) - var delIds, delRelIds []string - var newRelLinks pbtypes.RelationLinks + var delIds []string var structMsgs = make([]*pb.EventBlockSetChildrenIds, 0, len(msgs)) var b1, b2 []byte for i, msg := range msgs { @@ -547,10 +542,6 @@ func (s *State) fillChanges(msgs []simple.EventMessage) { updMsgs = append(updMsgs, msg.Msg) case *pb.EventMessageValueOfBlockDataViewGroupOrderUpdate: updMsgs = append(updMsgs, msg.Msg) - case *pb.EventMessageValueOfObjectRelationsAmend: - newRelLinks = append(newRelLinks, msg.Msg.GetObjectRelationsAmend().RelationLinks...) - case *pb.EventMessageValueOfObjectRelationsRemove: - delRelIds = append(delRelIds, msg.Msg.GetObjectRelationsRemove().RelationKeys...) case *pb.EventMessageValueOfBlockDataViewObjectOrderUpdate: updMsgs = append(updMsgs, msg.Msg) case *pb.EventMessageValueOfBlockDataviewViewUpdate: @@ -580,30 +571,6 @@ func (s *State) fillChanges(msgs []simple.EventMessage) { }, }) } - if len(newRelLinks) > 0 { - filteredRelationsLinks := s.filterLocalAndDerivedRelations(newRelLinks) - if len(filteredRelationsLinks) > 0 { - cb.AddChange(&pb.ChangeContent{ - Value: &pb.ChangeContentValueOfRelationAdd{ - RelationAdd: &pb.ChangeRelationAdd{ - RelationLinks: filteredRelationsLinks, - }, - }, - }) - } - } - if len(delRelIds) > 0 { - filteredRelationsKeys := s.filterLocalAndDerivedRelationsByKey(delRelIds) - if len(filteredRelationsKeys) > 0 { - cb.AddChange(&pb.ChangeContent{ - Value: &pb.ChangeContentValueOfRelationRemove{ - RelationRemove: &pb.ChangeRelationRemove{ - RelationKey: filteredRelationsKeys, - }, - }, - }) - } - } if len(updMsgs) > 0 { cb.AddChange(&pb.ChangeContent{ Value: &pb.ChangeContentValueOfBlockUpdate{ @@ -623,26 +590,6 @@ func (s *State) fillChanges(msgs []simple.EventMessage) { s.changes = append(s.changes, s.makeDeviceInfoChanges()...) } -func (s *State) filterLocalAndDerivedRelations(newRelLinks pbtypes.RelationLinks) pbtypes.RelationLinks { - var relLinksWithoutLocal pbtypes.RelationLinks - for _, link := range newRelLinks { - if !slices.Contains(bundle.LocalAndDerivedRelationKeys, domain.RelationKey(link.Key)) { - relLinksWithoutLocal = relLinksWithoutLocal.Append(link) - } - } - return relLinksWithoutLocal -} - -func (s *State) filterLocalAndDerivedRelationsByKey(relationKeys []string) []string { - var relKeysWithoutLocal []string - for _, key := range relationKeys { - if !slices.Contains(bundle.LocalAndDerivedRelationKeys, domain.RelationKey(key)) { - relKeysWithoutLocal = append(relKeysWithoutLocal, key) - } - } - return relKeysWithoutLocal -} - func (s *State) fillStructureChanges(cb *changeBuilder, msgs []*pb.EventBlockSetChildrenIds) { for _, msg := range msgs { s.makeStructureChanges(cb, msg) diff --git a/core/block/editor/state/change_test.go b/core/block/editor/state/change_test.go index 7403c8e42f..b3de372dd7 100644 --- a/core/block/editor/state/change_test.go +++ b/core/block/editor/state/change_test.go @@ -695,82 +695,6 @@ func Test_ApplyChange(t *testing.T) { }) } -func TestRelationChanges(t *testing.T) { - a := NewDoc("root", nil).(*State) - a.relationLinks = []*model.RelationLink{{Key: "1"}, {Key: "2"}, {Key: "3"}} - ac := a.Copy() - b := a.NewState() - b.relationLinks = []*model.RelationLink{{Key: "3"}, {Key: "4"}, {Key: "5"}} - _, _, err := ApplyState("", b, false) - require.NoError(t, err) - chs := a.GetChanges() - require.NoError(t, ac.ApplyChange(chs...)) - require.Equal(t, a.relationLinks, ac.relationLinks) -} - -func TestLocalRelationChanges(t *testing.T) { - t.Run("local relation added", func(t *testing.T) { - // given - a := NewDoc("root", nil).(*State) - a.relationLinks = []*model.RelationLink{} - b := a.NewState() - b.relationLinks = []*model.RelationLink{{Key: bundle.RelationKeySyncStatus.String(), Format: model.RelationFormat_number}} - - // when - _, _, err := ApplyState("", b, false) - require.NoError(t, err) - chs := a.GetChanges() - - // then - require.Len(t, chs, 0) - }) - t.Run("local relation removed", func(t *testing.T) { - // given - a := NewDoc("root", nil).(*State) - a.relationLinks = []*model.RelationLink{{Key: bundle.RelationKeySyncStatus.String(), Format: model.RelationFormat_number}} - b := a.NewState() - b.relationLinks = []*model.RelationLink{} - - // when - _, _, err := ApplyState("", b, false) - require.NoError(t, err) - chs := a.GetChanges() - - // then - require.Len(t, chs, 0) - }) - t.Run("derived relation added", func(t *testing.T) { - // given - a := NewDoc("root", nil).(*State) - a.relationLinks = []*model.RelationLink{} - b := a.NewState() - b.relationLinks = []*model.RelationLink{{Key: bundle.RelationKeySpaceId.String(), Format: model.RelationFormat_longtext}} - - // when - _, _, err := ApplyState("", b, false) - require.NoError(t, err) - chs := a.GetChanges() - - // then - require.Len(t, chs, 0) - }) - t.Run("derived relation removed", func(t *testing.T) { - // given - a := NewDoc("root", nil).(*State) - a.relationLinks = []*model.RelationLink{{Key: bundle.RelationKeySpaceId.String(), Format: model.RelationFormat_longtext}} - b := a.NewState() - b.relationLinks = []*model.RelationLink{} - - // when - _, _, err := ApplyState("", b, false) - require.NoError(t, err) - chs := a.GetChanges() - - // then - require.Len(t, chs, 0) - }) -} - func TestRootBlockChanges(t *testing.T) { a := NewDoc("root", nil).(*State) s := a.NewState() diff --git a/core/block/editor/state/details.go b/core/block/editor/state/details.go index 75094967f1..602a1438fe 100644 --- a/core/block/editor/state/details.go +++ b/core/block/editor/state/details.go @@ -8,7 +8,6 @@ import ( "github.com/anyproto/anytype-heart/core/relationutils" "github.com/anyproto/anytype-heart/pkg/lib/bundle" "github.com/anyproto/anytype-heart/pkg/lib/pb/model" - "github.com/anyproto/anytype-heart/util/pbtypes" "github.com/anyproto/anytype-heart/util/slice" ) @@ -162,19 +161,6 @@ func (s *State) SetLocalDetail(key domain.RelationKey, value domain.Value) { // details removers func (s *State) RemoveRelation(keys ...domain.RelationKey) { - // TODO: GO-4284 remove logic regarding relationLinks - relLinks := s.getRelationLinks() - relLinksFiltered := make(pbtypes.RelationLinks, 0, len(relLinks)) - for _, link := range relLinks { - if slice.FindPos(keys, domain.RelationKey(link.Key)) >= 0 { - continue - } - relLinksFiltered = append(relLinksFiltered, &model.RelationLink{ - Key: link.Key, - Format: link.Format, - }) - } - s.relationLinks = relLinksFiltered // remove detail value s.RemoveDetail(keys...) // remove from the list of featured relations diff --git a/core/block/editor/state/state.go b/core/block/editor/state/state.go index f05a29353f..a04e199f89 100644 --- a/core/block/editor/state/state.go +++ b/core/block/editor/state/state.go @@ -121,7 +121,6 @@ type State struct { fileKeys []pb.ChangeFileKeys // Deprecated details *domain.Details localDetails *domain.Details - relationLinks pbtypes.RelationLinks notifications map[string]*model.Notification deviceStore map[string]*model.DeviceInfo @@ -175,11 +174,9 @@ func (s *State) filterRelations(filters *Filters) { resultDetails := domain.NewDetails() layout, _ := s.Layout() relationKeys := filters.RelationsWhiteList[layout] - var updatedRelationLinks pbtypes.RelationLinks for key, value := range s.details.Iterate() { if slices.Contains(relationKeys, key) { resultDetails.Set(key, value) - updatedRelationLinks = append(updatedRelationLinks, s.relationLinks.Get(key.String())) continue } } @@ -191,7 +188,6 @@ func (s *State) filterRelations(filters *Filters) { for key, value := range s.localDetails.Iterate() { if slices.Contains(relationKeys, key) { resultLocalDetails.Set(key, value) - updatedRelationLinks = append(updatedRelationLinks, s.relationLinks.Get(key.String())) continue } } @@ -199,7 +195,6 @@ func (s *State) filterRelations(filters *Filters) { if resultLocalDetails.Len() == 0 { s.localDetails = nil } - s.relationLinks = updatedRelationLinks } func (s *State) MigrationVersion() uint32 { @@ -700,40 +695,6 @@ func (s *State) apply(spaceId string, fast, one, withLayouts bool) (msgs []simpl })}) } - if s.parent != nil && s.relationLinks != nil { - added, removed := s.relationLinks.Diff(s.parent.relationLinks) - - if len(added)+len(removed) > 0 { - action.RelationLinks = &undo.RelationLinks{ - Before: s.parent.relationLinks, - After: s.relationLinks, - } - } - - if len(removed) > 0 { - msgs = append(msgs, WrapEventMessages(false, []*pb.EventMessage{ - event.NewMessage(s.SpaceID(), &pb.EventMessageValueOfObjectRelationsRemove{ - ObjectRelationsRemove: &pb.EventObjectRelationsRemove{ - Id: s.RootId(), - RelationKeys: removed, - }, - }, - ), - })...) - } - if len(added) > 0 { - msgs = append(msgs, WrapEventMessages(false, []*pb.EventMessage{ - event.NewMessage(s.SpaceID(), &pb.EventMessageValueOfObjectRelationsAmend{ - ObjectRelationsAmend: &pb.EventObjectRelationsAmend{ - Id: s.RootId(), - RelationLinks: added, - }, - }, - ), - })...) - } - } - // generate changes s.fillChanges(msgs) @@ -790,10 +751,6 @@ func (s *State) apply(spaceId string, fast, one, withLayouts bool) (msgs []simpl s.parent.fileKeys = append(s.parent.fileKeys, s.fileKeys...) } - if s.parent != nil && s.relationLinks != nil { - s.parent.relationLinks = s.relationLinks - } - if s.parent != nil && s.localDetails != nil { prev := s.parent.LocalDetails() if diff, keysToUnset := domain.StructDiff(prev, s.localDetails); diff != nil || len(keysToUnset) != 0 { @@ -849,10 +806,6 @@ func (s *State) intermediateApply() { s.parent.localDetails = s.localDetails } - if s.relationLinks != nil { - s.parent.relationLinks = s.relationLinks - } - if s.objectTypeKeys != nil { s.parent.objectTypeKeys = s.objectTypeKeys } @@ -956,10 +909,6 @@ func (s *State) StringDebug() string { buf := bytes.NewBuffer(nil) fmt.Fprintf(buf, "RootId: %s\n", s.RootId()) fmt.Fprintf(buf, "ObjectTypeKeys: %v\n", s.ObjectTypeKeys()) - fmt.Fprintf(buf, "Relations:\n") - for _, rel := range s.relationLinks { - fmt.Fprintf(buf, "\t%v\n", rel) - } fmt.Fprintf(buf, "\nDetails:\n") arena := &anyenc.Arena{} @@ -986,12 +935,12 @@ func (s *State) StringDebug() string { return buf.String() } -// SetDetailAndBundledRelation sets the detail value and bundled relation in case it is missing -// TODO: GO-4284 remove +// SetDetailAndBundledRelation sets the detail value. +// +// Deprecated: GO-4284 object-level relationLinks were removed; this is now a thin alias +// for SetDetail kept to avoid churn at call sites. Prefer SetDetail directly. func (s *State) SetDetailAndBundledRelation(key domain.RelationKey, value domain.Value) { - s.AddBundledRelationLinks(key) s.SetDetail(key, value) - return } func (s *State) SetAlign(align model.BlockAlign, ids ...string) (err error) { @@ -1323,7 +1272,6 @@ func (s *State) Copy() *State { rootId: s.rootId, details: s.Details().Copy(), localDetails: s.LocalDetails().Copy(), - relationLinks: s.getRelationLinks(), // Get methods copy inside objectTypeKeys: objTypes, noObjectType: s.noObjectType, migrationVersion: s.migrationVersion, @@ -1688,45 +1636,9 @@ func (s *State) SetContext(context session.Context) { s.ctx = context } -// deprecated -func (s *State) AddRelationLinks(links ...*model.RelationLink) { - relLinks := s.getRelationLinks() - for _, l := range links { - if !relLinks.Has(l.Key) { - relLinks = append(relLinks, l) - } - } - s.relationLinks = relLinks -} - -// TODO: GO-4284 remove -func (s *State) PickRelationLinks() pbtypes.RelationLinks { - return s.pickRelationLinks() -} - -// TODO: GO-4284 remove -func (s *State) pickRelationLinks() pbtypes.RelationLinks { - if s.relationLinks != nil { - return s.relationLinks - } - if s.parent != nil { - return s.parent.pickRelationLinks() - } - return nil -} - -// TODO: GO-4284 remove -func (s *State) getRelationLinks() pbtypes.RelationLinks { - if s.relationLinks != nil { - return s.relationLinks - } - if s.parent != nil { - parentLinks := s.parent.pickRelationLinks() - s.relationLinks = parentLinks.Copy() - return s.relationLinks - } - return nil -} +// Deprecated: GO-4284 object-level relationLinks were removed; this is now a no-op kept +// to avoid churn at call sites. Relations are tracked by details keys. +func (s *State) AddRelationLinks(links ...*model.RelationLink) {} func (s *State) Descendants(rootId string) []simple.Block { var ( @@ -1795,20 +1707,9 @@ func (s *State) SelectRoots(ids []string) []string { return res } -// TODO: GO-4284 remove -func (s *State) AddBundledRelationLinks(keys ...domain.RelationKey) { - existingLinks := s.pickRelationLinks() - - var links []*model.RelationLink - for _, key := range keys { - if !existingLinks.Has(key.String()) { - links = append(links, bundle.MustGetRelationLink(key)) - } - } - if len(links) > 0 { - s.AddRelationLinks(links...) - } -} +// Deprecated: GO-4284 object-level relationLinks were removed; this is now a no-op kept +// to avoid churn at call sites. Relations are tracked by details keys. +func (s *State) AddBundledRelationLinks(keys ...domain.RelationKey) {} func (s *State) GetNotificationById(id string) *model.Notification { iterState := s.findStateWithNonEmptyNotifications() diff --git a/core/block/editor/state/state_test.go b/core/block/editor/state/state_test.go index f349b10dee..19503bcaf0 100644 --- a/core/block/editor/state/state_test.go +++ b/core/block/editor/state/state_test.go @@ -2251,88 +2251,6 @@ func TestState_ApplyChangeIgnoreErrDetailsUnset(t *testing.T) { }) } -func TestState_ApplyChangeIgnoreErrRelationAdd(t *testing.T) { - st := NewDoc("root", map[string]simple.Block{ - "root": simple.New(&model.Block{ - Id: "root", - }), - }).(*State) - - t.Run("apply RelationAdd change: add new relation", func(t *testing.T) { - // given - change := &pb.ChangeContent{Value: &pb.ChangeContentValueOfRelationAdd{ - RelationAdd: &pb.ChangeRelationAdd{ - RelationLinks: []*model.RelationLink{ - { - Key: "relation1", - Format: model.RelationFormat_longtext, - }, - }, - }, - }} - - // when - st.ApplyChangeIgnoreErr(change) - - // then - assert.Contains(t, st.relationLinks, &model.RelationLink{Key: "relation1", Format: model.RelationFormat_longtext}) - }) - - t.Run("apply RelationAdd change: add already existing relation - no changes", func(t *testing.T) { - // given - change := &pb.ChangeContent{Value: &pb.ChangeContentValueOfRelationAdd{ - RelationAdd: &pb.ChangeRelationAdd{ - RelationLinks: []*model.RelationLink{ - { - Key: "relation1", - Format: model.RelationFormat_longtext, - }, - }, - }, - }} - - // when - st.ApplyChangeIgnoreErr(change) - - // then - assert.Contains(t, st.relationLinks, &model.RelationLink{Key: "relation1", Format: model.RelationFormat_longtext}) - }) -} - -func TestState_ApplyChangeIgnoreErrRelationRemove(t *testing.T) { - t.Run("apply RelationRemove change: remove relations", func(t *testing.T) { - // given - st := NewDoc("root", map[string]simple.Block{ - "root": simple.New(&model.Block{ - Id: "root", - }), - }).(*State) - - st.AddRelationLinks([]*model.RelationLink{ - { - Key: "relation1", - Format: model.RelationFormat_longtext, - }, - { - Key: "relation2", - Format: model.RelationFormat_shorttext, - }, - }...) - originLength := len(st.relationLinks) - change := &pb.ChangeContent{Value: &pb.ChangeContentValueOfRelationRemove{ - RelationRemove: &pb.ChangeRelationRemove{ - RelationKey: []string{"relation1", "relation2"}, - }, - }} - - // when - st.ApplyChangeIgnoreErr(change) - - // then - assert.Len(t, st.relationLinks, originLength-2) - }) -} - func TestState_ApplyChangeIgnoreErrObjectTypeAdd(t *testing.T) { st := NewDoc("root", map[string]simple.Block{ "root": simple.New(&model.Block{ @@ -2807,128 +2725,6 @@ func TestState_SetDeviceName(t *testing.T) { }) } -func TestAddBundledRealtionLinks(t *testing.T) { - t.Run("with relationLinks in state", func(t *testing.T) { - t.Run("empty", func(t *testing.T) { - st := &State{ - relationLinks: []*model.RelationLink{}, - } - st.AddBundledRelationLinks(bundle.RelationKeyName, bundle.RelationKeyIconOption) - - want := &State{ - relationLinks: []*model.RelationLink{ - { - Key: bundle.RelationKeyName.String(), - Format: model.RelationFormat_shorttext, - }, - { - Key: bundle.RelationKeyIconOption.String(), - Format: model.RelationFormat_number, - }, - }, - } - - assert.Equal(t, want, st) - }) - t.Run("one already exists, one not", func(t *testing.T) { - st := &State{ - relationLinks: []*model.RelationLink{ - { - Key: bundle.RelationKeyName.String(), - Format: model.RelationFormat_shorttext, - }, - }, - } - st.AddBundledRelationLinks(bundle.RelationKeyName, bundle.RelationKeyIconOption) - - want := &State{ - relationLinks: []*model.RelationLink{ - { - Key: bundle.RelationKeyName.String(), - Format: model.RelationFormat_shorttext, - }, - { - Key: bundle.RelationKeyIconOption.String(), - Format: model.RelationFormat_number, - }, - }, - } - - assert.Equal(t, want, st) - }) - }) - t.Run("with relationLinks only in parent state", func(t *testing.T) { - st := &State{ - relationLinks: nil, - parent: &State{ - relationLinks: []*model.RelationLink{ - { - Key: bundle.RelationKeyName.String(), - Format: model.RelationFormat_shorttext, - }, - }, - }, - } - st.AddBundledRelationLinks(bundle.RelationKeyName, bundle.RelationKeyIconOption) - - want := &State{ - relationLinks: []*model.RelationLink{ - { - Key: bundle.RelationKeyName.String(), - Format: model.RelationFormat_shorttext, - }, - { - Key: bundle.RelationKeyIconOption.String(), - Format: model.RelationFormat_number, - }, - }, - parent: &State{ - relationLinks: []*model.RelationLink{ - { - Key: bundle.RelationKeyName.String(), - Format: model.RelationFormat_shorttext, - }, - }, - }, - } - - assert.Equal(t, want, st) - }) -} - -func TestState_AddRelationLinks(t *testing.T) { - t.Run("add new link", func(t *testing.T) { - // given - s := &State{} - newLink := &model.RelationLink{ - Key: "newLink", - Format: model.RelationFormat_shorttext, - } - - // when - s.AddRelationLinks(newLink) - - // then - assert.True(t, s.relationLinks.Has("newLink")) - }) - t.Run("add existing link", func(t *testing.T) { - // given - s := &State{} - newLink := &model.RelationLink{ - Key: "existingLink", - Format: model.RelationFormat_shorttext, - } - - // when - s.AddRelationLinks(newLink) - s.AddRelationLinks(newLink) - - // then - assert.True(t, s.relationLinks.Has("existingLink")) - assert.Len(t, s.relationLinks, 1) - }) -} - func TestFilter(t *testing.T) { t.Run("remove blocks", func(t *testing.T) { // given @@ -2942,24 +2738,6 @@ func TestFilter(t *testing.T) { bundle.RelationKeyAssignee: domain.String("assignee"), bundle.RelationKeyResolvedLayout: domain.Int64(model.ObjectType_todo), })) - st.AddRelationLinks(&model.RelationLink{ - Key: bundle.RelationKeyCoverType.String(), - Format: model.RelationFormat_number, - }, - &model.RelationLink{ - Key: bundle.RelationKeyName.String(), - Format: model.RelationFormat_longtext, - }, - &model.RelationLink{ - Key: bundle.RelationKeyAssignee.String(), - Format: model.RelationFormat_object, - }, - &model.RelationLink{ - Key: bundle.RelationKeyResolvedLayout.String(), - Format: model.RelationFormat_number, - }, - ) - // when filteredState := st.Filter(&Filters{RemoveBlocks: true}) @@ -2979,24 +2757,6 @@ func TestFilter(t *testing.T) { bundle.RelationKeyAssignee: domain.String("assignee"), bundle.RelationKeyResolvedLayout: domain.Int64(model.ObjectType_todo), })) - st.AddRelationLinks(&model.RelationLink{ - Key: bundle.RelationKeyCoverType.String(), - Format: model.RelationFormat_number, - }, - &model.RelationLink{ - Key: bundle.RelationKeyName.String(), - Format: model.RelationFormat_longtext, - }, - &model.RelationLink{ - Key: bundle.RelationKeyAssignee.String(), - Format: model.RelationFormat_object, - }, - &model.RelationLink{ - Key: bundle.RelationKeyResolvedLayout.String(), - Format: model.RelationFormat_number, - }, - ) - // when filteredState := st.Filter(&Filters{RelationsWhiteList: map[model.ObjectTypeLayout][]domain.RelationKey{ model.ObjectType_todo: {bundle.RelationKeyAssignee}, @@ -3005,8 +2765,6 @@ func TestFilter(t *testing.T) { // then assert.Equal(t, filteredState.details.Len(), 1) assert.Equal(t, filteredState.localDetails.Len(), 0) - assert.Len(t, filteredState.relationLinks, 1) - assert.Equal(t, bundle.RelationKeyAssignee.String(), filteredState.relationLinks[0].Key) }) t.Run("empty white list relations", func(t *testing.T) { // given @@ -3020,24 +2778,6 @@ func TestFilter(t *testing.T) { bundle.RelationKeyAssignee: domain.String("assignee"), bundle.RelationKeyResolvedLayout: domain.Int64(model.ObjectType_todo), })) - st.AddRelationLinks(&model.RelationLink{ - Key: bundle.RelationKeyCoverType.String(), - Format: model.RelationFormat_number, - }, - &model.RelationLink{ - Key: bundle.RelationKeyName.String(), - Format: model.RelationFormat_longtext, - }, - &model.RelationLink{ - Key: bundle.RelationKeyAssignee.String(), - Format: model.RelationFormat_object, - }, - &model.RelationLink{ - Key: bundle.RelationKeyResolvedLayout.String(), - Format: model.RelationFormat_number, - }, - ) - // when filteredState := st.Filter(&Filters{RelationsWhiteList: map[model.ObjectTypeLayout][]domain.RelationKey{ model.ObjectType_todo: {}, @@ -3046,6 +2786,5 @@ func TestFilter(t *testing.T) { // then assert.Equal(t, filteredState.details.Len(), 0) assert.Equal(t, filteredState.localDetails.Len(), 0) - assert.Len(t, filteredState.relationLinks, 0) }) } diff --git a/core/block/import/common/objectcreator/objectcreator.go b/core/block/import/common/objectcreator/objectcreator.go index 611e9c6bac..63d592d479 100644 --- a/core/block/import/common/objectcreator/objectcreator.go +++ b/core/block/import/common/objectcreator/objectcreator.go @@ -201,7 +201,6 @@ func (oc *ObjectCreator) injectImportDetails(sn *common.Snapshot, origin objecto sn.Snapshot.Data.Details.SetInt64(bundle.RelationKeyOrigin, int64(origin.Origin)) sn.Snapshot.Data.Details.SetInt64(bundle.RelationKeyImportType, int64(origin.ImportType)) - // we don't need to inject relatonLinks, they will be automatically injected for bundled relations } func (oc *ObjectCreator) updateExistingObject(st *state.State, oldIDtoNew map[string]string, newID string) *domain.Details { diff --git a/core/block/object/objectlink/dependent_objects_test.go b/core/block/object/objectlink/dependent_objects_test.go index 2eb6661fe2..855de35f74 100644 --- a/core/block/object/objectlink/dependent_objects_test.go +++ b/core/block/object/objectlink/dependent_objects_test.go @@ -227,7 +227,6 @@ func TestState_DepSmartIdsLinksAndRelations(t *testing.T) { Format: model.RelationFormat_object, }, } - stateWithLinks.AddRelationLinks(relations...) stateWithLinks.AddDetails(domain.NewDetailsFromMap(map[domain.RelationKey]domain.Value{ "relation1": domain.String("image_with_cute_kitten"), "relation2": domain.String("Important"), @@ -259,10 +258,6 @@ func TestState_DepSmartIdsLinksAndRelations(t *testing.T) { t.Run("save backlinks", func(t *testing.T) { st := stateWithLinks.Copy() st.SetDetail(bundle.RelationKeyBacklinks, domain.StringList([]string{"link1"})) - st.AddRelationLinks(&model.RelationLink{ - Key: bundle.RelationKeyBacklinks.String(), - Format: model.RelationFormat_object, - }) objectIDs := DependentObjectIDs(st, converter, fetcher, Flags{Details: true}) assert.Len(t, objectIDs, 1) assert.Contains(t, objectIDs, "link1") @@ -270,16 +265,12 @@ func TestState_DepSmartIdsLinksAndRelations(t *testing.T) { t.Run("skip backlinks", func(t *testing.T) { st := stateWithLinks.Copy() st.SetDetail(bundle.RelationKeyBacklinks, domain.StringList([]string{"link1"})) - st.AddRelationLinks(&model.RelationLink{ - Key: bundle.RelationKeyBacklinks.String(), - Format: model.RelationFormat_object, - }) objectIDs := DependentObjectIDs(st, converter, fetcher, Flags{Details: true, NoBackLinks: true}) assert.Len(t, objectIDs, 0) }) } -func buildStateWithLinks() *state.State { +func buildStateWithLinks() (*state.State, []*model.RelationLink) { stateWithLinks := state.NewDoc("root", map[string]simple.Block{ "root": simple.New(&model.Block{ Id: "root", @@ -344,21 +335,20 @@ func buildStateWithLinks() *state.State { Format: model.RelationFormat_date, }, } - stateWithLinks.AddRelationLinks(relations...) stateWithLinks.SetDetail("relation1", domain.StringList([]string{"file"})) stateWithLinks.SetDetail("relation2", domain.StringList([]string{"option1"})) stateWithLinks.SetDetail("relation3", domain.StringList([]string{"option2"})) stateWithLinks.SetDetail("relation4", domain.StringList([]string{"option3"})) stateWithLinks.SetDetail("relation5", domain.Int64(time.Now().Unix())) - return stateWithLinks + return stateWithLinks, relations } func TestState_DepSmartIdsLinksDetailsAndRelations(t *testing.T) { // given - stateWithLinks := buildStateWithLinks() + stateWithLinks, relations := buildStateWithLinks() converter := &fakeConverter{} - fetcher := setupFetcher(t, stateWithLinks.PickRelationLinks()) + fetcher := setupFetcher(t, relations) t.Run("blocks option is turned on: get ids from blocks", func(t *testing.T) { objectIDs := DependentObjectIDs(stateWithLinks, converter, fetcher, Flags{Blocks: true}) @@ -395,7 +385,6 @@ func TestState_DepSmartIdsLinksCreatorModifierWorkspace(t *testing.T) { Format: model.RelationFormat_object, }, } - stateWithLinks.AddRelationLinks(relations...) stateWithLinks.SetDetail("relation1", domain.Int64(time.Now().Unix())) stateWithLinks.SetDetail(bundle.RelationKeyCreatedDate, domain.Int64(time.Now().Unix())) stateWithLinks.SetDetail(bundle.RelationKeyCreator, domain.String("creator")) @@ -419,7 +408,7 @@ func TestState_DepSmartIdsObjectTypes(t *testing.T) { stateWithLinks := state.NewDoc("root", nil).(*state.State) stateWithLinks.SetObjectTypeKey(bundle.TypeKeyPage) converter := &fakeConverter{} - fetcher := setupFetcher(t, stateWithLinks.PickRelationLinks()) + fetcher := setupFetcher(t, nil) t.Run("all options are turned off", func(t *testing.T) { objectIDs := DependentObjectIDs(stateWithLinks, converter, fetcher, Flags{}) @@ -440,9 +429,9 @@ func TestDependentObjectIDsPerSpace(t *testing.T) { spc2 = "space2" spc3 = "space3" ) - st := buildStateWithLinks() + st, relations := buildStateWithLinks() converter := &fakeConverter{} - fetcher := setupFetcher(t, st.PickRelationLinks()) + fetcher := setupFetcher(t, relations) resolver := &fakeSpaceIdResolver{idsToSpaceIds: map[string]string{ "objectID": spc1, "objectID2": spc2, diff --git a/core/block/source/sourceimpl/source.go b/core/block/source/sourceimpl/source.go index 1a5b4e71c8..6dee5758e3 100644 --- a/core/block/source/sourceimpl/source.go +++ b/core/block/source/sourceimpl/source.go @@ -444,9 +444,7 @@ func (s *treeSource) buildChange(params source.PushChangeParams) (c *pb.Change) Details: params.State.Details().ToProto(), ObjectTypes: domain.MarshalTypeKeys(params.State.ObjectTypeKeys()), Collections: params.State.Store(), - // TODO: GO-4284 We need to use PickRelationLinks here because we build a state. - // Changes on RelationLinks could go to old clients - RelationLinks: params.State.PickRelationLinks(), + // GO-4284: object-level relationLinks were removed; snapshots no longer carry them. Key: params.State.UniqueKeyInternal(), OriginalCreatedTimestamp: params.State.OriginalCreatedTimestamp(), FileInfo: params.State.GetFileInfo().ToModel(), diff --git a/core/block/template/templateimpl/impl_test.go b/core/block/template/templateimpl/impl_test.go index f23e8d4b20..2a76c9363b 100644 --- a/core/block/template/templateimpl/impl_test.go +++ b/core/block/template/templateimpl/impl_test.go @@ -561,7 +561,6 @@ func TestService_TemplateNamePrefill(t *testing.T) { // then assert.NoError(t, err) assert.Equal(t, customName, st.Details().GetString(bundle.RelationKeyName), "custom name should take precedence over template name") - assert.True(t, st.PickRelationLinks().Has(bundle.RelationKeyName.String()), "Name relation link should exist") }) t.Run("prefill type Empty with custom details - custom name is applied", func(t *testing.T) { @@ -578,7 +577,6 @@ func TestService_TemplateNamePrefill(t *testing.T) { // then assert.NoError(t, err) assert.Equal(t, customName, st.Details().GetString(bundle.RelationKeyName), "custom name should be applied when prefill type is Empty") - assert.True(t, st.PickRelationLinks().Has(bundle.RelationKeyName.String()), "Name relation link should exist") }) t.Run("prefill type FromTemplateName with empty name in details - template name should be preserved", func(t *testing.T) { @@ -623,7 +621,6 @@ func TestService_TemplateNamePrefill(t *testing.T) { assert.NoError(t, err) assert.Equal(t, blankTemplateId, st.RootId()) assert.Equal(t, customName, st.Details().GetString(bundle.RelationKeyName), "custom name should be applied to blank template") - assert.True(t, st.PickRelationLinks().Has(bundle.RelationKeyName.String()), "Name relation link should exist") }) t.Run("blank template with empty name in details - name should remain empty", func(t *testing.T) { diff --git a/core/debug/exporter/treeimporter.go b/core/debug/exporter/treeimporter.go index 019051e120..abae54e376 100644 --- a/core/debug/exporter/treeimporter.go +++ b/core/debug/exporter/treeimporter.go @@ -25,9 +25,11 @@ type TreeJson struct { } type JsonChange struct { - Id string `json:"id"` - Ord int `json:"ord"` - Change MarshalledJsonChange `json:"change"` + Id string `json:"id"` + Ord int `json:"ord"` + Identity string `json:"identity"` + Timestamp int64 `json:"timestamp"` + Change MarshalledJsonChange `json:"change"` } type MarshalledJsonChange struct { @@ -87,10 +89,16 @@ func (t *treeImporter) Json() (treeJson TreeJson, err error) { return true } model := change.Model.(*pb.Change) + identity := "" + if change.Identity != nil { + identity = change.Identity.Account() + } ch := JsonChange{ - Id: change.Id, - Ord: i, - Change: MarshalledJsonChange{JsonString: pbtypes.Sprint(model)}, + Id: change.Id, + Ord: i, + Identity: identity, + Timestamp: change.Timestamp, + Change: MarshalledJsonChange{JsonString: pbtypes.Sprint(model)}, } treeJson.Changes = append(treeJson.Changes, ch) return true diff --git a/core/history/history.go b/core/history/history.go index 4a9b177d32..022b0d59c9 100644 --- a/core/history/history.go +++ b/core/history/history.go @@ -23,7 +23,6 @@ import ( "encoding/hex" "errors" "fmt" - "slices" "strings" "sync" "time" @@ -52,7 +51,6 @@ import ( "github.com/anyproto/anytype-heart/pkg/lib/pb/model" "github.com/anyproto/anytype-heart/space" "github.com/anyproto/anytype-heart/space/clientspace" - "github.com/anyproto/anytype-heart/util/pbtypes" ) const CName = "history" @@ -329,7 +327,6 @@ func filterHistoryEvents(msg []simple.EventMessage) []*pb.EventMessage { func isSuitableChange(message simple.EventMessage) bool { return isDataviewChange(message) || isDetailsChange(message) || - isRelationsChange(message) || isBlockPropertiesChange(message) || isSimpleBlockChange(message) || isBasicBlockChange(message) @@ -348,39 +345,6 @@ func isDataviewChange(message simple.EventMessage) bool { message.Msg.GetBlockDataviewTargetObjectIdSet() != nil } -func isRelationsChange(message simple.EventMessage) bool { - filterLocalAndDerivedRelations(message.Msg.GetObjectRelationsAmend()) - filterLocalAndDerivedRelationsByKey(message.Msg.GetObjectRelationsRemove()) - return (message.Msg.GetObjectRelationsAmend() != nil && len(message.Msg.GetObjectRelationsAmend().RelationLinks) > 0) || - (message.Msg.GetObjectRelationsRemove() != nil && len(message.Msg.GetObjectRelationsRemove().RelationKeys) > 0) -} - -func filterLocalAndDerivedRelationsByKey(removedRelations *pb.EventObjectRelationsRemove) { - if removedRelations == nil { - return - } - var relKeysWithoutLocal []string - for _, key := range removedRelations.RelationKeys { - if !slices.Contains(bundle.LocalAndDerivedRelationKeys, domain.RelationKey(key)) { - relKeysWithoutLocal = append(relKeysWithoutLocal, key) - } - } - removedRelations.RelationKeys = relKeysWithoutLocal -} - -func filterLocalAndDerivedRelations(addedRelations *pb.EventObjectRelationsAmend) { - if addedRelations == nil { - return - } - var relLinksWithoutLocal pbtypes.RelationLinks - for _, link := range addedRelations.RelationLinks { - if !slices.Contains(bundle.LocalAndDerivedRelationKeys, domain.RelationKey(link.Key)) { - relLinksWithoutLocal = relLinksWithoutLocal.Append(link) - } - } - addedRelations.RelationLinks = relLinksWithoutLocal -} - func isDetailsChange(message simple.EventMessage) bool { return message.Msg.GetObjectDetailsAmend() != nil || message.Msg.GetObjectDetailsUnset() != nil diff --git a/core/history/history_test.go b/core/history/history_test.go index 57193fd63d..816a6b0a91 100644 --- a/core/history/history_test.go +++ b/core/history/history_test.go @@ -706,9 +706,11 @@ func TestHistory_DiffVersions(t *testing.T) { // then assert.Nil(t, err) - assert.Len(t, changes, 4) + // GO-4284: relation-link add/remove changes no longer surface in diffs; + // only the two detail changes (set "key", unset "key2") remain. + assert.Len(t, changes, 2) }) - t.Run("object diff -local relations changes", func(t *testing.T) { + t.Run("object diff - relation-link-only changes produce no diff", func(t *testing.T) { // given accountKeys, _ := accountdata.NewRandom() account := accountKeys.SignKey.GetPublic() @@ -761,11 +763,9 @@ func TestHistory_DiffVersions(t *testing.T) { // then assert.Nil(t, err) - assert.Len(t, changes, 2) - assert.Len(t, changes[1].GetObjectRelationsAmend().RelationLinks, 1) - assert.Equal(t, changes[1].GetObjectRelationsAmend().RelationLinks[0].Key, relationKey) - assert.Len(t, changes[0].GetObjectRelationsRemove().RelationKeys, 1) - assert.Equal(t, changes[0].GetObjectRelationsRemove().RelationKeys[0], relationKey1) + // GO-4284: changes that only add/remove relation links (no detail values) + // no longer produce diff events. + assert.Len(t, changes, 0) }) t.Run("object diff - no changes", func(t *testing.T) { diff --git a/docs/GO-4284-relationlinks-removal.md b/docs/GO-4284-relationlinks-removal.md new file mode 100644 index 0000000000..c1d1d968e5 --- /dev/null +++ b/docs/GO-4284-relationlinks-removal.md @@ -0,0 +1,111 @@ +# GO-4284 — Remove deprecated object-level relationLinks + +## Why + +Object-level `relationLinks` (the `model.RelationLink{Key,Format}` list attached to an +object, distinct from dataview relations) are **no longer read by any client or by the +local indexer**. They are kept alive only by auto-add writers. + +This causes a real bug: when one device sets a detail whose relation link is missing +(e.g. `discussionId`), every *other* online participant's device independently runs the +link reconciliation, emits a `RelationAdd` change **under its own identity**, and pushes +it. Result: a single local edit produces phantom history entries authored by every other +member of the space (observed in version history: 6× `relationAdd discussionId` at the +same second from 4 different identities). + +The objectstore already derives relation keys from **details**, not links +(`FetchRelationByLinks` has zero live callers; `state.HasRelation`/`iterateKeys` read +details keys). So the links are dead weight. + +## Scope + +**IN scope:** object-level `state.relationLinks` and everything that auto-adds / reads / +serializes it. + +**OUT of scope:** dataview relation links (`model.BlockContentDataview.RelationLinks`, +`core/block/simple/dataview`, `core/block/editor/dataview`) — separate, user-driven +feature. `bundle.HasRelation`, schema `Type.HasRelation`, `ObjectPath.HasRelation` are +unrelated despite the name. + +## Backward compatibility + +- Keep the protobuf types (`pb.ChangeRelationAdd/Remove`, + `model.SmartBlockSnapshotBase.RelationLinks`, `EventObjectRelationsAmend/Remove`) so + existing trees still parse. +- Keep `changeRelationAdd` / `changeRelationRemove` apply handlers as **no-ops** (parse + but don't store), so old changes load without error. +- Stop *populating* snapshot relation links on write. + +--- + +## Inventory + +### A. Core state machinery — `core/block/editor/state/` +- `state.go:124` — field `relationLinks pbtypes.RelationLinks` +- `state.go:174-202` — `filterRelations` (filters relationLinks) +- `state.go:703-735` — Apply diff: emits `ObjectRelationsAmend` / `ObjectRelationsRemove` + events + undo `RelationLinks` (**write path into tree**) +- `state.go:793-794, 852-853` — parent propagation of relationLinks +- `state.go:960` — StringDebug loop over relationLinks +- `state.go:989-993` — `SetDetailAndBundledRelation` (calls `AddBundledRelationLinks`) +- `state.go:1326` — `Copy()` copies relationLinks +- `state.go:1692-1699` — `AddRelationLinks` +- `state.go:1703-1726` — `PickRelationLinks`, `pickRelationLinks`, `getRelationLinks` +- `state.go:1798-1811` — `AddBundledRelationLinks`, `AddBundledRelationLinks` impl +- `details.go:164-...` — `RemoveRelation` (filters relationLinks; keep detail/featured removal) +- `change.go:85` — snapshot read into `relationLinks` +- `change.go:200-205, 280-291` — `changeRelationAdd` / `changeRelationRemove` apply handlers (→ no-op) +- `change.go:471, 551, 583-606, 626-644` — change generation: `RelationAdd`/`RelationRemove` + ops + `filterLocalAndDerivedRelations[ByKey]` (**write path into tree**) + +### B. Snapshot serialization / derivation +- `core/block/source/sourceimpl/source.go:447-449` — `RelationLinks: State.PickRelationLinks()` (stop populating) ✅ DONE +- `core/block/import/common/types.go:86,102` — propagate `sn.RelationLinks` (kept: backward-compat read of old imports) + +### B2. SEPARATE, STILL-LIVE surface — `model.ObjectType.RelationLinks` (NOT removed) +This is the **object-type's recommended relations** exposed as links, a different concept +from object-level `state.relationLinks`. It is actively consumed, so it was intentionally +left in place. Removing it requires migrating these consumers to read `recommendedRelations` +details directly — a separate task: +- `pkg/lib/localstore/objectstore/spaceindex/object_type.go:54-58` — `getRelationLinksForRecommendedRelations` +- `core/relationutils/objecttype.go:21` — iterates `ot.RelationLinks` (consumer) +- `core/block/source/sourceimpl/bundledobjecttype.go:55` — iterates `ot.RelationLinks` (consumer) +- `pkg/lib/schema/{schema,type,exporter}.go`, `pkg/lib/schema/yaml/exporter.go` — schema export +- Follow-up: `core/block/undo/undo.go` `Action.RelationLinks` field is now always nil (dead, can be removed) + +### C. Object-level WRITE callers +- **`SetDetailAndBundledRelation` — 122 callers across 32 files** (top: detailsinject.go 18, + spaceview.go 14, history.go 8, filerequest.go 8, spaceinfo/* 16). Signature is identical + to `SetDetail(key, value)` → mechanical rename. +- **`AddBundledRelationLinks` — 13 callers** (smartblock.go ×4, template.go ×2, participant.go, + source.go, fileindex.go, templateimpl/impl.go, builtintemplate.go, +def) +- **`AddRelationLinks` — 10 callers** (basic/details.go ×2, basic.go, import ×3, bundledobjecttype.go, + smartblock.go, smarttest, +def) +- **`AddRelationLinksToState` — interface method** (smartblock.go iface+impl, clipboard.go caller, + smarttest) → remove from `SmartBlock` interface, regenerate mocks + +### D. READ sites +- `source.go:449` `PickRelationLinks()` (snapshot build) — covered in B +- `RemoveRelation` reads links internally — covered in A +- `pkg/lib/localstore/objectstore/spaceindex/relations.go:95` `FetchRelationByLinks` — **dead, remove** + (interface `store.go:110`, `invalid.go:194`) + +### E. Backward-compat (KEEP, make no-op) +- `changeRelationAdd` / `changeRelationRemove` handlers — parse, don't store +- pb types + `model.SmartBlockSnapshotBase.RelationLinks` — keep generated + +--- + +## Execution order (each commit `GO-4284 …`) + +1. **Stop writing links into the tree** (fixes the bug): remove `RelationAdd`/`RelationRemove` + change generation (`change.go`), the diff emit + undo (`state.go:703-735`), and stop + populating snapshot links (`source.go:449`). After this, no new link data enters any tree. +2. **Remove writers**: `SetDetailAndBundledRelation` → `SetDetail` (mass rename + delete method); + remove `AddBundledRelationLinks` / `AddRelationLinks` / `AddRelationLinksToState` + callers. +3. **Remove state field & accessors**: `relationLinks` field, `PickRelationLinks`, + `pickRelationLinks`, `getRelationLinks`, `filterRelations`, parent prop, Copy, StringDebug; + strip link logic from `RemoveRelation`. +4. **Remove derivation/serialization**: `object_type.go`, schema exporters, import propagation, + dead `FetchRelationByLinks`. +5. **Make apply handlers no-op**, keep pb for compat. Regenerate mocks. `make test`. diff --git a/pkg/lib/localstore/objectstore/spaceindex/invalid.go b/pkg/lib/localstore/objectstore/spaceindex/invalid.go index 1996a815bb..8cc87508de 100644 --- a/pkg/lib/localstore/objectstore/spaceindex/invalid.go +++ b/pkg/lib/localstore/objectstore/spaceindex/invalid.go @@ -10,7 +10,6 @@ import ( "github.com/anyproto/anytype-heart/core/relationutils" "github.com/anyproto/anytype-heart/pkg/lib/database" "github.com/anyproto/anytype-heart/pkg/lib/pb/model" - "github.com/anyproto/anytype-heart/util/pbtypes" ) type invalidStore struct { @@ -191,10 +190,6 @@ func (s *invalidStore) FetchRelationByKeys(keys ...domain.RelationKey) (relation return nil, s.err } -func (s *invalidStore) FetchRelationByLinks(links pbtypes.RelationLinks) (relations relationutils.Relations, err error) { - return nil, s.err -} - func (s *invalidStore) ListAllRelations() (relations relationutils.Relations, err error) { return nil, s.err } diff --git a/pkg/lib/localstore/objectstore/spaceindex/relations.go b/pkg/lib/localstore/objectstore/spaceindex/relations.go index b2d418b99e..d0098ce6ae 100644 --- a/pkg/lib/localstore/objectstore/spaceindex/relations.go +++ b/pkg/lib/localstore/objectstore/spaceindex/relations.go @@ -11,7 +11,6 @@ import ( "github.com/anyproto/anytype-heart/pkg/lib/core/smartblock" "github.com/anyproto/anytype-heart/pkg/lib/database" "github.com/anyproto/anytype-heart/pkg/lib/pb/model" - "github.com/anyproto/anytype-heart/util/pbtypes" ) func (s *dsObjectStore) GetRelationLink(key string) (*model.RelationLink, error) { @@ -92,14 +91,6 @@ func (s *dsObjectStore) FetchRelationByKeys(keys ...domain.RelationKey) (relatio return } -func (s *dsObjectStore) FetchRelationByLinks(links pbtypes.RelationLinks) (relations relationutils.Relations, err error) { - keys := make([]domain.RelationKey, 0, len(links)) - for _, l := range links { - keys = append(keys, domain.RelationKey(l.Key)) - } - return s.FetchRelationByKeys(keys...) -} - func (s *dsObjectStore) GetRelationById(id string) (*model.Relation, error) { det, err := s.GetDetails(id) if err != nil { diff --git a/pkg/lib/localstore/objectstore/spaceindex/store.go b/pkg/lib/localstore/objectstore/spaceindex/store.go index fc8a1ea8e1..213682fb47 100644 --- a/pkg/lib/localstore/objectstore/spaceindex/store.go +++ b/pkg/lib/localstore/objectstore/spaceindex/store.go @@ -18,7 +18,6 @@ import ( "github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore/anystorehelper" "github.com/anyproto/anytype-heart/pkg/lib/logging" "github.com/anyproto/anytype-heart/pkg/lib/pb/model" - "github.com/anyproto/anytype-heart/util/pbtypes" ) var log = logging.Logger("objectstore.spaceindex") @@ -107,7 +106,6 @@ type Store interface { GetRelationLink(key string) (*model.RelationLink, error) FetchRelationByKey(key string) (relation *relationutils.Relation, err error) FetchRelationByKeys(keys ...domain.RelationKey) (relations relationutils.Relations, err error) - FetchRelationByLinks(links pbtypes.RelationLinks) (relations relationutils.Relations, err error) ListAllRelations() (relations relationutils.Relations, err error) GetRelationById(id string) (relation *model.Relation, err error) GetRelationByKey(key string) (*model.Relation, error)