perf(dashboard): replace pause/jobs/pool polling with push events#231
Merged
Conversation
Three dashboard endpoints were polled per-client on 500 ms / 1 s / 5 s
intervals (running-job-details, processor/paused, metrics/nntp-pool).
The polling generated ~3 req/s per idle client and crashed JSON.parse
in the dev proxy whenever the Go backend was unreachable.
Reuse the existing WebSocket hub instead of polling:
- App.emit() unifies Wails-runtime and WebSocket dispatch so the
broadcaster is mode-agnostic.
- eventBroadcaster runs one shared ticker per metric (1 s running-jobs
with JSON dedupe; 5 s pool metrics; piggybacks auto-pause state-change
detection on the running-jobs tick).
- PauseProcessing/ResumeProcessing now ship a full {paused, autoPaused,
reason} snapshot so the UI renders without follow-up RPCs.
- Frontend components drop their setInterval loops, fetch once on mount,
then subscribe via apiClient.on(). N clients are now driven by 1
server-side ticker instead of N pollers.
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.
Summary
Three dashboard endpoints were polled by every client on tight intervals:
/api/processor/paused(+ auto-paused, reason)DashboardHeader.svelte/api/running-job-detailsProgressSection.svelte/api/metrics/nntp-poolProviderStatus.svelte,routes/metrics/+page.svelteThat's ~3 req/s per idle client. It also caused the "HTML instead of JSON" symptom in dev: when the Go backend on
:8080was unreachable, the Vite proxy returned the SPAindex.html, which crashedJSON.parseinweb-client.ts.This PR replaces the polling with push events over the existing WebSocket hub. No new transport — SSE was considered and rejected in favor of reusing the WS infrastructure already used for upload/config events.
What changed
Backend (
internal/backend/)app.go— added aProcessingPauseStatepayload andpauseState()helper; addedApp.emit(event, payload)that routes to Wails runtime (desktop) orwebEventEmitter(web).PauseProcessing/ResumeProcessingnow broadcast the full pause snapshot so the UI doesn't need follow-up RPCs.broadcaster.go(new) — one shared ticker per metric:running-jobs-updated(JSON dedupe; idle state goes silent)processing:auto-paused(state-change detection only)nntp-pool-metrics-updatedStartup/Shutdown.Frontend
lib/api/events.ts(new) — typed event payloads + event-name constants.DashboardHeader.svelte,ProgressSection.svelte,ProviderStatus.svelte,routes/metrics/+page.svelte— dropsetIntervalloops and visibility-change handlers, fetch once on mount, then subscribe viaapiClient.on().Net effect
Replaces N pollers × per-client with 1 ticker × server-side. A typical idle dashboard goes from ~3 req/s to zero recurring HTTP traffic; updates arrive as WS frames.
Reviewer notes
nntp-pool-metrics-updatedis not deduped becauseTimestamp/Elapsed/AvgSpeeddrift every tick; the cost of an unconditional 5 s emit is negligible.running-jobs-updateddedupe is most effective when idle (no jobs → identical empty payload → no emit).internal/processor/to avoid an import cycle intointernal/backend/.Test plan
go build ./internal/... ./cmd/web/...go vet ./internal/... ./cmd/web/...go test -race ./internal/processor/... ./internal/queue/...bun run check— 0 errors, 0 warningsgo run ./cmd/web+bun run dev, confirm DevTools shows each of the three endpoints called once on mount and never again; WS frames carry the new event types.wails dev).