Files
HealthLog/src/lib/retry-import.ts
T
Marc-André Bombeck b5e799c2d6 fix(charts): degrade chart failures to one card and heal stale shells per version
The update poller and the chunk-error reload guard key on the target
version instead of disarming for the whole session, so a second deploy
re-arms the self-heal and a stale shell can no longer strand with
404ing chunks. Lazy chart imports retry once and mount inside a
per-card error boundary with a reload affordance — a failed chunk
degrades to one card instead of replacing the page. The JSON API
client attaches a fifteen-second timeout unless the caller brings its
own signal (the raw streaming path is exempt), chart queries surface
errors with a retry instead of rendering as an empty period, per-type
fetch failures reject instead of caching an empty series as fresh, and
the session and snapshot queries retry once on transient network or
server errors.
2026-06-11 21:17:27 +02:00

33 lines
1.1 KiB
TypeScript

/**
* Retrying wrapper for lazy chunk imports.
*
* A rejected `import()` inside `React.lazy` / `next/dynamic` caches its
* rejection on the component instance, so one transient chunk 404 (a
* stale shell right after a deploy, a flaky connection) bricks the lazy
* boundary for the rest of the session — remounting never re-attempts
* the import. Wrapping the importer here absorbs the transient class:
* the import retries once after a short delay before the rejection is
* allowed to surface to the boundary's error handling.
*/
export const IMPORT_RETRY_DELAY_MS = 1_000;
/**
* Run `importer`, retrying `retries` more times (default once) after
* `delayMs` when it rejects. The final rejection propagates unchanged
* so the caller's error boundary sees the original chunk error.
*/
export async function importWithRetry<T>(
importer: () => Promise<T>,
retries = 1,
delayMs = IMPORT_RETRY_DELAY_MS,
): Promise<T> {
try {
return await importer();
} catch (err) {
if (retries <= 0) throw err;
await new Promise((resolve) => setTimeout(resolve, delayMs));
return importWithRetry(importer, retries - 1, delayMs);
}
}