stop button aborts queue loop, remaining jobs stay pending in queue
Build and Push Docker Image / build (push) Successful in 6m48s

previously stop only killed the running ffmpeg process — the loop
immediately picked up the next pending job. now the abort signal
breaks the loop between jobs, so remaining items stay in the queue
column as pending jobs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-20 15:46:31 +02:00
parent c985bb9f04
commit 65acc683b9
2 changed files with 13 additions and 4 deletions
+12 -3
View File
@@ -21,6 +21,7 @@ const app = new Hono();
// ─── Sequential local queue ──────────────────────────────────────────────────
let queueRunning = false;
let queueAbort: AbortController | null = null;
let runningProc: ReturnType<typeof Bun.spawn> | null = null;
let runningJobId: number | null = null;
let activeQueue: Job[] | null = null;
@@ -65,6 +66,8 @@ function emitQueueStatus(
async function runSequential(initial: Job[]): Promise<void> {
if (queueRunning) return;
queueRunning = true;
queueAbort = new AbortController();
const { signal } = queueAbort;
try {
let first = true;
const queue: Job[] = [...initial];
@@ -73,6 +76,7 @@ async function runSequential(initial: Job[]): Promise<void> {
activeSeen = seen;
while (queue.length > 0) {
if (signal.aborted) break;
const job = queue.shift() as Job;
// Pause outside the processing window
@@ -111,8 +115,8 @@ async function runSequential(initial: Job[]): Promise<void> {
// When the local queue drains, re-check the DB for jobs that were
// approved mid-run. Without this they'd sit pending until the user
// manually clicks "Run all" again.
if (queue.length === 0) {
// manually clicks "Run all" again. Skip if aborted — user wants to stop.
if (queue.length === 0 && !signal.aborted) {
const more = db.prepare("SELECT * FROM jobs WHERE status = 'pending' ORDER BY created_at").all() as Job[];
enqueueUnseenJobs(queue, seen, more);
}
@@ -121,6 +125,7 @@ async function runSequential(initial: Job[]): Promise<void> {
activeQueue = null;
activeSeen = null;
queueRunning = false;
queueAbort = null;
emitQueueStatus("idle");
}
}
@@ -300,8 +305,12 @@ app.post("/clear-completed", (c) => {
// ─── Stop running job ─────────────────────────────────────────────────────────
app.post("/stop", (c) => {
// Abort the queue loop so no more jobs start after the current one
if (queueAbort) queueAbort.abort();
if (!runningProc || runningJobId == null) {
return c.json({ ok: false, error: "No job is currently running" }, 409);
// No active ffmpeg but queue loop might be between jobs — abort is enough
return c.json({ ok: true, stopped: null });
}
const stoppedId = runningJobId;
try {