Skip to content

feat(search): live automatic-search activity indicator (sidebar)#723

Draft
kevinheneveld wants to merge 1 commit into
Listenarrs:canaryfrom
kevinheneveld:feat/search-activity-indicator
Draft

feat(search): live automatic-search activity indicator (sidebar)#723
kevinheneveld wants to merge 1 commit into
Listenarrs:canaryfrom
kevinheneveld:feat/search-activity-indicator

Conversation

@kevinheneveld

Copy link
Copy Markdown
Contributor

What

A live activity indicator for the automatic-search sweep: a sidebar pill that shows what the background search is doing right now ("Searching 4 indexers for …", "Grabbed 2 release(s) for …", "Search idle — last sweep processed 31 book(s)"), driven over the existing search-progress SignalR channel.

  • SearchActivityTracker (singleton): holds the current stage + a rolling 30-entry feed of recent per-book outcomes; hydrated on page load via a new GET /search/activity endpoint (in a SearchController.Activity.cs partial, keeping the main controller under the 500-line architecture cap).
  • SearchProgressReporter.BroadcastAutomaticAsync: broadcasts type: "automatic" progress events through the existing IHubBroadcaster plumbing and records them in the tracker.
  • Hooks (all optional + best-effort — a notification hiccup can never affect a search): per-book "searching" in IndexerSearchWorkflow (gated on isAutomaticSearch), per-book outcome + idle transitions in the automatic-search sweep.
  • Frontend: a searchActivity Pinia store (SignalR + hydration) and a SidebarSearchActivity pill.

Note: the kevin/live original also had a dashboard "recent outcomes" panel; canary has no dashboard view, so this PR ships the sidebar half. The endpoint and store already carry the 30-outcome feed, so a future panel (e.g. on the Activity view) can consume it with zero backend changes.

Why

The automatic-search sweep is invisible today — you can't tell whether it's running, stuck, or idle without reading logs. This surfaces it where you already are.

Tests

7 new backend tests (tracker state/feed + reporter automatic-broadcast) and a 3-case vitest spec for the store. Full suite passing; vue-tsc + eslint + prettier clean.

🤖 Generated with Claude Code

The background sweep now reports per-book activity to the UI so you can
see what it's doing without tailing logs. A compact pill above the
sidebar version footer shows the current line ("Searching N indexers
for X", pulsing while active; "Search idle" otherwise).

Built on the existing SearchProgress realtime channel (includeAutomatic
opt-in already present): the automatic-search sweep and the indexer
search workflow emit searching/grabbed/no_results/idle via a new
SearchProgressReporter.BroadcastAutomaticAsync; a process-local
SearchActivityTracker keeps the current event plus the last 30 outcomes
so a fresh page hydrates from GET /search/activity immediately instead
of waiting for the next SignalR event — which during an idle window
could be hours away. Interactive Add-New search is unaffected.

The tracker's rolling outcome feed is exposed by the endpoint and kept
in the frontend store for a future activity panel; the sidebar pill
renders the current line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant