feat(workflow): serve the pinned copy to public viewers - #8575
yangzhang75 wants to merge 2 commits into
Conversation
A public workflow follows the author's latest content, as publishing has
always done. This adds the other state: the author pins the version they
have now, and the public copy stops moving until they pin again.
`is_public` stays the on/off switch; `published_content` is the pin, NULL
while following. `WorkflowPublishService` owns the two states, and three
endpoints expose them: POST and DELETE `/workflow/pin/{wid}` to pin and
unpin, GET `/workflow/publish-status/{wid}` for what the author is shown.
Publishing and unpublishing move through the same service, so unpublishing
drops the pin rather than leaving a private workflow carrying one.
Two paths are narrowed so a pin can hold. A save wrote the whole row back,
so a publish landing while a save was in flight was silently rolled back,
and a request body could set the publish columns itself; saves now write
only name, description and content. Creating a workflow clears the publish
columns for the same reason.
Nothing reads the pinned copy yet: every workflow is in the following
state it is in today, and nothing on screen changes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
With a version pinned, a workflow has two copies: the author's working copy and the frozen one on public show. This routes every read that serves a viewer without granted access through the frozen copy, and freezes the name and description with the graph. `WorkflowPublishService.publicCopyOf` returns the three fields as a group, so a surface cannot pick up the published graph under a title the author has not published; `WorkflowAccessResource.hasGrantedAccess` is the seam that decides which copy a caller gets. Granted access -- owner, shared, project member -- keeps tracking the author's latest, because sharing is not publishing. Name and description freeze because they are as public as the graph: if only the graph froze, a report about a title could be answered by editing the title while the pinned copy still advertised it. Routed through it: opening a workflow, the hub's read, Clone, Duplicate, `/workflow_name`, `/workflow_description` and the size a listing shows. A workflow that follows the author's latest -- every workflow today -- is served exactly what it is served now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Automated Reviewer SuggestionsBased on the
|
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| ⚪ | bs=10 sw=10 sl=64 | 401 | 0.245 | 23,913/35,709/35,709 us | ⚪ within ±5% / 🔴 +138.4% |
| 🔴 | bs=100 sw=10 sl=64 | 805 | 0.491 | 119,894/180,648/180,648 us | 🔴 +32.5% / 🔴 +80.8% |
| ⚪ | bs=1000 sw=10 sl=64 | 940 | 0.574 | 1,067,649/1,133,100/1,133,100 us | ⚪ within ±5% / 🔴 +18.1% |
Baseline details
Latest main 471e53c from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 401 tuples/sec | 414 tuples/sec | 839.58 tuples/sec | -3.1% | -52.2% |
| bs=10 sw=10 sl=64 | MB/s | 0.245 MB/s | 0.253 MB/s | 0.512 MB/s | -3.2% | -52.2% |
| bs=10 sw=10 sl=64 | p50 | 23,913 us | 24,423 us | 11,937 us | -2.1% | +100.3% |
| bs=10 sw=10 sl=64 | p95 | 35,709 us | 37,348 us | 14,976 us | -4.4% | +138.4% |
| bs=10 sw=10 sl=64 | p99 | 35,709 us | 37,348 us | 19,204 us | -4.4% | +85.9% |
| bs=100 sw=10 sl=64 | throughput | 805 tuples/sec | 849 tuples/sec | 1,096 tuples/sec | -5.2% | -26.6% |
| bs=100 sw=10 sl=64 | MB/s | 0.491 MB/s | 0.518 MB/s | 0.669 MB/s | -5.2% | -26.6% |
| bs=100 sw=10 sl=64 | p50 | 119,894 us | 116,711 us | 94,033 us | +2.7% | +27.5% |
| bs=100 sw=10 sl=64 | p95 | 180,648 us | 136,306 us | 99,939 us | +32.5% | +80.8% |
| bs=100 sw=10 sl=64 | p99 | 180,648 us | 136,306 us | 110,148 us | +32.5% | +64.0% |
| bs=1000 sw=10 sl=64 | throughput | 940 tuples/sec | 952 tuples/sec | 1,128 tuples/sec | -1.3% | -16.7% |
| bs=1000 sw=10 sl=64 | MB/s | 0.574 MB/s | 0.581 MB/s | 0.688 MB/s | -1.2% | -16.6% |
| bs=1000 sw=10 sl=64 | p50 | 1,067,649 us | 1,050,271 us | 921,191 us | +1.7% | +15.9% |
| bs=1000 sw=10 sl=64 | p95 | 1,133,100 us | 1,094,636 us | 959,735 us | +3.5% | +18.1% |
| bs=1000 sw=10 sl=64 | p99 | 1,133,100 us | 1,094,636 us | 988,604 us | +3.5% | +14.6% |
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,498.69,200,128000,401,0.245,23913.38,35708.89,35708.89
1,100,10,64,20,2484.59,2000,1280000,805,0.491,119894.10,180648.14,180648.14
2,1000,10,64,20,21272.12,20000,12800000,940,0.574,1067648.78,1133100.04,1133100.04
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #8575 +/- ##
============================================
- Coverage 92.91% 92.76% -0.16%
- Complexity 4884 4907 +23
============================================
Files 1224 1226 +2
Lines 51298 51534 +236
Branches 6322 6359 +37
============================================
+ Hits 47664 47803 +139
- Misses 2070 2156 +86
- Partials 1564 1575 +11
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
What changes were proposed in this PR?
With a version pinned, a workflow has two copies. This routes every read that serves a viewer
without granted access through the frozen one.
WorkflowAccessResource.hasGrantedAccess(wid, uid): granted access, as opposedto being able to read a workflow only because it is public. An owner or a shared user keeps
tracking the author's latest, because sharing is not publishing. Everyone else is here only
because the workflow is public, and gets the public copy.
WorkflowPublishService.PublicCopycarries the name, thedescription, the content and the default view together, and
publicCopyOfhands them out as agroup, so no surface can serve the published graph under a title the author never published, or
open a form view over a copy whose content carries no form.
Duplicate,
/workflow_name,/workflow_description, and the size a listing shows.from the author's current content, so listing or checking out versions would hand a public
viewer the drafts the pin is holding back.
canReadHistorykeeps the history open to anyonewith granted access, and to everyone while nothing is pinned — the public copy is then the
author's latest and its history is the history of what everyone can already see.
A workflow that follows the author's latest — every workflow today — is served exactly what it
is served now.
publicCopyOfreturns the working copy when nothing is frozen, so with no UI topin from yet (that arrives later in the series), nothing anyone can see changes.
Any related issues, documentation, discussions?
Closes #7939
Part of #7828. Design discussion: #7128. Stacked on #7853, which this needs and which is under
review; until that merges, this PR shows its commit too and the review here is the second one.
How was this PR tested?
22 new cases in
WorkflowPublishSpec(52 in the suite, 537 in the dashboard package):the author still opening everything they have;
still clones its working copy and a copy starts with no publish state of its own;
not, and a public workflow with nothing pinned keeps the history it has today;
The history guard was checked by mutation: restoring
hasReadAccessturns the leak case red,and the case was written from a reproduction — a stranger retrieving a version of a pinned
workflow and getting back an unpublished draft.
scalafmtCheckAllclean.Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 5)
🤖 Generated with Claude Code