From 3f04f71f760e6e6277b60eaf993c9fba7feb9fe6 Mon Sep 17 00:00:00 2001 From: kirillston Date: Mon, 2 Jun 2025 18:58:03 +0200 Subject: [PATCH 1/3] GO-5699 Fix missing versions in history show --- core/history/history.go | 2 +- core/history/history_test.go | 160 ++++++++++++++++++++--------------- 2 files changed, 95 insertions(+), 67 deletions(-) diff --git a/core/history/history.go b/core/history/history.go index a2d1d2c66..be3eb1395 100644 --- a/core/history/history.go +++ b/core/history/history.go @@ -564,7 +564,7 @@ func (h *history) buildState(id domain.FullID, versionId string) ( } st.BlocksInit(st) - if ch, e := tree.GetChange(versionId); e == nil { + if ch, e := tree.GetChange(tree.Id()); e == nil { participantId := domain.NewParticipantId(id.SpaceID, ch.Identity.Account()) ver = &pb.RpcHistoryVersion{ Id: ch.Id, diff --git a/core/history/history_test.go b/core/history/history_test.go index c3e2b6b1a..d7f27aaa6 100644 --- a/core/history/history_test.go +++ b/core/history/history_test.go @@ -3,6 +3,7 @@ package history import ( "context" "fmt" + "strings" "testing" "github.com/anyproto/any-sync/commonspace/object/accountdata" @@ -15,6 +16,7 @@ import ( "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/anyproto/anytype-heart/core/block/editor/state" @@ -1006,83 +1008,17 @@ func TestHistory_Versions(t *testing.T) { Id: "id", PreviousIds: []string{"id2"}, Identity: account, - Model: &pb.Change{ - Content: []*pb.ChangeContent{ - { - Value: &pb.ChangeContentValueOfBlockUpdate{ - BlockUpdate: &pb.ChangeBlockUpdate{ - Events: []*pb.EventMessage{ - { - Value: &pb.EventMessageValueOfBlockSetText{ - BlockSetText: &pb.EventBlockSetText{ - Id: "blockId", - Text: &pb.EventBlockSetTextText{ - Value: "new text", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, } ch1 := &objecttree.Change{ Identity: account, Id: "id1", PreviousIds: []string{"id2"}, - Model: &pb.Change{ - Content: []*pb.ChangeContent{ - { - Value: &pb.ChangeContentValueOfBlockUpdate{ - BlockUpdate: &pb.ChangeBlockUpdate{ - Events: []*pb.EventMessage{ - { - Value: &pb.EventMessageValueOfBlockSetText{ - BlockSetText: &pb.EventBlockSetText{ - Id: "blockId", - Text: &pb.EventBlockSetTextText{ - Value: "some text", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, } ch2 := &objecttree.Change{ Id: "id2", Identity: account, - Model: &pb.Change{ - Content: []*pb.ChangeContent{ - { - Value: &pb.ChangeContentValueOfBlockUpdate{ - BlockUpdate: &pb.ChangeBlockUpdate{ - Events: []*pb.EventMessage{ - { - Value: &pb.EventMessageValueOfBlockSetText{ - BlockSetText: &pb.EventBlockSetText{ - Id: "blockId", - Text: &pb.EventBlockSetTextText{ - Value: "new text some text", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, } currChange := []*objecttree.Change{ @@ -1169,6 +1105,57 @@ func TestHistory_injectLocalDetails(t *testing.T) { }) } +func TestHistory_Show(t *testing.T) { + t.Run("show history when parallel editing", func(t *testing.T) { + objectId := "objectId" + spaceID := "spaceID" + + accountKeys, _ := accountdata.NewRandom() + account := accountKeys.SignKey.GetPublic() + + ch := &objecttree.Change{ + Id: "id", + PreviousIds: []string{objectId}, + Identity: account, + Model: &pb.Change{}, + } + + ch1 := &objecttree.Change{ + Identity: account, + Id: "id1", + PreviousIds: []string{objectId}, + Model: &pb.Change{}, + } + + root := &objecttree.Change{ + Id: objectId, + Identity: account, + Model: &pb.Change{}, + } + + changesMap := map[string][]*objecttree.Change{ + "id1 id": {root, ch1}, + "id id1": {root, ch}, + objectId: {root, ch, ch1}, + } + + h := newFixtureShow(t, changesMap, objectId, spaceID) + + // when + fullId := domain.FullID{ObjectID: objectId, SpaceID: spaceID} + resp, err := h.Versions(fullId, objectId, 10, false) + require.Nil(t, err) + require.Len(t, resp, 2) + + view, version, err := h.Show(fullId, resp[0].Id) + + // then + assert.Nil(t, err) + assert.NotNil(t, view) + assert.NotNil(t, version) + }) +} + type historyFixture struct { *history space *mock_clientspace.MockSpace @@ -1225,6 +1212,47 @@ func newFixtureDiffVersions(t *testing.T, } } +func newFixtureShow(t *testing.T, changes map[string][]*objecttree.Change, objectId, spaceID string) *historyFixture { + spaceService := mock_space.NewMockService(t) + space := mock_clientspace.NewMockSpace(t) + ctrl := gomock.NewController(t) + treeBuilder := mock_objecttreebuilder.NewMockTreeBuilder(ctrl) + + if len(changes) > 0 { + treeBuilder.EXPECT().BuildHistoryTree(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, id string, opts objecttreebuilder.HistoryTreeOpts) (objecttree.HistoryTree, error) { + assert.True(t, opts.Include) + assert.Equal(t, objectId, id) + versionId := strings.Join(opts.Heads, " ") + + chs, ok := changes[versionId] + assert.True(t, ok) + + return &historyStub{ + objectId: objectId, + changes: chs, + }, nil + }).AnyTimes() + space.EXPECT().TreeBuilder().Return(treeBuilder) + space.EXPECT().Id().Return(spaceID).Maybe() + spaceService.EXPECT().Get(context.Background(), spaceID).Return(space, nil) + } + + space.EXPECT().GetTypeIdByKey(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, key domain.TypeKey) (string, error) { + return key.URL(), nil + }) + + h := &history{ + objectStore: objectstore.NewStoreFixture(t), + spaceService: spaceService, + heads: map[string]string{}, + } + return &historyFixture{ + history: h, + space: space, + treeBuilder: treeBuilder, + } +} + func configureTreeBuilder(treeBuilder *mock_objecttreebuilder.MockTreeBuilder, objectId, currVersionId, spaceID string, expectedChanges []*objecttree.Change, From c186f46bb6c906eae403f548bfb5b735a1253ece Mon Sep 17 00:00:00 2001 From: kirillston Date: Thu, 5 Jun 2025 11:52:45 +0200 Subject: [PATCH 2/3] GO-5699 Take version from last head --- core/history/history.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/history/history.go b/core/history/history.go index be3eb1395..3637f70d9 100644 --- a/core/history/history.go +++ b/core/history/history.go @@ -564,7 +564,8 @@ func (h *history) buildState(id domain.FullID, versionId string) ( } st.BlocksInit(st) - if ch, e := tree.GetChange(tree.Id()); e == nil { + heads := tree.Heads() + if ch, e := tree.GetChange(heads[len(heads)-1]); e == nil { participantId := domain.NewParticipantId(id.SpaceID, ch.Identity.Account()) ver = &pb.RpcHistoryVersion{ Id: ch.Id, From 12b7f460eb2bf50a6acb50446043f056c33d74ff Mon Sep 17 00:00:00 2001 From: kirillston Date: Fri, 6 Jun 2025 11:51:55 +0200 Subject: [PATCH 3/3] GO-5699 Fix test --- core/history/history_test.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/core/history/history_test.go b/core/history/history_test.go index d7f27aaa6..c1ce7d73e 100644 --- a/core/history/history_test.go +++ b/core/history/history_test.go @@ -34,6 +34,7 @@ import ( type historyStub struct { changes []*objecttree.Change + heads []string objectId string } @@ -87,7 +88,7 @@ func (h historyStub) ChangeInfo() *treechangeproto.TreeChangeInfo { } } -func (h historyStub) Heads() []string { return nil } +func (h historyStub) Heads() []string { return h.heads } func (h historyStub) Root() *objecttree.Change { return &objecttree.Change{ @@ -1133,13 +1134,14 @@ func TestHistory_Show(t *testing.T) { Model: &pb.Change{}, } + heads := []string{"id", "id1"} changesMap := map[string][]*objecttree.Change{ "id1 id": {root, ch1}, "id id1": {root, ch}, objectId: {root, ch, ch1}, } - h := newFixtureShow(t, changesMap, objectId, spaceID) + h := newFixtureShow(t, changesMap, heads, objectId, spaceID) // when fullId := domain.FullID{ObjectID: objectId, SpaceID: spaceID} @@ -1212,7 +1214,7 @@ func newFixtureDiffVersions(t *testing.T, } } -func newFixtureShow(t *testing.T, changes map[string][]*objecttree.Change, objectId, spaceID string) *historyFixture { +func newFixtureShow(t *testing.T, changes map[string][]*objecttree.Change, heads []string, objectId, spaceID string) *historyFixture { spaceService := mock_space.NewMockService(t) space := mock_clientspace.NewMockSpace(t) ctrl := gomock.NewController(t) @@ -1230,6 +1232,7 @@ func newFixtureShow(t *testing.T, changes map[string][]*objecttree.Change, objec return &historyStub{ objectId: objectId, changes: chs, + heads: heads, }, nil }).AnyTimes() space.EXPECT().TreeBuilder().Return(treeBuilder) @@ -1265,6 +1268,7 @@ func configureTreeBuilder(treeBuilder *mock_objecttreebuilder.MockTreeBuilder, }).Return(&historyStub{ objectId: objectId, changes: expectedChanges, + heads: []string{currVersionId}, }, nil) space.EXPECT().TreeBuilder().Return(treeBuilder) space.EXPECT().Id().Return(spaceID).Maybe()