mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-07-14 18:15:56 -04:00
fix: misc bug fixes and reliability improvements
- Fix `refreshCreditsJob` to treat `null` `lastFetchedAt` as needing refresh (not just missing cast entry) - Fix `buildBackupCron` 6h expression to correctly fire every 6 hours using explicit hour list instead of `*/6` - Fix `vacuumDatabase` to pass the path directly as a bound parameter (the manual escape was redundant and incorrect) - Clean up orphaned `.tmp` files when image cache writes fail in both `downloadAndCacheImage` and `fetchAndMaybeCache` - Surface import job payload parse/validation errors as job-level `error` status instead of throwing unhandled exceptions; check for cancellation before the processing loop starts - Replace bare `Error` throws in `readImportJob` with `ORPCError` (`NOT_FOUND` / `FORBIDDEN`) so oRPC maps them to correct HTTP status codes - Auto-promote title status to `in_progress` when `logEpisodeWatchBatch` is called for titles that have no status or are only on the watchlist - Refresh seasons from TMDB when a webhook references a season not yet in the DB (handles newly-released seasons) - Upgrade fire-and-forget enrichment failures and webhook processing errors from `log.debug` → `log.warn` so they surface in production logs
This commit is contained in:
@@ -218,7 +218,7 @@ async function refreshCreditsJob() {
|
||||
for (const titleId of libraryIds) {
|
||||
const castEntry = getCastEntryForTitle(titleId);
|
||||
|
||||
const needsRefresh = !castEntry || (castEntry.lastFetchedAt && castEntry.lastFetchedAt < stale);
|
||||
const needsRefresh = !castEntry || !castEntry.lastFetchedAt || castEntry.lastFetchedAt < stale;
|
||||
|
||||
if (needsRefresh) {
|
||||
await refreshCredits(titleId);
|
||||
@@ -254,7 +254,7 @@ export function buildBackupCron(
|
||||
|
||||
switch (frequency) {
|
||||
case "6h":
|
||||
return `${m} */6 * * *`;
|
||||
return `${m} ${h},${(h + 6) % 24},${(h + 12) % 24},${(h + 18) % 24} * * *`;
|
||||
case "12h":
|
||||
return `${m} ${h},${(h + 12) % 24} * * *`;
|
||||
case "7d":
|
||||
|
||||
@@ -171,7 +171,7 @@ export const createJob = os.imports.createJob.use(authed).handler(async ({ input
|
||||
log.error(`Import job ${job.id} failed:`, err);
|
||||
});
|
||||
|
||||
return readImportJob(job.id);
|
||||
return readImportJob(job.id, context.user.id);
|
||||
});
|
||||
|
||||
export const getJob = os.imports.getJob.use(authed).handler(({ input, context }) => {
|
||||
@@ -187,7 +187,7 @@ export const cancelJob = os.imports.cancelJob.use(authed).handler(({ input, cont
|
||||
});
|
||||
}
|
||||
updateImportJobProgress(input.id, { status: "cancelled" });
|
||||
return readImportJob(input.id);
|
||||
return readImportJob(input.id, context.user.id);
|
||||
});
|
||||
|
||||
export const jobEvents = os.imports.jobEvents.use(authed).handler(async function* ({
|
||||
|
||||
@@ -13,10 +13,13 @@ import {
|
||||
removeTitleStatus,
|
||||
setTitleStatus,
|
||||
} from "@sofa/core/tracking";
|
||||
import { createLogger } from "@sofa/logger";
|
||||
|
||||
import { os } from "../context";
|
||||
import { authed } from "../middleware";
|
||||
|
||||
const log = createLogger("titles");
|
||||
|
||||
export const detail = os.titles.detail.use(authed).handler(async ({ input }) => {
|
||||
const result = await getOrFetchTitle(input.id);
|
||||
if (!result)
|
||||
@@ -77,7 +80,9 @@ export const quickAdd = os.titles.quickAdd.use(authed).handler(async ({ input, c
|
||||
}
|
||||
|
||||
// Trigger full TMDB import if still a shell (fire-and-forget)
|
||||
getOrFetchTitleByTmdbId(result.tmdbId, result.type as "movie" | "tv").catch(() => {});
|
||||
getOrFetchTitleByTmdbId(result.tmdbId, result.type as "movie" | "tv").catch((err) => {
|
||||
log.warn(`Failed to import ${result.type} TMDB ${result.tmdbId}:`, err);
|
||||
});
|
||||
|
||||
return { id: result.id, alreadyAdded: result.alreadyAdded };
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ app.post("/:token", async (c) => {
|
||||
await processWebhook(connection.id, connection.userId, provider, event);
|
||||
} catch (err) {
|
||||
// Swallow errors — never return non-200 to media servers
|
||||
log.debug("Webhook processing failed:", err);
|
||||
log.warn("Webhook processing failed:", err);
|
||||
}
|
||||
|
||||
return c.json({ ok: true });
|
||||
|
||||
Reference in New Issue
Block a user