Skip to content

[backport cloud/1.46] refactor(billing): unify cancel-status polling into billingOperationStore (B8 / FE-970)#13008

Merged
christian-byrne merged 1 commit into
cloud/1.46from
backport-12788-to-cloud-1.46
Jun 19, 2026
Merged

[backport cloud/1.46] refactor(billing): unify cancel-status polling into billingOperationStore (B8 / FE-970)#13008
christian-byrne merged 1 commit into
cloud/1.46from
backport-12788-to-cloud-1.46

Conversation

@comfy-pr-bot

Copy link
Copy Markdown
Member

Backport of #12788 to cloud/1.46

Automatically created by backport workflow.

…tore (B8 / FE-970) (#12788)

## Motivation

- **Why B8 exists**: two divergent BillingOp pollers poll the same
op-status endpoint with different policies (hand-rolled 2× / 5s cap / 30
attempts vs the store's 1.5× / 8s / 120s). Once B1 (FE-966) routes
personal flows through the facade, a single cancel op would be polled by
**both** — duplicate requests, with two timeout policies racing on the
same state.
- **The latent bug — silent failure on a money path**: the bespoke
poller treated timeout as a silent return, so `cancelSubscription`
resolved and the dialog showed "cancelled successfully" while the
backend op could still be pending or fail later. The root cause is
structural: the poll outcome was fire-and-forget — no caller consumed
it, so there was no channel through which a failure could surface.
- **The fix — outcome as an awaited contract**: `startOperation` returns
the terminal outcome as a `Promise<BillingOperation>`;
`cancelSubscription` awaits it and throws on any non-`succeeded`
terminal. Every outcome must now flow through the caller, making silence
structurally impossible (timeout/failure → error toast).
- **The trade-off this creates**: "the terminal promise always settles"
becomes load-bearing — the dialog's loading state hangs on it, and a
never-settling path would be worse than the old silence (a permanently
locked dialog). The terminal-promise hardening below, and its regression
tests, enforce that guarantee.

## Summary

Two divergent BillingOp pollers (hand-rolled
`useWorkspaceBilling.pollCancelStatus` vs `billingOperationStore`) are
unified into one — cancel-status polling now runs through
`billingOperationStore`; `pollCancelStatus` and its bespoke
backoff/timers/state are removed.

## Changes

- **What**: `billingOperationStore` gains `'cancel'` in `OperationType`;
`startOperation` now returns `Promise<BillingOperation>` resolving on
the terminal outcome (existing subscription / topup callers unaffected —
fire-and-forget preserved). `useWorkspaceBilling.cancelSubscription`
awaits the shared poller and throws on any non-`succeeded` terminal. One
backoff config = store's 1.5× / 8s / 120s.
- **Terminal-promise hardening**: the terminal promise always settles —
a rejected post-success status/balance refresh no longer leaves
`cancelSubscription` hanging with the dialog locked open
(`Promise.allSettled`), and a duplicate `startOperation` for an
in-flight op joins the same terminal promise instead of resolving
instantly with a `pending` snapshot (which the cancel path would read as
failure).
- **Breaking**: none — the `cancelSubscription(): Promise<void>`
contract is unchanged for `CancelSubscriptionDialogContent` /
`useBillingContext`.

## Review Focus

- **Intentional behavior change**: a cancel **timeout** is now a
terminal outcome that **throws** (`billingOperation.cancelTimeout`), so
the dialog surfaces an error toast — instead of the old silent
success-ish return (which could show success while the op was still
pending). Success / failure semantics otherwise preserved (success →
status refresh + `isSubscribed: false`; failure → throw with message).
- FE-only refactor (B8); cleanest after FE-904 but independent of it.
Relates FE-932 (shared status-refresh path).

## Tests

90 unit tests green across the four affected suites (fake timers for all
polling):

- **`billingOperationStore.test.ts` (33)** — cancel terminal outcomes
(succeeded / failed / timeout) resolve the awaited promise with the
right status + i18n message; cancel suppresses the store's toasts and
settings-dialog side effects; success refreshes status/balance and sets
`isSubscribed: false`; backoff progression, 8s cap, 2-min timeout;
transient poll errors keep polling. Regression guards for the hardening:
post-success refresh failure still settles the terminal promise
(reproduced as a hang before the fix), and a duplicate `startOperation`
joins the in-flight terminal promise instead of resolving with a
`pending` snapshot.
- **`useWorkspaceBilling.test.ts`** — `cancelSubscription` drives the
shared poller; throws the op error on `failed`, throws on `timeout`,
falls back to a generic message when `errorMessage` is absent; a failing
cancel API propagates without starting the poller.
- **`CancelSubscriptionDialogContent.test.ts` (8)** — locks the dialog
half of the behavior change: a rejected `cancelSubscription` shows an
error toast and keeps the dialog open; success closes the dialog with a
success toast.
- **`useSubscriptionCheckout.test.ts`** — unchanged, confirms
fire-and-forget callers are unaffected.

Both hardening regressions were proven red→green locally: before the fix
the terminal-hang test timed out at 5s and the duplicate-start test
resolved `pending`. Gates: vue-tsc / oxlint type-aware / eslint / oxfmt
clean; full CI green including all Playwright shards and the cloud
project. The existing `cancelSubscriptionDialog.spec.ts` e2e (@ui,
open/close/escape flows) is unchanged and green; cloud-backend e2e for
billing flows is tracked separately in FE-991.

Fixes FE-970
@comfy-pr-bot comfy-pr-bot added the backport Backporting a PR onto a release candidate label Jun 19, 2026
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jun 19, 2026
@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.24561% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...m/workspace/composables/useSubscriptionCheckout.ts 50.00% 1 Missing ⚠️
@@              Coverage Diff              @@
##             cloud/1.46   #13008   +/-   ##
=============================================
  Coverage              ?   61.86%           
=============================================
  Files                 ?     1455           
  Lines                 ?    75268           
  Branches              ?    21241           
=============================================
  Hits                  ?    46568           
  Misses                ?    28352           
  Partials              ?      348           
Flag Coverage Δ
unit 61.86% <98.24%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...tform/workspace/composables/useWorkspaceBilling.ts 99.29% <100.00%> (ø)
...platform/workspace/stores/billingOperationStore.ts 98.63% <100.00%> (ø)
...m/workspace/composables/useSubscriptionCheckout.ts 96.38% <50.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown

📦 Bundle Size

⏳ Size data collection in progress…

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 53.8 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 57.7 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 57.5 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 58.0 MB heap
large-graph-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 58.0 MB heap
large-graph-pan: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 80.1 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 68.4 MB heap
minimap-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 68.8 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 60.9 MB heap
subgraph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 53.8 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 67.2 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 139ms TBT · 76.0 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 65.5 MB heap
vue-large-graph-idle: · 58.1 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 162.4 MB heap
vue-large-graph-pan: · 58.1 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 169.7 MB heap
workflow-execution: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 62.0 MB heap

ℹ️ No baseline found — significance unavailable.

Absolute values
Metric Value
canvas-idle: avg frame time 17ms
canvas-idle: p95 frame time 17ms
canvas-idle: layout duration 0ms
canvas-idle: style recalc duration 9ms
canvas-idle: layout count 0
canvas-idle: style recalc count 11
canvas-idle: task duration 416ms
canvas-idle: script duration 24ms
canvas-idle: TBT 0ms
canvas-idle: heap used 53.8 MB
canvas-idle: DOM nodes 21
canvas-idle: event listeners 4
canvas-mouse-sweep: avg frame time 17ms
canvas-mouse-sweep: p95 frame time 17ms
canvas-mouse-sweep: layout duration 4ms
canvas-mouse-sweep: style recalc duration 41ms
canvas-mouse-sweep: layout count 12
canvas-mouse-sweep: style recalc count 73
canvas-mouse-sweep: task duration 845ms
canvas-mouse-sweep: script duration 121ms
canvas-mouse-sweep: TBT 0ms
canvas-mouse-sweep: heap used 57.7 MB
canvas-mouse-sweep: DOM nodes -93
canvas-mouse-sweep: event listeners -94
canvas-zoom-sweep: avg frame time 17ms
canvas-zoom-sweep: p95 frame time 17ms
canvas-zoom-sweep: layout duration 1ms
canvas-zoom-sweep: style recalc duration 17ms
canvas-zoom-sweep: layout count 6
canvas-zoom-sweep: style recalc count 30
canvas-zoom-sweep: task duration 360ms
canvas-zoom-sweep: script duration 27ms
canvas-zoom-sweep: TBT 0ms
canvas-zoom-sweep: heap used 57.5 MB
canvas-zoom-sweep: DOM nodes 77
canvas-zoom-sweep: event listeners 19
dom-widget-clipping: avg frame time 17ms
dom-widget-clipping: p95 frame time 17ms
dom-widget-clipping: layout duration 0ms
dom-widget-clipping: style recalc duration 9ms
dom-widget-clipping: layout count 0
dom-widget-clipping: style recalc count 12
dom-widget-clipping: task duration 379ms
dom-widget-clipping: script duration 58ms
dom-widget-clipping: TBT 0ms
dom-widget-clipping: heap used 58.0 MB
dom-widget-clipping: DOM nodes 19
dom-widget-clipping: event listeners 1
large-graph-idle: avg frame time 17ms
large-graph-idle: p95 frame time 17ms
large-graph-idle: layout duration 0ms
large-graph-idle: style recalc duration 10ms
large-graph-idle: layout count 0
large-graph-idle: style recalc count 11
large-graph-idle: task duration 573ms
large-graph-idle: script duration 107ms
large-graph-idle: TBT 0ms
large-graph-idle: heap used 58.0 MB
large-graph-idle: DOM nodes 22
large-graph-idle: event listeners 5
large-graph-pan: avg frame time 17ms
large-graph-pan: p95 frame time 17ms
large-graph-pan: layout duration 0ms
large-graph-pan: style recalc duration 21ms
large-graph-pan: layout count 0
large-graph-pan: style recalc count 70
large-graph-pan: task duration 1209ms
large-graph-pan: script duration 424ms
large-graph-pan: TBT 0ms
large-graph-pan: heap used 80.1 MB
large-graph-pan: DOM nodes 18
large-graph-pan: event listeners 6
large-graph-zoom: avg frame time 17ms
large-graph-zoom: p95 frame time 17ms
large-graph-zoom: layout duration 9ms
large-graph-zoom: style recalc duration 22ms
large-graph-zoom: layout count 60
large-graph-zoom: style recalc count 66
large-graph-zoom: task duration 1468ms
large-graph-zoom: script duration 533ms
large-graph-zoom: TBT 0ms
large-graph-zoom: heap used 68.4 MB
large-graph-zoom: DOM nodes 13
large-graph-zoom: event listeners 9
minimap-idle: avg frame time 17ms
minimap-idle: p95 frame time 17ms
minimap-idle: layout duration 0ms
minimap-idle: style recalc duration 9ms
minimap-idle: layout count 0
minimap-idle: style recalc count 10
minimap-idle: task duration 595ms
minimap-idle: script duration 107ms
minimap-idle: TBT 0ms
minimap-idle: heap used 68.8 MB
minimap-idle: DOM nodes 19
minimap-idle: event listeners 4
subgraph-dom-widget-clipping: avg frame time 17ms
subgraph-dom-widget-clipping: p95 frame time 17ms
subgraph-dom-widget-clipping: layout duration 0ms
subgraph-dom-widget-clipping: style recalc duration 13ms
subgraph-dom-widget-clipping: layout count 0
subgraph-dom-widget-clipping: style recalc count 49
subgraph-dom-widget-clipping: task duration 400ms
subgraph-dom-widget-clipping: script duration 129ms
subgraph-dom-widget-clipping: TBT 0ms
subgraph-dom-widget-clipping: heap used 60.9 MB
subgraph-dom-widget-clipping: DOM nodes 24
subgraph-dom-widget-clipping: event listeners 6
subgraph-idle: avg frame time 17ms
subgraph-idle: p95 frame time 17ms
subgraph-idle: layout duration 0ms
subgraph-idle: style recalc duration 8ms
subgraph-idle: layout count 0
subgraph-idle: style recalc count 11
subgraph-idle: task duration 434ms
subgraph-idle: script duration 21ms
subgraph-idle: TBT 0ms
subgraph-idle: heap used 53.8 MB
subgraph-idle: DOM nodes 21
subgraph-idle: event listeners 4
subgraph-mouse-sweep: avg frame time 17ms
subgraph-mouse-sweep: p95 frame time 17ms
subgraph-mouse-sweep: layout duration 5ms
subgraph-mouse-sweep: style recalc duration 41ms
subgraph-mouse-sweep: layout count 16
subgraph-mouse-sweep: style recalc count 76
subgraph-mouse-sweep: task duration 762ms
subgraph-mouse-sweep: script duration 97ms
subgraph-mouse-sweep: TBT 0ms
subgraph-mouse-sweep: heap used 67.2 MB
subgraph-mouse-sweep: DOM nodes 64
subgraph-mouse-sweep: event listeners 4
subgraph-transition-enter: avg frame time 17ms
subgraph-transition-enter: p95 frame time 17ms
subgraph-transition-enter: layout duration 12ms
subgraph-transition-enter: style recalc duration 26ms
subgraph-transition-enter: layout count 5
subgraph-transition-enter: style recalc count 17
subgraph-transition-enter: task duration 732ms
subgraph-transition-enter: script duration 29ms
subgraph-transition-enter: TBT 139ms
subgraph-transition-enter: heap used 76.0 MB
subgraph-transition-enter: DOM nodes 13833
subgraph-transition-enter: event listeners 2527
viewport-pan-sweep: avg frame time 17ms
viewport-pan-sweep: p95 frame time 17ms
viewport-pan-sweep: layout duration 0ms
viewport-pan-sweep: style recalc duration 59ms
viewport-pan-sweep: layout count 0
viewport-pan-sweep: style recalc count 251
viewport-pan-sweep: task duration 3955ms
viewport-pan-sweep: script duration 1328ms
viewport-pan-sweep: TBT 0ms
viewport-pan-sweep: heap used 65.5 MB
viewport-pan-sweep: DOM nodes 20
viewport-pan-sweep: event listeners 20
vue-large-graph-idle: avg frame time 17ms
vue-large-graph-idle: p95 frame time 17ms
vue-large-graph-idle: layout duration 0ms
vue-large-graph-idle: style recalc duration 0ms
vue-large-graph-idle: layout count 0
vue-large-graph-idle: style recalc count 0
vue-large-graph-idle: task duration 11504ms
vue-large-graph-idle: script duration 616ms
vue-large-graph-idle: TBT 0ms
vue-large-graph-idle: heap used 162.4 MB
vue-large-graph-idle: DOM nodes -3307
vue-large-graph-idle: event listeners -16472
vue-large-graph-pan: avg frame time 17ms
vue-large-graph-pan: p95 frame time 17ms
vue-large-graph-pan: layout duration 0ms
vue-large-graph-pan: style recalc duration 21ms
vue-large-graph-pan: layout count 0
vue-large-graph-pan: style recalc count 67
vue-large-graph-pan: task duration 14095ms
vue-large-graph-pan: script duration 886ms
vue-large-graph-pan: TBT 0ms
vue-large-graph-pan: heap used 169.7 MB
vue-large-graph-pan: DOM nodes -3308
vue-large-graph-pan: event listeners -16470
workflow-execution: avg frame time 17ms
workflow-execution: p95 frame time 17ms
workflow-execution: layout duration 2ms
workflow-execution: style recalc duration 33ms
workflow-execution: layout count 6
workflow-execution: style recalc count 17
workflow-execution: task duration 163ms
workflow-execution: script duration 28ms
workflow-execution: TBT 0ms
workflow-execution: heap used 62.0 MB
workflow-execution: DOM nodes 162
workflow-execution: event listeners 69
Raw data
{
  "timestamp": "2026-06-19T13:41:47.392Z",
  "gitSha": "8a97bd29809ef524b600af0ab7912b09d5985ae6",
  "branch": "backport-12788-to-cloud-1.46",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 1990.8399999999915,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 10.204,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 398.7579999999999,
      "heapDeltaBytes": -1857576,
      "heapUsedBytes": 56503056,
      "domNodes": 22,
      "jsHeapTotalBytes": 24903680,
      "scriptDurationMs": 22.467000000000002,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-idle",
      "durationMs": 2019.7840000000156,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.252999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 434.004,
      "heapDeltaBytes": -2272076,
      "heapUsedBytes": 56276964,
      "domNodes": 20,
      "jsHeapTotalBytes": 25952256,
      "scriptDurationMs": 25.46,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1898.4020000000044,
      "styleRecalcs": 74,
      "styleRecalcDurationMs": 43.059,
      "layouts": 12,
      "layoutDurationMs": 3.9880000000000004,
      "taskDurationMs": 876.4490000000001,
      "heapDeltaBytes": -13411600,
      "heapUsedBytes": 55044032,
      "domNodes": -239,
      "jsHeapTotalBytes": 21426176,
      "scriptDurationMs": 122.443,
      "eventListeners": -192,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1854.6630000000164,
      "styleRecalcs": 72,
      "styleRecalcDurationMs": 39.381,
      "layouts": 12,
      "layoutDurationMs": 3.83,
      "taskDurationMs": 813.485,
      "heapDeltaBytes": 15299996,
      "heapUsedBytes": 65964160,
      "domNodes": 54,
      "jsHeapTotalBytes": 23330816,
      "scriptDurationMs": 119.95100000000001,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1726.7180000000053,
      "styleRecalcs": 30,
      "styleRecalcDurationMs": 16.223000000000003,
      "layouts": 6,
      "layoutDurationMs": 0.548,
      "taskDurationMs": 363.513,
      "heapDeltaBytes": 1926100,
      "heapUsedBytes": 60208064,
      "domNodes": 77,
      "jsHeapTotalBytes": 24903680,
      "scriptDurationMs": 29.304999999999996,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1732.0480000000202,
      "styleRecalcs": 30,
      "styleRecalcDurationMs": 18.174999999999997,
      "layouts": 6,
      "layoutDurationMs": 0.717,
      "taskDurationMs": 356.61699999999996,
      "heapDeltaBytes": 1482212,
      "heapUsedBytes": 60376532,
      "domNodes": 76,
      "jsHeapTotalBytes": 26738688,
      "scriptDurationMs": 23.764,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 662.6009999999951,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.937000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 371.637,
      "heapDeltaBytes": 5396200,
      "heapUsedBytes": 56010936,
      "domNodes": 18,
      "jsHeapTotalBytes": 10223616,
      "scriptDurationMs": 57.001999999999995,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 603.1860000000506,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 9.715000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 387.22,
      "heapDeltaBytes": 7073908,
      "heapUsedBytes": 65693056,
      "domNodes": 20,
      "jsHeapTotalBytes": 17301504,
      "scriptDurationMs": 58.91100000000001,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666682,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2015.9699999999816,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 9.299999999999997,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 539.649,
      "heapDeltaBytes": -8843312,
      "heapUsedBytes": 60684616,
      "domNodes": 24,
      "jsHeapTotalBytes": 11939840,
      "scriptDurationMs": 100.44500000000001,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2034.592000000032,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 10.172,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 607.269,
      "heapDeltaBytes": -9090444,
      "heapUsedBytes": 60859576,
      "domNodes": 20,
      "jsHeapTotalBytes": 11939840,
      "scriptDurationMs": 113.93100000000001,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2153.618999999992,
      "styleRecalcs": 70,
      "styleRecalcDurationMs": 21.014000000000003,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1255.15,
      "heapDeltaBytes": 10861956,
      "heapUsedBytes": 83243012,
      "domNodes": 18,
      "jsHeapTotalBytes": 12640256,
      "scriptDurationMs": 426.2049999999999,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2128.7020000000325,
      "styleRecalcs": 70,
      "styleRecalcDurationMs": 20.716,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1162.639,
      "heapDeltaBytes": 11906200,
      "heapUsedBytes": 84687224,
      "domNodes": 18,
      "jsHeapTotalBytes": 11067392,
      "scriptDurationMs": 421.44599999999997,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3188.5389999999916,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 20.515999999999995,
      "layouts": 60,
      "layoutDurationMs": 8.238999999999999,
      "taskDurationMs": 1349.0549999999998,
      "heapDeltaBytes": 13947620,
      "heapUsedBytes": 68850780,
      "domNodes": 14,
      "jsHeapTotalBytes": 5767168,
      "scriptDurationMs": 489.31,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3601.54,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 22.905999999999995,
      "layouts": 60,
      "layoutDurationMs": 9.999999999999998,
      "taskDurationMs": 1586.805,
      "heapDeltaBytes": 19898388,
      "heapUsedBytes": 74554372,
      "domNodes": 12,
      "jsHeapTotalBytes": 6553600,
      "scriptDurationMs": 576.784,
      "eventListeners": 10,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2015.6370000000265,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.58,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 544.1639999999999,
      "heapDeltaBytes": -9549780,
      "heapUsedBytes": 63627748,
      "domNodes": 20,
      "jsHeapTotalBytes": 8531968,
      "scriptDurationMs": 100.98000000000002,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "minimap-idle",
      "durationMs": 2025.0959999999623,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 10.219,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 644.8799999999999,
      "heapDeltaBytes": 13663876,
      "heapUsedBytes": 80574972,
      "domNodes": 18,
      "jsHeapTotalBytes": 15523840,
      "scriptDurationMs": 113.102,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 584.1400000000476,
      "styleRecalcs": 49,
      "styleRecalcDurationMs": 12.689,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 384.66499999999996,
      "heapDeltaBytes": 6554864,
      "heapUsedBytes": 60899460,
      "domNodes": 24,
      "jsHeapTotalBytes": 12582912,
      "scriptDurationMs": 123.646,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 616.1490000000072,
      "styleRecalcs": 49,
      "styleRecalcDurationMs": 13.000000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 415.018,
      "heapDeltaBytes": 8065556,
      "heapUsedBytes": 66782936,
      "domNodes": 24,
      "jsHeapTotalBytes": 19398656,
      "scriptDurationMs": 134.42700000000002,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666682,
      "p95FrameDurationMs": 16.799999999999727
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2021.6119999999762,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 7.430000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 406.25899999999996,
      "heapDeltaBytes": -2293860,
      "heapUsedBytes": 56482692,
      "domNodes": 20,
      "jsHeapTotalBytes": 25952256,
      "scriptDurationMs": 18.442,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2000.5489999999782,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 9.271999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 461.008,
      "heapDeltaBytes": -2475128,
      "heapUsedBytes": 56337292,
      "domNodes": 22,
      "jsHeapTotalBytes": 25952256,
      "scriptDurationMs": 23.497,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1702.9890000000023,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 38.690000000000005,
      "layouts": 16,
      "layoutDurationMs": 4.372,
      "taskDurationMs": 689.3679999999999,
      "heapDeltaBytes": 12586216,
      "heapUsedBytes": 66826076,
      "domNodes": 62,
      "jsHeapTotalBytes": 25165824,
      "scriptDurationMs": 90.942,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1739.4750000000272,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 43.485,
      "layouts": 16,
      "layoutDurationMs": 4.727,
      "taskDurationMs": 834.043,
      "heapDeltaBytes": 15516140,
      "heapUsedBytes": 74099728,
      "domNodes": 65,
      "jsHeapTotalBytes": 25690112,
      "scriptDurationMs": 103.409,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 948.8089999999829,
      "styleRecalcs": 17,
      "styleRecalcDurationMs": 25.761,
      "layouts": 5,
      "layoutDurationMs": 11.730999999999998,
      "taskDurationMs": 732.34,
      "heapDeltaBytes": 4440716,
      "heapUsedBytes": 79647820,
      "domNodes": 13833,
      "jsHeapTotalBytes": 17301504,
      "scriptDurationMs": 28.772999999999993,
      "eventListeners": 2527,
      "totalBlockingTimeMs": 139,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8188.413000000026,
      "styleRecalcs": 252,
      "styleRecalcDurationMs": 58.69500000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 4023.695,
      "heapDeltaBytes": -746212,
      "heapUsedBytes": 69235916,
      "domNodes": 22,
      "jsHeapTotalBytes": 19193856,
      "scriptDurationMs": 1373.1660000000002,
      "eventListeners": 20,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8148.278000000005,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 58.364999999999995,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3885.592,
      "heapDeltaBytes": -3647048,
      "heapUsedBytes": 68184244,
      "domNodes": 18,
      "jsHeapTotalBytes": 16048128,
      "scriptDurationMs": 1282.307,
      "eventListeners": 20,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 11180.116999999995,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 11165.722,
      "heapDeltaBytes": -35749172,
      "heapUsedBytes": 169673324,
      "domNodes": -3306,
      "jsHeapTotalBytes": 21467136,
      "scriptDurationMs": 639.0039999999999,
      "eventListeners": -16471,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.220000000000073,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 11858.541999999943,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 11841.465,
      "heapDeltaBytes": -37525296,
      "heapUsedBytes": 170944188,
      "domNodes": -3308,
      "jsHeapTotalBytes": 23302144,
      "scriptDurationMs": 593.4229999999999,
      "eventListeners": -16472,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333237,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 13922.890999999992,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 20.598000000000006,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 13877.077,
      "heapDeltaBytes": -21650360,
      "heapUsedBytes": 168972676,
      "domNodes": -3308,
      "jsHeapTotalBytes": 17010688,
      "scriptDurationMs": 911.248,
      "eventListeners": -16472,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.219999999999953,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 14336.181000000011,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 20.51900000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14313.839,
      "heapDeltaBytes": -26112468,
      "heapUsedBytes": 187005148,
      "domNodes": -3308,
      "jsHeapTotalBytes": 19808256,
      "scriptDurationMs": 860.81,
      "eventListeners": -16468,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "workflow-execution",
      "durationMs": 477.8140000000235,
      "styleRecalcs": 19,
      "styleRecalcDurationMs": 29.515000000000004,
      "layouts": 6,
      "layoutDurationMs": 2.18,
      "taskDurationMs": 149.605,
      "heapDeltaBytes": 5433636,
      "heapUsedBytes": 65134736,
      "domNodes": 170,
      "jsHeapTotalBytes": 3145728,
      "scriptDurationMs": 21.215,
      "eventListeners": 69,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "workflow-execution",
      "durationMs": 510.38600000003953,
      "styleRecalcs": 15,
      "styleRecalcDurationMs": 36.413000000000004,
      "layouts": 5,
      "layoutDurationMs": 1.8219999999999998,
      "taskDurationMs": 176.01600000000002,
      "heapDeltaBytes": 5227080,
      "heapUsedBytes": 64955500,
      "domNodes": 153,
      "jsHeapTotalBytes": 2883584,
      "scriptDurationMs": 35.205,
      "eventListeners": 69,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66666666666665,
      "p95FrameDurationMs": 16.700000000000273
    }
  ]
}

@github-actions

Copy link
Copy Markdown

🎭 Playwright: ✅ 1671 passed, 0 failed · 1 flaky

📊 Browser Reports
  • chromium: View Report (✅ 1652 / ❌ 0 / ⚠️ 0 / ⏭️ 5)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 16 / ❌ 0 / ⚠️ 1 / ⏭️ 0)

@christian-byrne christian-byrne merged commit 93e0821 into cloud/1.46 Jun 19, 2026
63 checks passed
@christian-byrne christian-byrne deleted the backport-12788-to-cloud-1.46 branch June 19, 2026 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport Backporting a PR onto a release candidate size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants