Files
twotalesanimation 81ad7e4ea9 Initial commit
2026-06-11 10:46:09 +02:00

61 lines
1.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// app/api/transcoder/claim/route.ts
// Atomically claims the next available transcoding job.
// Uses SELECT … FOR UPDATE SKIP LOCKED so multiple workers never race on the
// same video.
import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { Prisma } from "@prisma/client";
import { verifyTranscoderToken } from "@/lib/transcoder-auth";
export const dynamic = "force-dynamic";
export async function POST(request: Request) {
if (!verifyTranscoderToken(request)) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
try {
const video = await prisma.$transaction(async (tx) => {
// Atomically lock the oldest uploaded video, skipping rows already
// locked by concurrent workers.
const rows = await tx.$queryRaw<{ id: string }[]>(
Prisma.sql`
SELECT id
FROM "Video"
WHERE "transcodingStatus" = 'uploaded'
ORDER BY "createdAt" ASC
LIMIT 1
FOR UPDATE SKIP LOCKED
`
);
if (rows.length === 0) return null;
return tx.video.update({
where: { id: rows[0].id },
data: { transcodingStatus: "processing" },
});
});
if (!video) {
// No work available return null body so the worker knows to stop.
return NextResponse.json(null, { status: 200 });
}
// Build the download URL from the public CMS base URL.
const cmsBase =
process.env.NEXTAUTH_URL?.replace(/\/$/, "") ??
process.env.CMS_PUBLIC_URL?.replace(/\/$/, "") ??
"";
return NextResponse.json({
videoId: video.id,
downloadUrl: `${cmsBase}/api/transcoder/download/${video.id}`,
});
} catch (err) {
console.error("[Transcoder Claim] Error:", err);
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
}
}