77 lines
1.9 KiB
TypeScript
77 lines
1.9 KiB
TypeScript
|
|
import { createAdminClient } from "@/lib/supabase/admin";
|
||
|
|
import type { RenderRequest, RenderJobStatus } from "@/lib/render-schemas";
|
||
|
|
|
||
|
|
export interface RenderJobRow {
|
||
|
|
id: string;
|
||
|
|
project_id: string;
|
||
|
|
status: RenderJobStatus;
|
||
|
|
progress: number;
|
||
|
|
progress_message: string | null;
|
||
|
|
output_url: string | null;
|
||
|
|
scenes: RenderRequest["scenes"];
|
||
|
|
settings: RenderRequest["settings"];
|
||
|
|
error_message: string | null;
|
||
|
|
created_at: string;
|
||
|
|
updated_at: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function createRenderJob(
|
||
|
|
payload: RenderRequest
|
||
|
|
): Promise<{ jobId: string } | { error: string }> {
|
||
|
|
const supabase = createAdminClient();
|
||
|
|
|
||
|
|
const { data, error } = await supabase
|
||
|
|
.from("render_jobs")
|
||
|
|
.insert({
|
||
|
|
project_id: payload.projectId,
|
||
|
|
status: "queued",
|
||
|
|
progress: 0,
|
||
|
|
progress_message: "Queued for rendering",
|
||
|
|
scenes: payload.scenes,
|
||
|
|
settings: payload.settings,
|
||
|
|
})
|
||
|
|
.select("id")
|
||
|
|
.single();
|
||
|
|
|
||
|
|
if (error || !data) {
|
||
|
|
return { error: error?.message ?? "Failed to create render job" };
|
||
|
|
}
|
||
|
|
|
||
|
|
return { jobId: data.id };
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function getRenderJob(
|
||
|
|
jobId: string
|
||
|
|
): Promise<RenderJobRow | null> {
|
||
|
|
const supabase = createAdminClient();
|
||
|
|
|
||
|
|
const { data, error } = await supabase
|
||
|
|
.from("render_jobs")
|
||
|
|
.select("*")
|
||
|
|
.eq("id", jobId)
|
||
|
|
.maybeSingle();
|
||
|
|
|
||
|
|
if (error || !data) return null;
|
||
|
|
return data as RenderJobRow;
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function triggerRenderWorker(jobId: string): Promise<void> {
|
||
|
|
const workerUrl = process.env.RENDER_WORKER_URL;
|
||
|
|
if (!workerUrl) return;
|
||
|
|
|
||
|
|
const secret = process.env.RENDER_WORKER_SECRET;
|
||
|
|
|
||
|
|
try {
|
||
|
|
await fetch(`${workerUrl.replace(/\/$/, "")}/process`, {
|
||
|
|
method: "POST",
|
||
|
|
headers: {
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
...(secret ? { Authorization: `Bearer ${secret}` } : {}),
|
||
|
|
},
|
||
|
|
body: JSON.stringify({ jobId }),
|
||
|
|
});
|
||
|
|
} catch {
|
||
|
|
// Worker may be offline; job stays queued for retry/poll
|
||
|
|
}
|
||
|
|
}
|