diff --git a/package.json b/package.json index c732dd9..512b524 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "netfelix-audio-fix", - "version": "2026.04.20.12", + "version": "2026.04.20.13", "scripts": { "dev:server": "NODE_ENV=development bun --hot server/index.tsx", "dev:client": "vite", diff --git a/server/api/execute.ts b/server/api/execute.ts index 9b5dcde..39c6104 100644 --- a/server/api/execute.ts +++ b/server/api/execute.ts @@ -21,6 +21,7 @@ const app = new Hono(); // ─── Sequential local queue ────────────────────────────────────────────────── let queueRunning = false; +let queueAbort: AbortController | null = null; let runningProc: ReturnType | null = null; let runningJobId: number | null = null; let activeQueue: Job[] | null = null; @@ -65,6 +66,8 @@ function emitQueueStatus( async function runSequential(initial: Job[]): Promise { 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 { 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 { // 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 { 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 {