From 4fb7c948ad608253f0f78706d37398d6b948e6ec Mon Sep 17 00:00:00 2001 From: Claude Integration Date: Tue, 2 Jun 2026 01:27:20 +0000 Subject: [PATCH] feat(cron): regenerate-variants task pour batch tous les Media existants --- src/lib/scheduled.ts | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/lib/scheduled.ts b/src/lib/scheduled.ts index f9faee8..d3272f8 100644 --- a/src/lib/scheduled.ts +++ b/src/lib/scheduled.ts @@ -5,10 +5,11 @@ import "server-only"; -import { BookingStatus } from "@/generated/prisma/enums"; +import { BookingStatus, MediaType } from "@/generated/prisma/enums"; import { prisma } from "@/lib/prisma"; import { recordAudit } from "@/lib/admin/audit"; import { purgeExpiredResetTokens } from "@/lib/password-reset"; +import { generateImageVariants } from "@/lib/variants-server"; const PENDING_TTL_DAYS = 7; @@ -67,9 +68,44 @@ export async function listUpcomingArrivalsInThreeDays() { }); } +/** Régénère les variantes responsives pour tous les Media PHOTO en base. */ +export async function regenerateAllVariants(): Promise<{ scanned: number; ok: number; skipped: number; failed: number }> { + const medias = await prisma.media.findMany({ + where: { type: MediaType.PHOTO }, + select: { id: true, s3Key: true }, + }); + let ok = 0; + let skipped = 0; + let failed = 0; + for (const m of medias) { + const ext = m.s3Key.split(".").pop()?.toLowerCase(); + if (!ext || !["jpg", "jpeg", "png", "webp", "avif"].includes(ext)) { + skipped++; + continue; + } + const mime = + ext === "png" ? "image/png" : + ext === "webp" ? "image/webp" : + ext === "avif" ? "image/avif" : + "image/jpeg"; + const result = await generateImageVariants({ originalS3Key: m.s3Key, mime }); + if (result.skipped) skipped++; + else if (result.results.every((r) => r.ok)) ok++; + else failed++; + } + await recordAudit({ + scope: "cron", + event: "variants.regenerate-all", + actorEmail: null, + details: { scanned: medias.length, ok, skipped, failed }, + }); + return { scanned: medias.length, ok, skipped, failed }; +} + export const SCHEDULED_TASKS = { "auto-cancel-stale-pending": autoCancelStalePending, "purge-reset-tokens": purgeResetTokens, + "regenerate-variants": regenerateAllVariants, } as const; export type ScheduledTaskName = keyof typeof SCHEDULED_TASKS;