feat(web): auto-poll request progress when ingests are in flight (#369)

Half of #369 — the auto-poll piece. Inbox deferred (separate task).

Both /requests (user) and /admin/requests (admin, 'approved' tab only)
now refetch every 12s while at least one row has status='approved'.
Stops automatically when all rows settle to pending/completed/rejected.
TanStack Query's default refetchIntervalInBackground=false handles
the visibility behavior — polling pauses when the tab is hidden and
resumes on focus.

Predicate hasInFlightRequest() is exported + tested so the polling
logic is auditable independent of TanStack Query's internals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-10 17:59:38 -04:00
co-authored by Claude Opus 4.7
parent 7bc254e17e
commit 861dd8ef17
3 changed files with 63 additions and 3 deletions
+13 -1
View File
@@ -116,10 +116,22 @@ export function createRootFoldersQuery(enabled: boolean = true) {
export function createAdminRequestsQuery(status?: LidarrRequestStatus) {
return createQuery({
queryKey: qk.adminRequests(status),
queryFn: () => listAdminRequests(status)
queryFn: () => listAdminRequests(status),
// Only the 'approved' tab needs polling — that's where in-flight
// ingests live. Other tabs (pending/rejected/completed) are static
// until the operator acts on them.
refetchInterval: (query) => {
if (status !== 'approved') return false;
const rows = query.state.data as LidarrRequest[] | undefined;
return hasInFlightRequest(rows) ? 12_000 : false;
}
});
}
function hasInFlightRequest(rows: readonly LidarrRequest[] | undefined): boolean {
return rows?.some((r) => r.status === 'approved') ?? false;
}
// Admin quarantine --------------------------------------------------------
export async function listAdminQuarantine(): Promise<AdminQuarantineRow[]> {