fix(frontend-admin): SSE/AbortController hygiene + signal-chain through proxy (0.87.9)

Three frontend findings (medium):

1. **`hooks.server.ts` didn't chain client-disconnect into the upstream
   fetch.** Closing an admin tab left the backend's `broadcast::Receiver`
   + spawned tokio task running until next backend restart. Listen for
   `event.request.signal.abort` and forward to the timeout controller.

2. **`admin/analysis/+page.svelte` missing visibility/pagehide/pageshow
   handlers.** Mobile Safari throttles SSE in background tabs; bfcache
   leaves a dead connection on back-nav. Apply the close/open-stream
   pattern from `admin/crawler/+page.svelte`.

3. **`loadCoverage` had no AbortController.** Debounced search
   keystrokes raced. Per-loader controller plumbed through
   `getAnalysisMangaCoverage`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-22 21:52:33 +02:00
parent c0281f7e9b
commit 747bdeda46
6 changed files with 92 additions and 14 deletions

View File

@@ -743,7 +743,8 @@ export type PageAnalysisDetail = {
/** Paginated per-manga analysis coverage (admin overview). */
export async function getAnalysisMangaCoverage(
opts: { search?: string; limit?: number; offset?: number } = {}
opts: { search?: string; limit?: number; offset?: number } = {},
init?: { signal?: AbortSignal }
): Promise<MangaCoveragePage> {
const params = new URLSearchParams();
if (opts.search) params.set('search', opts.search);
@@ -751,7 +752,8 @@ export async function getAnalysisMangaCoverage(
if (opts.offset != null) params.set('offset', String(opts.offset));
const qs = params.toString();
return request<MangaCoveragePage>(
`/v1/admin/analysis/mangas${qs ? `?${qs}` : ''}`
`/v1/admin/analysis/mangas${qs ? `?${qs}` : ''}`,
init?.signal ? { signal: init.signal } : undefined
);
}