feat(web): per-item pause route for queued jobs
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { POST } from "./route";
|
||||
import { prisma } from "@/lib/db";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
|
||||
function req(id: string, paused: boolean) {
|
||||
return new Request(`http://localhost/api/requests/${id}/pause`, {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({ paused }),
|
||||
});
|
||||
}
|
||||
|
||||
async function seed(jobData: Prisma.JobCreateWithoutRequestInput) {
|
||||
return prisma.request.create({
|
||||
data: { artist: "A", album: "B", status: "pending", job: { create: jobData } },
|
||||
include: { job: true },
|
||||
});
|
||||
}
|
||||
|
||||
describe("per-item pause API", () => {
|
||||
it("pauses a queued job", async () => {
|
||||
const created = await seed({ state: "requested" });
|
||||
const res = await POST(req(created.id, true), { params: Promise.resolve({ id: created.id }) });
|
||||
expect(res.status).toBe(200);
|
||||
const job = await prisma.job.findUnique({ where: { id: created.job!.id } });
|
||||
expect(job?.paused).toBe(true);
|
||||
});
|
||||
|
||||
it("resumes a paused job", async () => {
|
||||
const created = await seed({ state: "requested", paused: true });
|
||||
await POST(req(created.id, false), { params: Promise.resolve({ id: created.id }) });
|
||||
const job = await prisma.job.findUnique({ where: { id: created.job!.id } });
|
||||
expect(job?.paused).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects pausing an in-flight job", async () => {
|
||||
const created = await seed({ state: "downloading" });
|
||||
const res = await POST(req(created.id, true), { params: Promise.resolve({ id: created.id }) });
|
||||
expect(res.status).toBe(400);
|
||||
});
|
||||
|
||||
it("404s for a missing request", async () => {
|
||||
const res = await POST(req("nope", true), { params: Promise.resolve({ id: "nope" }) });
|
||||
expect(res.status).toBe(404);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
import { prisma } from "@/lib/db";
|
||||
|
||||
export async function POST(request: Request, { params }: { params: Promise<{ id: string }> }) {
|
||||
const { id } = await params;
|
||||
|
||||
let body: { paused?: unknown };
|
||||
try {
|
||||
body = (await request.json()) as { paused?: unknown };
|
||||
} catch {
|
||||
return Response.json({ error: "invalid JSON" }, { status: 400 });
|
||||
}
|
||||
if (typeof body.paused !== "boolean") {
|
||||
return Response.json({ error: "paused must be a boolean" }, { status: 400 });
|
||||
}
|
||||
|
||||
const req = await prisma.request.findUnique({ where: { id }, include: { job: true } });
|
||||
if (!req || !req.job) {
|
||||
return Response.json({ error: "not found" }, { status: 404 });
|
||||
}
|
||||
if (req.job.state !== "requested") {
|
||||
return Response.json({ error: "only queued jobs can be paused" }, { status: 400 });
|
||||
}
|
||||
|
||||
await prisma.job.update({ where: { id: req.job.id }, data: { paused: body.paused } });
|
||||
return Response.json({ ok: true, paused: body.paused });
|
||||
}
|
||||
Reference in New Issue
Block a user