Repository navigation
Conversation
Every external output port of an operator that keeps its result is stored, but results were only ever read from the first port, so a Split's second output or an If's True branch could not be shown. A pagination request can now name the output port to read, with the first port as the default, and the reply carries the port it read and that port's row count. The live result updates keep following the first port, so a client paging another port takes the count from the reply. The result store's count per operator now comes from the first port too; it was built from every stored port, so a terminal Split's second output could replace its first output's count. On the frontend, the result service gives each extra port its own pagination service, which names its port in its requests, keeps no page cache and takes its row count from each reply, and every port's service takes its schema only from replies to its own requests. The result table and its row detail can show any port. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Switching the table to another output port left the previous port's rows on screen when the new port was empty, with the loading state never ending, and a late reply for the previous port could replace the new port's rows. A port change now starts from an empty table, a reply for an operator or port no longer shown is dropped, and an empty page ends the loading. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…canvas Resting the pointer on an operator for half a second shows a card beside it with the operator's first rows and its size, or its error, or how to keep a result the run did not keep. A pointer passing over, dragging, or a click opens nothing, and the card lingers a moment so the pointer can move into it. An operator with several outputs says the rows are the first output's. The preview can be turned off under Layers, and stays off while the heat-map overlay is on. The first rows come from a request of their own, so a preview never moves the result table's page or reads its cache. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tput port Pinning the hover card opens a window beside the operator with its whole result table, tied to it by a dashed line. Several windows can be open at once; each can be dragged and resized, and follows its operator when the operator or the canvas moves. An operator with more than one output gets a tab per output port in its window. The first port is the one the running execution reports on; another port is read through the port-aware result service when its tab is shown. The table in a window measures what it draws around its rows, the search bar, header, statistics and pager, and fits as many rows as the rest of the window allows, so the pager sits near the window's bottom at any size. The bottom panel keeps its own rule. The statistics row shows only when a column has statistics, which a port past the first never has. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
09f2b2d to
896a32a
Compare
Automated Reviewer SuggestionsBased on the
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #9063 +/- ##
============================================
+ Coverage 91.86% 91.88% +0.02%
+ Complexity 5022 4979 -43
============================================
Files 1277 1279 +2
Lines 56155 56138 -17
Branches 7310 7285 -25
============================================
- Hits 51585 51581 -4
- Misses 2740 2742 +2
+ Partials 1830 1815 -15
*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:
|
Resolve the conflicts with apache#8766: a page with no rows takes its columns from the stored schema, and the reply still carries the port's total count and is dropped when it belongs to another operator or port. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🔴 | bs=10 sw=10 sl=64 | 378 | 0.231 | 26,071/33,964/33,964 us | 🟢 -15.9% / 🔴 +177.8% |
| 🟢 | bs=100 sw=10 sl=64 | 833 | 0.508 | 118,244/141,446/141,446 us | 🟢 -13.4% / 🔴 +62.3% |
| 🔴 | bs=1000 sw=10 sl=64 | 957 | 0.584 | 1,043,456/1,184,143/1,184,143 us | 🔴 +5.4% / 🔴 +44.8% |
Baseline details
Latest main 94914a0 from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 378 tuples/sec | 397 tuples/sec | 1,019 tuples/sec | -4.8% | -62.9% |
| bs=10 sw=10 sl=64 | MB/s | 0.231 MB/s | 0.242 MB/s | 0.622 MB/s | -4.5% | -62.9% |
| bs=10 sw=10 sl=64 | p50 | 26,071 us | 22,978 us | 10,144 us | +13.5% | +157.0% |
| bs=10 sw=10 sl=64 | p95 | 33,964 us | 40,389 us | 12,225 us | -15.9% | +177.8% |
| bs=10 sw=10 sl=64 | p99 | 33,964 us | 40,389 us | 15,527 us | -15.9% | +118.7% |
| bs=100 sw=10 sl=64 | throughput | 833 tuples/sec | 839 tuples/sec | 1,371 tuples/sec | -0.7% | -39.2% |
| bs=100 sw=10 sl=64 | MB/s | 0.508 MB/s | 0.512 MB/s | 0.837 MB/s | -0.8% | -39.3% |
| bs=100 sw=10 sl=64 | p50 | 118,244 us | 114,028 us | 79,910 us | +3.7% | +48.0% |
| bs=100 sw=10 sl=64 | p95 | 141,446 us | 163,399 us | 87,155 us | -13.4% | +62.3% |
| bs=100 sw=10 sl=64 | p99 | 141,446 us | 163,399 us | 106,643 us | -13.4% | +32.6% |
| bs=1000 sw=10 sl=64 | throughput | 957 tuples/sec | 951 tuples/sec | 1,415 tuples/sec | +0.6% | -32.4% |
| bs=1000 sw=10 sl=64 | MB/s | 0.584 MB/s | 0.581 MB/s | 0.864 MB/s | +0.5% | -32.4% |
| bs=1000 sw=10 sl=64 | p50 | 1,043,456 us | 1,054,790 us | 780,407 us | -1.1% | +33.7% |
| bs=1000 sw=10 sl=64 | p95 | 1,184,143 us | 1,123,975 us | 817,814 us | +5.4% | +44.8% |
| bs=1000 sw=10 sl=64 | p99 | 1,184,143 us | 1,123,975 us | 848,683 us | +5.4% | +39.5% |
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,529.50,200,128000,378,0.231,26071.28,33963.51,33963.51
1,100,10,64,20,2401.84,2000,1280000,833,0.508,118243.77,141446.10,141446.10
2,1000,10,64,20,20909.23,20000,12800000,957,0.584,1043456.44,1184142.97,1184142.97…nd keep it fresh Pressing an output port to drag a link now closes the card: a native capture listener on the paper replaces element/blank:pointerdown, which JointJS never emits for a magnet. Deleting the card's operator closes it and cancels a pending one, and ngOnDestroy clears both card timers. The card fetches its rows again on its operator's result updates until it shows a full preview, keeping the rows on show while it does. selectPage's default column limit is ALL_COLUMNS, as peekFirstRows' is: Number.MAX_SAFE_INTEGER fails the server's Int parse, so the row details modal's request was never answered. The heat-map test now waits out the preview delay, and a new test covers the Layers > Result preview toggle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The row details modal's column limit is a separate fix, as the review asked, so selectPage goes back to what it was before 7e4e75f. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An operator's result updates count its first port only, so a table on another port asked for its page only when paged: it kept a run's partial rows after the run, and the last run's rows after a re-run. Such a table now asks for its page again on the operator's updates, at most once a second and always for the last one, and once more when the operator completes, as the first port may stop updating before the others are filled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e is gone A pinned window kept showing the output port its tab had chosen after that port was removed, with the tabs hidden once one port was left, so only unpinning brought it back. It now shows the last port instead, and the chosen one again if it comes back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pinning from the card, unpinning a closed window, unpinning a deleted operator's window and only that one, a window's place beside its operator as the canvas moves and after a drag, and the line's three courses: to a window on the right, on the left, and above or below. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
carloea2
left a comment
There was a problem hiding this comment.
Cell downloads still use the first output.
A cell export reads the operator's first port, so on Output 2 the button downloaded Output 1's cell. It now shows only on the first port. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@carloea2 The cell download button is now hidden on outputs past the first, since the export reads port 0. Could you take another look? |
carloea2
left a comment
There was a problem hiding this comment.
The cell download fix passes locally. With current main, 72 focused tests and 7163 full-suite tests pass, with one skipped. Please refresh main and rerun the failing macOS pinned-tab checks before marking it ready.
# Conflicts: # frontend/src/app/workspace/component/workflow-editor/operator-result-preview/operator-result-preview.component.html # frontend/src/app/workspace/component/workflow-editor/operator-result-preview/operator-result-preview.component.scss # frontend/src/app/workspace/component/workflow-editor/operator-result-preview/operator-result-preview.component.ts # frontend/src/app/workspace/component/workflow-editor/workflow-editor.component.html # frontend/src/app/workspace/component/workflow-editor/workflow-editor.component.scss # frontend/src/app/workspace/component/workflow-editor/workflow-editor.component.spec.ts # frontend/src/app/workspace/component/workflow-editor/workflow-editor.component.ts
What changes were proposed in this PR?
The hover card gets a Pin button. Pinning turns it into a window beside the operator with the whole result table, tied to the operator by a dashed line. Several windows can be open at once; each can be dragged and resized, and follows its operator when it or the canvas moves.
An operator with more than one output gets a tab per output port in its window. The first port is the one the running execution reports on. Another port is read when its tab is shown, through the port-aware result service from #9054, and pages by the row count its replies carry. The execution reports a change only for the first port, so another port is read again as results arrive, at most once a second, and once more when the operator completes. If the chosen output is removed, the window shows the last one that is left. The table in a window fills the window: it measures the space its search bar, header, statistics row and pager take, and fits as many rows as are left. It shows its statistics row only when a column has statistics, which another port never has.
Any related issues, documentation, discussions?
Closes #9062. Part of #9052. Design discussed in #8842.
How was this PR tested?
A new spec for the pinned window covers its port tabs, the port it shows and the height it hands the table. New cases in the result table's spec cover filling a given height, the statistics row, and refreshing a port past the first. New cases in the editor's spec cover pinning, unpinning, unpinning a deleted operator's window, the window's position as the canvas moves, and the connector line on each side. The affected frontend specs pass. In the running app, a Split of 20 rows into 13 and 7 shows the first output's 13 rows in its first tab and the other 7 in its second, each paged correctly, and the pager ends near the window's bottom edge at any window size. A window pinned on a Split's second output during a run shows its rows when the run ends, and shows the new rows after a re-run.
Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5.5)
🤖 Generated with Claude Code