Initial commit
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
// 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 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user