fix: FormData stream exhausted on retry + undefined segments crash
Two bugs triggered together when the model was unloaded during a job: 1. submitJob() created FormData/createReadStream once outside the retry loop. After a 503, the audio ReadStream was consumed and subsequent retries sent an empty body to whisper, causing it to return segments:undefined. 2. webhook handler cast whisperJob.segments as Segment[] without guarding against undefined, so deduplicateSegments(undefined) crashed with 'Cannot read properties of undefined (reading 'map')' — stored as job.error. Fixes: - Move FormData + createReadStream inside the retry loop (fresh stream per attempt) - Use (whisperJob.segments ?? []) in webhook handler - Add Array.isArray guard at top of deduplicateSegments() as belt-and-suspenders Tests: - New: verifies createReadStream called once per attempt (3 attempts = 3 streams) - New: webhook handles segments:undefined without throwing - New: webhook handles segments:null without throwing - 150/150 passing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -289,6 +289,34 @@ describe('POST /api/webhook/[jobId] — empty segments', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// ── Undefined / missing segments (model returned no segments field) ───────────
|
||||
|
||||
describe('POST /api/webhook/[jobId] — undefined segments', () => {
|
||||
it('completes the job as done when segments field is absent from whisper payload', async () => {
|
||||
mockGetJob.mockReturnValue(makeJob('job-noseg'));
|
||||
// Simulate whisper returning a result without a segments field
|
||||
const payload = { ...makeWhisperJob(), segments: undefined as unknown as never[] };
|
||||
|
||||
const res = await POST(makeEvent('job-noseg', payload) as any);
|
||||
expect(res.status).toBe(200);
|
||||
expect(await res.json()).toEqual({ ok: true });
|
||||
expect(mockUpdateJob).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ status: 'done', id: 'job-noseg' })
|
||||
);
|
||||
});
|
||||
|
||||
it('does not throw "cannot read properties of undefined" when segments is null', async () => {
|
||||
mockGetJob.mockReturnValue(makeJob('job-nullseg'));
|
||||
const payload = { ...makeWhisperJob(), segments: null as unknown as never[] };
|
||||
|
||||
// Must NOT throw — previously crashed with "Cannot read properties of undefined (reading 'map')"
|
||||
await expect(POST(makeEvent('job-nullseg', payload) as any)).resolves.toBeDefined();
|
||||
expect(mockUpdateJob).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ status: 'done' })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ── Internal error handling ───────────────────────────────────────────────────
|
||||
|
||||
describe('POST /api/webhook/[jobId] — internal errors', () => {
|
||||
|
||||
Reference in New Issue
Block a user