Skip to content

feat(frontend): pin an operator's result beside it, with a tab per output port - #9063

Draft
kz930 wants to merge 8 commits into
apache:mainfrom
kz930:feat/9062-pinned-result-windows
Draft

kz930 wants to merge 8 commits into
apache:mainfrom
kz930:feat/9062-pinned-result-windows

Conversation

@kz930

@kz930 kz930 commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

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 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.

pr3-2-pinned-output-1 pr3-3-pinned-output-2

This needs #9058, so the diff includes its commit and #9054's until they merge. The PR's own change is the last commit.

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 and the statistics row. 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.

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Claude Opus 5.5)

🤖 Generated with Claude Code

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>
kz930 and others added 3 commits October 20, 2026 16:37
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>
@kz930
kz930 force-pushed the feat/9062-pinned-result-windows branch from 09f2b2d to 896a32a Compare October 20, 2026 23:40
@kz930

kz930 commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

@carloea2 could you take a look at this when you have a chance? It stays a draft until #9058 merges, but its own change, the last commit, is ready for review.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @aglinxinyuan, @yangzhang75, @Ma77Ball
    You can notify them by mentioning @aglinxinyuan, @yangzhang75, @Ma77Ball in a comment.

@codecov-commenter

codecov-commenter commented Oct 21, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.65285% with 121 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.68%. Comparing base (94914a0) to head (ac7682d).
⚠️ Report is 34 commits behind head on main.

Files with missing lines Patch % Lines
...onent/workflow-editor/workflow-editor.component.ts 48.10% 36 Missing and 5 partials ⚠️
...-result-window/pinned-result-window.component.html 0.00% 29 Missing ⚠️
...ed-result-window/pinned-result-window.component.ts 52.08% 18 Missing and 5 partials ⚠️
...ent/workflow-editor/workflow-editor.component.html 44.44% 10 Missing ⚠️
...esult-preview/operator-result-preview.component.ts 89.39% 0 Missing and 7 partials ⚠️
...result-table-frame/result-table-frame.component.ts 91.11% 0 Missing and 4 partials ⚠️
...c/app/workspace/component/menu/menu.component.html 50.00% 2 Missing ⚠️
...ult-preview/operator-result-preview.component.html 95.34% 1 Missing and 1 partial ⚠️
...ervice/workflow-graph/model/joint-graph-wrapper.ts 60.00% 2 Missing ⚠️
...src/app/workspace/component/menu/menu.component.ts 66.66% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #9063      +/-   ##
============================================
- Coverage     91.82%   91.68%   -0.15%     
  Complexity     5068     5068              
============================================
  Files          1273     1276       +3     
  Lines         55339    55544     +205     
  Branches       7001     7055      +54     
============================================
+ Hits          50817    50924     +107     
- Misses         2801     2875      +74     
- Partials       1721     1745      +24     
Flag Coverage Δ *Carryforward flag
access-control-service 77.38% <ø> (-0.07%) ⬇️ Carriedforward from 896a32a
agent-service 99.14% <ø> (-0.02%) ⬇️ Carriedforward from 896a32a
amber 85.96% <100.00%> (+<0.01%) ⬆️
computing-unit-managing-service 60.48% <ø> (-1.36%) ⬇️ Carriedforward from 896a32a
config-service 87.37% <ø> (-0.13%) ⬇️ Carriedforward from 896a32a
file-service 82.01% <ø> (-0.29%) ⬇️ Carriedforward from 896a32a
frontend 96.14% <66.93%> (-0.38%) ⬇️
notebook-migration-service 83.73% <ø> (-0.04%) ⬇️ Carriedforward from 896a32a
pyamber 98.57% <ø> (+0.09%) ⬆️ Carriedforward from 896a32a
workflow-compiling-service 72.43% <ø> (-0.18%) ⬇️ Carriedforward from 896a32a

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@carloea2 carloea2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pin-window changes pass 198 focused component tests and 63 tests in real Chromium, including the port tabs and result-table sizing. Focused prettier-eslint and ESLint checks pass. No blocker found in this increment after #9058. This does not approve the later removal of result access in #9060.

kz930 and others added 4 commits October 26, 2026 14:27
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>
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Benchmark changes need a look

🟢 4 better · 🔴 3 worse · ⚪ 8 noise (<±5%) · 0 without baseline

Compared against main 94914a0 benchmarked on this same runner, so the delta is largely free of cross-runner hardware noise. The "7d avg" column still reflects the gh-pages dashboard. Treat <±5% as noise unless repeated.

Dashboard · Run

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

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

engine feature frontend Changes related to the frontend GUI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pin an operator's result beside it, with a tab per output port

3 participants