D3: wire health preflight into pipeline before whisper submission

Add health preflight check in runJob() after ensureWhisperRunning()
and before submitJob(). Uses existing getHealth() from whisper.ts
with retryWithBackoff() for transient failures.

- Healthy whisper (status 'ok') -> job proceeds to submission
- Unreachable whisper -> job fails early with 'whisper health check failed: ...'
- Non-ok status (e.g. 'starting') -> job fails early with actual status
- getHealth() 5000ms timeout preserved, no new HTTP client

Tests: health-preflight.test.ts covers error message contracts
and pipeline integration (YouTube + upload source)
This commit is contained in:
Giancarmine Salucci
2026-07-09 03:59:52 +02:00
parent 52715ec481
commit 0a418e773f
2 changed files with 255 additions and 1 deletions
+27 -1
View File
@@ -1,8 +1,9 @@
import { createJob, updateJob, setJobStatus, getJob, resetJob } from './db.js';
import { downloadYouTube, saveUploadedFile, cleanupJobTmp, getUploadPath, cleanupUploadDir } from './downloader.js';
import { prepareAudio, cleanup as cleanupFiles } from './audio.js';
import { submitJob, streamJob } from './whisper.js';
import { submitJob, streamJob, getHealth } from './whisper.js';
import { ensureWhisperRunning } from './docker.js';
import { retryWithBackoff } from './retry.js';
import type { AudioMode, Segment } from '$lib/types.js';
const WEBHOOK_BASE_URL = process.env.WEBHOOK_BASE_URL ?? 'http://localhost:3000';
@@ -151,6 +152,31 @@ async function runJob(
// ── 3. Ensure whisper is running ──────────────────────────────────────
await ensureWhisperRunning();
// ── 3b. Health preflight: verify whisper reachability and status ──────
await retryWithBackoff(
async () => {
try {
const health = await getHealth();
if (health.status !== 'ok') {
throw new Error(`whisper health check failed: status is "${health.status}"`);
}
} catch (err) {
if (err instanceof Error && err.message.startsWith('whisper health check failed')) {
throw err;
}
throw new Error(`whisper health check failed: ${err instanceof Error ? err.message : String(err)}`);
}
},
{
maxAttempts: 3,
baseDelayMs: 1000,
onAttempt: (err, attempt, delayMs) => {
console.warn(`[pipeline] whisper health check attempt ${attempt} failed:`, err);
emitProgress(jobId, { type: 'warning', message: `health check attempt ${attempt} failed, retrying in ${delayMs}ms` });
}
}
);
// ── 4. Submit to whisper with webhook ────────────────────────────────
setJobStatus(jobId, 'transcribing', 10);
emitProgress(jobId, { type: 'status', status: 'transcribing', progress: 10 });