refactor: optimize cron scheduling, DB maintenance, and TMDB reliability

- Skip recommendations refresh for titles fetched within the last 7 days via `getTitlesWithFreshRecommendations`; only stale titles are re-fetched
- Replace `Promise.allSettled` in `refreshTvChildren` with a `mapWithConcurrency` helper (concurrency = 5) to stay within TMDB's rate limit
- Add 30s request timeout middleware to TMDB client to prevent indefinitely hung fetches
- Expand `optimizeDb` weekly job to prune 30-day-old cron runs, integration events, expired sessions, and expired verifications
- Add `wal_checkpoint(TRUNCATE)` to `optimizeDatabase` so the WAL is flushed before `PRAGMA optimize`
- Add `recoverStaleImportJobs` called on server startup to mark any `pending`/`running` import jobs as errored after a crash/restart
- Return `false` from `triggerJob` immediately if the job is already running
This commit is contained in:
2026-03-23 13:59:31 -04:00
parent d9be566863
commit b289b7abed
17 changed files with 235 additions and 36 deletions
+20 -1
View File
@@ -126,6 +126,25 @@ const baseUrlRewriteMiddleware: Middleware | null = isCustomBase
}
: null;
const TMDB_REQUEST_TIMEOUT_MS = 30_000;
const requestTimeouts = new WeakMap<Request, Timer>();
const timeoutMiddleware: Middleware = {
async onRequest({ request }) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), TMDB_REQUEST_TIMEOUT_MS);
const newRequest = new Request(request, { signal: controller.signal });
requestTimeouts.set(newRequest, timeout);
return newRequest;
},
async onResponse({ request }) {
const timeout = requestTimeouts.get(request);
if (timeout) clearTimeout(timeout);
return undefined;
},
};
const authMiddleware: Middleware = {
async onRequest({ request }) {
request.headers.set("Authorization", `Bearer ${getApiKey()}`);
@@ -155,7 +174,7 @@ const loggingMiddleware: Middleware = {
const client = createClient<paths>({ baseUrl });
if (baseUrlRewriteMiddleware) client.use(baseUrlRewriteMiddleware);
client.use(authMiddleware, loggingMiddleware);
client.use(timeoutMiddleware, authMiddleware, loggingMiddleware);
// ─── Search ─────────────────────────────────────────────────────────