2026-08-15 18:37:30 +02:00
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
|
|
|
|
|
|
import { eq } from "drizzle-orm";
|
|
|
|
|
import { requireAuth, unauthorizedResponse } from "@/lib/auth/guard";
|
|
|
|
|
import { getDb } from "@/lib/db/client";
|
|
|
|
|
import { runs } from "@/lib/db/schema";
|
|
|
|
|
import { cancelRun } from "@/lib/runner/registry";
|
2026-08-19 09:54:16 +02:00
|
|
|
import { logger } from "@/lib/logger";
|
|
|
|
|
|
|
|
|
|
const log = logger.child({ mod: "api" });
|
2026-08-15 18:37:30 +02:00
|
|
|
|
|
|
|
|
export async function POST(
|
|
|
|
|
request: Request,
|
|
|
|
|
{ params }: { params: Promise<{ runId: string }> },
|
|
|
|
|
) {
|
|
|
|
|
const auth = await requireAuth(request);
|
|
|
|
|
if (!auth.authenticated) return unauthorizedResponse();
|
|
|
|
|
|
|
|
|
|
const { runId } = await params;
|
|
|
|
|
const db = getDb();
|
|
|
|
|
const run = db.select().from(runs).where(eq(runs.id, runId)).get();
|
|
|
|
|
if (!run) return Response.json({ error: "Run not found" }, { status: 404 });
|
|
|
|
|
|
|
|
|
|
if (run.status !== "queued" && run.status !== "running") {
|
|
|
|
|
return Response.json(
|
|
|
|
|
{ error: `Run already ${run.status}` },
|
|
|
|
|
{ status: 409 },
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const cancelled = cancelRun(runId);
|
|
|
|
|
if (!cancelled) {
|
2026-08-19 09:54:16 +02:00
|
|
|
log.warn(
|
|
|
|
|
{ runId },
|
|
|
|
|
"cancel requested for a run not tracked by this process",
|
|
|
|
|
);
|
2026-08-15 18:37:30 +02:00
|
|
|
return Response.json(
|
|
|
|
|
{ error: "Run is not active in this server process" },
|
|
|
|
|
{ status: 409 },
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-19 09:54:16 +02:00
|
|
|
log.info({ runId, requestedBy: auth.identity }, "cancel requested via API");
|
2026-08-15 18:37:30 +02:00
|
|
|
return Response.json({ status: "cancelling" }, { status: 202 });
|
|
|
|
|
}
|