Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
feat(backend): add ability to include drafts in the entity timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
burdiyan committed May 24, 2024
1 parent 3886156 commit 12c2a66
Show file tree
Hide file tree
Showing 7 changed files with 318 additions and 214 deletions.
9 changes: 6 additions & 3 deletions backend/daemon/api/entities/v1alpha/entities.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ func (api *Server) GetEntityTimeline(ctx context.Context, in *entities.GetEntity
authorID = stmt.ColumnInt64(5)
authorBytes = stmt.ColumnBytesUnsafe(6)
deps = stmt.ColumnText(7)
isDraft = stmt.ColumnInt(8)
)

idLong := cid.NewCidV1(uint64(codec), hash).String()
Expand All @@ -188,6 +189,7 @@ func (api *Server) GetEntityTimeline(ctx context.Context, in *entities.GetEntity
Author: author,
CreateTime: timestamppb.New(hlc.Timestamp(ts).Time()),
IsTrusted: isTrusted > 0,
IsDraft: isDraft > 0,
}

if deps == "" {
Expand Down Expand Up @@ -226,7 +228,7 @@ func (api *Server) GetEntityTimeline(ctx context.Context, in *entities.GetEntity

authorHeads.Put(idLong)
return nil
}, edb.ResourcesID); err != nil {
}, edb.ResourcesID, in.IncludeDrafts); err != nil {
return err
}

Expand Down Expand Up @@ -272,7 +274,8 @@ var qGetEntityTimeline = dqb.Str(`
trusted_accounts.id > 0 AS is_trusted,
public_keys.id AS author_id,
public_keys.principal AS author,
group_concat(change_deps.parent, ' ') AS deps
group_concat(change_deps.parent, ' ') AS deps,
drafts.blob IS NOT NULL AS is_draft
FROM structural_blobs
JOIN blobs INDEXED BY blobs_metadata ON blobs.id = structural_blobs.id
JOIN public_keys ON public_keys.id = structural_blobs.author
Expand All @@ -282,7 +285,7 @@ var qGetEntityTimeline = dqb.Str(`
WHERE structural_blobs.resource IS NOT NULL
AND structural_blobs.type = 'Change'
AND structural_blobs.resource = :resource
AND drafts.blob IS NULL
AND is_draft <= :include_drafts
GROUP BY change_deps.child
ORDER BY structural_blobs.ts
`)
Expand Down
61 changes: 58 additions & 3 deletions backend/daemon/api/entities/v1alpha/entities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ func TestEntityTimeline(t *testing.T) {

e := hyper.NewEntity("fake-obj")

// c1 — c2
// / \
// c3 c4
c1, err := e.CreateChange(e.NextTimestamp(), alice.Account, aliceDelegation, map[string]any{
"name": "Alice",
})
Expand All @@ -110,7 +113,7 @@ func TestEntityTimeline(t *testing.T) {
"lastName": "Liddell",
})
require.NoError(t, err)
require.NoError(t, blobs.SaveBlob(ctx, c4))
require.NoError(t, blobs.SaveDraftBlob(ctx, e.ID(), c4))
require.NoError(t, e.ApplyChange(c4.CID, c4.Decoded.(hyper.Change)))

want := &entities.EntityTimeline{
Expand Down Expand Up @@ -144,6 +147,7 @@ func TestEntityTimeline(t *testing.T) {
CreateTime: timestamppb.New(c4.Decoded.(hyper.Change).HLCTime.Time()),
Deps: []string{c1.CID.String()},
IsTrusted: true,
IsDraft: true,
},
},
Roots: []string{c1.CID.String()},
Expand All @@ -165,8 +169,59 @@ func TestEntityTimeline(t *testing.T) {
},
}

timeline, err := api.GetEntityTimeline(ctx, &entities.GetEntityTimelineRequest{Id: string(e.ID())})
timeline, err := api.GetEntityTimeline(ctx, &entities.GetEntityTimelineRequest{Id: string(e.ID()), IncludeDrafts: true})
require.NoError(t, err)
testutil.ProtoEqual(t, want, timeline, "timeline with drafts must match")

// Now without drafts.
{
want := &entities.EntityTimeline{
Id: string(e.ID()),
Owner: alice.Account.String(),
Changes: map[string]*entities.Change{
c1.CID.String(): {
Id: c1.CID.String(),
Author: alice.Account.String(),
CreateTime: timestamppb.New(c1.Decoded.(hyper.Change).HLCTime.Time()),
Children: []string{c2.CID.String(), c3.CID.String()},
IsTrusted: true,
},
c2.CID.String(): {
Id: c2.CID.String(),
Author: alice.Account.String(),
CreateTime: timestamppb.New(c2.Decoded.(hyper.Change).HLCTime.Time()),
Deps: []string{c1.CID.String()},
IsTrusted: true,
},
c3.CID.String(): {
Id: c3.CID.String(),
Author: bob.Account.String(),
CreateTime: timestamppb.New(c3.Decoded.(hyper.Change).HLCTime.Time()),
Deps: []string{c1.CID.String()},
IsTrusted: true,
},
},
Roots: []string{c1.CID.String()},
ChangesByTime: []string{c1.CID.String(), c2.CID.String(), c3.CID.String()},
Heads: []string{c2.CID.String(), c3.CID.String()},
AuthorVersions: []*entities.AuthorVersion{
{
Author: alice.Account.String(),
Heads: []string{c2.CID.String()},
Version: strings.Join([]string{c2.CID.String()}, "."),
VersionTime: timestamppb.New(c2.Decoded.(hyper.Change).HLCTime.Time()),
},
{
Author: bob.Account.String(),
Heads: []string{c3.CID.String()},
Version: c3.CID.String(),
VersionTime: timestamppb.New(c3.Decoded.(hyper.Change).HLCTime.Time()),
},
},
}

testutil.ProtoEqual(t, want, timeline, "timeline must match")
timeline, err := api.GetEntityTimeline(ctx, &entities.GetEntityTimelineRequest{Id: string(e.ID()), IncludeDrafts: false})
require.NoError(t, err)
testutil.ProtoEqual(t, want, timeline, "timeline without drafts must match")
}
}
Loading

0 comments on commit 12c2a66

Please sign in to comment.