Fix updateTag errors when called from cron jobs and detached promises

updateTag (Next.js cache revalidation) only works inside Route Handlers
and Server Actions. It was being called from cron jobs and fire-and-forget
promises, causing intermittent errors attributed to whichever route was
rendering concurrently (e.g. /explore).

- Pass `{ revalidate: false }` from cron and fire-and-forget contexts
- Add try-catch around updateTag calls as a safety net

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 19:29:18 -04:00
co-authored by Claude Opus 4.6
parent aba84c6979
commit dfda2da827
3 changed files with 17 additions and 7 deletions
+1 -1
View File
@@ -301,7 +301,7 @@ async function refreshCreditsJob() {
(castEntry.lastFetchedAt && castEntry.lastFetchedAt < stale); (castEntry.lastFetchedAt && castEntry.lastFetchedAt < stale);
if (needsRefresh) { if (needsRefresh) {
await refreshCredits(titleId); await refreshCredits(titleId, { revalidate: false });
await Bun.sleep(RATE_LIMIT_MS); await Bun.sleep(RATE_LIMIT_MS);
} }
} }
+6 -1
View File
@@ -280,7 +280,12 @@ export async function refreshCredits(
if (revalidate) { if (revalidate) {
for (const personId of personIds.values()) { for (const personId of personIds.values()) {
updateTag(`person-${personId}`); try {
updateTag(`person-${personId}`);
} catch {
// updateTag only works inside Route Handlers / Server Actions;
// swallow the error when called from cron jobs or detached promises.
}
} }
} }
+10 -5
View File
@@ -173,7 +173,7 @@ async function _getOrFetchTitleByTmdbId(tmdbId: number, type: "movie" | "tv") {
extractAndStoreColors(existing.id, show.poster_path ?? null).catch( extractAndStoreColors(existing.id, show.poster_path ?? null).catch(
(err) => log.debug("Color extraction failed:", err), (err) => log.debug("Color extraction failed:", err),
); );
refreshCredits(existing.id).catch((err) => refreshCredits(existing.id, { revalidate: false }).catch((err) =>
log.debug("Credits enrichment failed:", err), log.debug("Credits enrichment failed:", err),
); );
refreshTrailer(existing.id).catch((err) => refreshTrailer(existing.id).catch((err) =>
@@ -227,7 +227,7 @@ async function _getOrFetchTitleByTmdbId(tmdbId: number, type: "movie" | "tv") {
extractAndStoreColors(row.id, movie.poster_path ?? null).catch((err) => extractAndStoreColors(row.id, movie.poster_path ?? null).catch((err) =>
log.debug("Color extraction failed:", err), log.debug("Color extraction failed:", err),
); );
refreshCredits(row.id).catch((err) => refreshCredits(row.id, { revalidate: false }).catch((err) =>
log.debug("Credits enrichment failed:", err), log.debug("Credits enrichment failed:", err),
); );
refreshTrailer(row.id).catch((err) => refreshTrailer(row.id).catch((err) =>
@@ -276,7 +276,7 @@ async function _getOrFetchTitleByTmdbId(tmdbId: number, type: "movie" | "tv") {
extractAndStoreColors(row.id, show.poster_path ?? null).catch((err) => extractAndStoreColors(row.id, show.poster_path ?? null).catch((err) =>
log.debug("Color extraction failed:", err), log.debug("Color extraction failed:", err),
); );
refreshCredits(row.id).catch((err) => refreshCredits(row.id, { revalidate: false }).catch((err) =>
log.debug("Credits enrichment failed:", err), log.debug("Credits enrichment failed:", err),
); );
refreshTrailer(row.id).catch((err) => refreshTrailer(row.id).catch((err) =>
@@ -352,7 +352,7 @@ export async function refreshTitle(titleId: string) {
refreshTrailer(updated.id).catch((err) => refreshTrailer(updated.id).catch((err) =>
log.debug("Trailer enrichment failed:", err), log.debug("Trailer enrichment failed:", err),
); );
refreshCredits(updated.id).catch((err) => refreshCredits(updated.id, { revalidate: false }).catch((err) =>
log.debug("Credits enrichment failed:", err), log.debug("Credits enrichment failed:", err),
); );
if (imageCacheEnabled()) { if (imageCacheEnabled()) {
@@ -586,7 +586,12 @@ export async function refreshRecommendations(
}); });
if (revalidate) { if (revalidate) {
updateTag(`recs-${titleId}`); try {
updateTag(`recs-${titleId}`);
} catch {
// updateTag only works inside Route Handlers / Server Actions;
// swallow when called from cron jobs or detached promises.
}
} }
} }