fix upload image trip

This commit is contained in:
2026-05-22 14:52:22 +07:00
parent 9022f983a2
commit 4c449a572a
18 changed files with 721 additions and 118 deletions
+74
View File
@@ -0,0 +1,74 @@
import { NextRequest, NextResponse } from "next/server";
import { runCron } from "@/lib/cron-runner";
import { prisma } from "@/lib/prisma";
import {
deleteTripImage,
listTripImageNames,
tripImageMtime,
TRIP_IMAGE_URL_PREFIX,
} from "@/lib/trip-image-storage";
export const runtime = "nodejs";
export const dynamic = "force-dynamic";
/** File yang lebih tua dari ini & tak direferensikan DB dianggap yatim. */
const ORPHAN_AGE_MS = 24 * 60 * 60 * 1000;
/**
* Cron — hapus file gambar trip yatim.
*
* Form create-trip multi-step mengunggah foto SEBELUM trip tersimpan; kalau
* user menutup form di tengah jalan, file menggantung di disk tanpa pernah
* jadi `TripImage`. Sweep ini menghapus file >24 jam yang tidak direferensikan
* `TripImage` mana pun. Idempotent — aman dijalankan berulang.
*
* Trigger: lihat docs/CRON_SETUP.md. Header wajib `Authorization: Bearer ${CRON_SECRET}`.
*/
export async function GET(req: NextRequest) {
const secret = process.env.CRON_SECRET;
if (!secret) {
console.error("[cron/cleanup-trip-images] CRON_SECRET tidak di-set");
return NextResponse.json(
{ error: "Server misconfigured" },
{ status: 500 }
);
}
if (req.headers.get("authorization") !== `Bearer ${secret}`) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const outcome = await runCron("cleanup-trip-images", async () => {
const names = await listTripImageNames();
if (names.length === 0) return { scanned: 0, deleted: 0 };
const referenced = await prisma.tripImage.findMany({
where: { url: { startsWith: TRIP_IMAGE_URL_PREFIX } },
select: { url: true },
});
const referencedNames = new Set(
referenced.map((r) => r.url.slice(TRIP_IMAGE_URL_PREFIX.length))
);
const now = Date.now();
let deleted = 0;
for (const name of names) {
if (referencedNames.has(name)) continue;
const mtime = await tripImageMtime(name);
// File baru di-upload tapi trip belum tersimpan → beri tenggang 24 jam.
if (!mtime || now - mtime.getTime() < ORPHAN_AGE_MS) continue;
await deleteTripImage(name);
deleted++;
}
return { scanned: names.length, deleted };
});
if (!outcome.ok) {
console.error("[cron/cleanup-trip-images] gagal", outcome.error);
return NextResponse.json(
{ error: "Gagal menjalankan cleanup" },
{ status: 500 }
);
}
console.log("[cron/cleanup-trip-images] selesai", outcome.payload);
return NextResponse.json({ ok: true, ...outcome.payload });
}