// app/api/transcoder/fail/[videoId]/route.ts // Marks a video job as failed. Called by the remote worker when transcoding // or upload encounters an unrecoverable error. import { NextResponse } from "next/server"; import { prisma } from "@/lib/prisma"; import { verifyTranscoderToken } from "@/lib/transcoder-auth"; const SAFE_ID = /^[a-zA-Z0-9_-]{1,64}$/; export async function POST( request: Request, context: { params: Promise<{ videoId: string }> } ) { if (!verifyTranscoderToken(request)) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } const { videoId } = await context.params; if (!SAFE_ID.test(videoId)) { return NextResponse.json({ error: "Invalid video ID" }, { status: 400 }); } const video = await prisma.video.findUnique({ where: { id: videoId } }); if (!video) { return NextResponse.json({ error: "Not found" }, { status: 404 }); } try { await prisma.video.update({ where: { id: videoId }, data: { transcodingStatus: "failed" }, }); // Log the error message from the worker if provided. let workerError = ""; try { const body = await request.json(); workerError = typeof body?.error === "string" ? body.error : ""; } catch { // Body may be empty – that's fine. } console.error( `[Transcoder Fail] ${videoId}${workerError ? ` – ${workerError}` : ""}` ); return NextResponse.json({ success: true }); } catch (err) { console.error(`[Transcoder Fail] DB error for ${videoId}:`, err); return NextResponse.json({ error: "Internal server error" }, { status: 500 }); } }