[web-console] Keep showing the pipeline metrics while the pipeline is stopping#6687
[web-console] Keep showing the pipeline metrics while the pipeline is stopping#6687Karakatiza666 wants to merge 1 commit into
Conversation
mythical-fred
left a comment
There was a problem hiding this comment.
Nice refactor and the UX intent is right — keeping the last-known chart on screen while a pipeline is stopping is a real improvement over the current cliff. A few things before this lands:
Blocker: no Vitest coverage. Per Gerd's hard rule on web-console changes, this needs tests. The specific pieces I would want covered:
usePipelineManager.silence(predicate)— verify that (a) errors matching the predicate do not firetoastErrorbut still reject the returned promise, (b) errors not matching still surface a toast, (c)doNotReportIfCancelledstill suppressescause === 'cancelled'/AbortErrorregardless ofpredicate. This is the only behaviorally new surface inusePipelineManager.svelte.ts; the rest of+177/-152is a mechanical wrap intobuild(), so ifsilence()is regression-tested the whole refactor is protected.TabPerformance— component spec (analogous to what you wrote for #6684) asserting the two banner states:metricsAvailable && !activeMetricsStreamrenders the new "Not receiving live metrics" banner; the existing!isNetworkHealthybanner still wins when the pipeline is unavailable.status.ts— theStopping → 'yes'flip is a one-line change but it inverts an existing contract; add/update theisMetricsAvailableunit test so the intent is nailed down and future refactors don't quietly revert it.
Race on mount: activeMetricsStream = $state<ReadableStream | null>(null) starts as null and metricsAvailable is derived from pipeline.current.deploymentStatus which is truthy immediately. So on first mount, before the first await pollingApi.pipelineTimeSeriesStream(...) resolves, metricsStreamInterrupted is true for one frame and the new "reconnecting" banner briefly appears even though nothing is wrong. Two options: (a) initialize with a hasEverConnected gate — banner only shows once we've had at least one successful stream; (b) treat the initial connect as its own state ('connecting' vs 'reconnecting') and only show the banner on 'reconnecting'. Slide transition makes this more visible, not less.
silence() cause-unwrapping: (error as any)?.cause ?? error is the right idea, but note that doNotReportIfCancelled reads error?.cause === 'cancelled' — a string sentinel — while your example expects cause to be an object with error_code. Worth a one-line comment in silence()'s JSDoc noting that cause can be either a string sentinel or an ErrorResponse-shaped object, so predicates should be defensive (which yours is via optional chaining).
Nit: pollingApi is only used for three call sites in TabPerformance.svelte. Naming it noisySilencedApi or bgApi would read better than pollingApi (the metrics stream isn't polling). Ignore if you disagree.
Nit: the slide transition on WarningBanner is a global change — it now animates every banner site, not just this one. Worth a quick pass to confirm the deployment-error banner and the auth banner don't now feel laggy on toggle.
The core design is right and the refactor is clean. Tests + the initial-mount gate would let this go straight in.
| const result = _getPipelineSupportBundle(pipelineName, options, onProgress) | ||
| return { | ||
| cancel: result.cancel, | ||
| // Build the API surface against a given error reporter. `.silence()` reuses this to produce a |
There was a problem hiding this comment.
this stuff seems to have been shuffled around, but it's not easy to tell what changed
… stopping Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
mythical-fred
left a comment
There was a problem hiding this comment.
Re-review at 6da9942 — one new commit that replaces the boolean activeMetricsStream with a three-state metricsStreamState: 'connecting' | 'live' | 'interrupted'.
The race blocker is fixed. metricsStreamInterrupted is now metricsAvailable && metricsStreamState === 'interrupted', so the reconnect banner can no longer flash on first mount before the initial stream connects — exactly the semantics I asked for. The state machine is also easier to reason about than the previous nullable-stream sentinel.
Still open from the previous review:
- No Vitest coverage. Nothing changed since the last round: no
TabPerformance.spec.ts, no test forusePipelineManager's newsilence()variant, no test for theStopping → 'yes'flip instatus.ts. Web-console tests are a hard rule for this repo — every non-trivial change tojs-packages/web-consoleneeds Vitest coverage before merge. The three-state transition (connecting → live → interrupted → live) is precisely the kind of thing that benefits from a small test: it's the whole point of the fix and it's easy to regress. silence()JSDoc. Still doesn't document thatcausecan be either the string'cancelled'or anErrorResponse-shaped object, and callers already have predicates that assume both. A one-sentence note prevents the next contributor from writing an unsafe predicate.pollingApinaming and globalslidetransition onWarningBanner— non-blocking nits from the last round, still worth doing while the diff is open.
The design is now right; blocker downgraded to just the missing tests. Once a Vitest file covers the connecting/live/interrupted transitions and the status.ts flip, this is an approve.
REQUEST_CHANGES pending tests.
Now when the pipeline is stopped the UI continues to display the live metrics up until the connection is broken.
Now when the metrics stream is interrupted the UI shows the banner that warns that connection to metrics was lost. This is different from the existing banner that warned that the pipeline is unavailable.
Testing: manual
Fix #6677
Screencast.From.2026-07-21.18-30-06.webm