import { NextResponse } from "next/server"; import { prisma } from "@/lib/db"; import { authErrorResponse } from "@/lib/auth/api"; import { requireSessionUser } from "@/lib/auth/session"; import { recoverStaleBackgroundJobs } from "@/lib/jobs/runner"; export async function GET(request: Request) { try { const user = await requireSessionUser(); const { searchParams } = new URL(request.url); const activeOnly = searchParams.get("active") === "1"; const topicId = searchParams.get("topicId"); const limit = Math.min(parseInt(searchParams.get("limit") ?? "10", 10), 30); const userAccounts = await prisma.account.findMany({ where: { userId: user.id }, select: { id: true }, }); const accountIds = userAccounts.map((account) => account.id); if (accountIds.length === 0) { return NextResponse.json({ jobs: [] }); } if (activeOnly) { await recoverStaleBackgroundJobs(); } const baseWhere = { accountId: { in: accountIds }, ...(topicId ? { topicId } : {}), }; const jobs = activeOnly ? await prisma.backgroundJob.findMany({ where: { ...baseWhere, status: { in: ["pending", "running"] } }, orderBy: { createdAt: "desc" }, }) : await Promise.all([ prisma.backgroundJob.findMany({ where: { ...baseWhere, status: { in: ["pending", "running"] } }, orderBy: { createdAt: "desc" }, }), prisma.backgroundJob.findMany({ where: baseWhere, orderBy: { createdAt: "desc" }, take: limit, }), ]).then(([active, recent]) => { const merged = new Map([...active, ...recent].map((job) => [job.id, job])); return [...merged.values()].sort( (a, b) => b.createdAt.getTime() - a.createdAt.getTime() ); }); return NextResponse.json({ jobs }); } catch (error) { const authRes = authErrorResponse(error); if (authRes) return authRes; console.error("[jobs GET]", error); return NextResponse.json( { error: error instanceof Error ? error.message : "載入任務失敗", jobs: [] }, { status: 500 } ); } }