import { NextRequest, NextResponse } from "next/server"; import fs from "node:fs/promises"; import { assertLocalRequest } from "@/lib/api/localOnly"; import { getJob, estimateRealtimeMultiplier } from "@/lib/whisperjav/db"; export const runtime = "nodejs"; export const dynamic = "force-dynamic"; const LOG_TAIL_LINES = 50; export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string }> }) { const blocked = assertLocalRequest(req); if (blocked) return blocked; const { id } = await ctx.params; const job = getJob(id); if (!job) return NextResponse.json({ error: "Not found" }, { status: 404 }); let logTail: string[] = []; try { const raw = await fs.readFile(job.logPath, "utf8"); const lines = raw.split(/\r?\n/); logTail = lines.slice(-LOG_TAIL_LINES - 1).filter(Boolean); } catch { /* log may not exist yet */ } // ETA: per-mode multiplier from history × video duration − elapsed. // Returns null when we can't compute (no duration / not running yet). let etaSec: number | null = null; if ( (job.status === "queued" || job.status === "running") && job.videoDurationSec && job.videoDurationSec > 0 && job.mode ) { const multiplier = estimateRealtimeMultiplier(job.mode); const totalProjected = job.videoDurationSec * multiplier; const start = job.startedAt ?? job.enqueuedAt; const elapsedSec = (Date.now() - start) / 1000; etaSec = Math.max(0, totalProjected - elapsedSec); } return NextResponse.json({ ...job, logTail, etaSec }); }