Complete SSE refactor: migrate consumers, extract invalidators, drop singleton#9261
Open
ericpgreen2 wants to merge 14 commits intoericgreen/sse-client-cleanupfrom
Open
Complete SSE refactor: migrate consumers, extract invalidators, drop singleton#9261ericpgreen2 wants to merge 14 commits intoericgreen/sse-client-cleanupfrom
ericpgreen2 wants to merge 14 commits intoericgreen/sse-client-cleanupfrom
Conversation
Completes the SSE refactor by moving the three consumers onto the new
layered API, extracting pure invalidator modules, wiring the cloud
editor's JWT refresh, and dropping the singleton/compat shims from PR 1.
Pure extractions (testable, injectable deps):
- `runtime-client/invalidation/file-invalidators.ts` — file WRITE/DELETE
handling, rill.yaml side effects, throttled `ListFiles` refetch.
- `runtime-client/invalidation/resource-invalidators.ts` — per-kind
dispatch for Connector, Source/Model, MetricsView, Explore, Canvas,
and Component resources plus delete variants.
- `web-admin/.../status/logs/log-store.ts` — ProjectLogsPage state
machine (monotonic ids, ring buffer, filter-by-level + search).
Consumer migrations:
- `FileAndResourceWatcher` is a thin per-mount class over
`SSEConnection` + `SSESubscriber` + optional `SSELifecycle`. The
singleton export is gone; the Svelte component constructs the watcher
synchronously so `setContext` runs before descendants read it.
- `RuntimeTrafficLights` reads watcher state via the new
`watcher-context.ts` key, with a safe fallback so it still renders
outside a watcher provider.
- `Conversation` uses `SSESubscriber` for typed message/error routing;
untagged frames normalize to the "message" decoder per the SSE spec.
Transport vs. server errors stay on separate channels.
- `ProjectLogsPage` uses `SSEConnection` + typed `SSESubscriber<{ log,
error }>` and delegates state to `LogStore`.
Call-site updates:
- `web-local/src/routes/+layout.svelte` → `lifecycle="aggressive"`.
- `web-admin/.../edit/+layout.svelte` → `lifecycle="none"` plus an
`onBeforeReconnect` hook that invalidates the branch-scoped
`GetProject` query key so the next `runtimeClient.getJwt()` returns a
fresh token.
Also:
- `SSEConnection.handleError` now fires `close` when `retryOnError` is
false so one-shot consumers (chat) can settle cleanly on failure.
- Deprecation shims removed: `sse-fetch-client.ts` and
`sse-connection-manager.ts` at the old paths; auto-close methods and
the `autoCloseTimeouts` param stripped from `SSEConnection`.
- New specs: `file-invalidators.spec.ts`,
`resource-invalidators.spec.ts`, `file-and-resource-watcher.spec.ts`,
`RuntimeTrafficLights.spec.ts`, `conversation-streaming.spec.ts`,
`log-store.spec.ts`. `web-admin/package.json` gains a `test:unit`
script for the latter.
…to ericgreen/sse-consumer-migrations # Conflicts: # web-common/src/runtime-client/sse/sse-connection.ts
…er-migrations # Conflicts: # web-common/src/runtime-client/sse/sse-connection.ts
With all consumers migrated off the deprecated auto-close API in the previous commit, the last PR 1 shims can go: - heartbeat() alias on SSEConnection (use resumeIfPaused() directly) - SSEConnectionLifecycle's schedulePause / cancelScheduledPause are now private; no external caller drives them
This was referenced Apr 21, 2026
This keeps connection/subscriber concerns separated while reducing boilerplate in watcher, chat, and logs consumers. Made-with: Cursor
Reintroduce Playwright reconciliation logging in the resource watcher and surface subscriber JSON parse failures as chat stream errors to avoid silent drops. Made-with: Cursor
Make cloud edit-session reconnect invalidation track latest reactive route values, ensure FileAndResourceWatcher always delegates to the latest callback prop, add an instanceId/runtimeClient consistency guard, and clarify legacy resource invalidation gate naming and test wording. Made-with: Cursor
Inline the trivial per-kind write/delete helpers into `dispatchWrite` and `dispatchDelete`, and inline `handleFileWrite`/`handleFileDelete` into `handleFileEvent`. Drop `isLeafResource` as an injected dep and call it directly from `invalidateForSourceOrModelWrite`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #9260 (merge that first). Migrates the three SSE consumers —
FileAndResourceWatcher,Conversation, andProjectLogsPage— onto the refactored client.Notable
heartbeat()alias).fileAndResourceWatcheris now scoped per runtime (project × branch) instead of a process-wide singleton, so cloud sessions that switch between deployments get their own watcher.Checklist:
Developed in collaboration with Claude Code