From 171b40f525194ce90e28f0705708b1cf90d39be8 Mon Sep 17 00:00:00 2001 From: Malin Date: Tue, 10 Mar 2026 10:39:06 +0100 Subject: [PATCH] fix: serialise local Cog model calls with a queue to prevent 409 conflicts --- utils/replicate-translate.ts | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/utils/replicate-translate.ts b/utils/replicate-translate.ts index 304812a..f12be8e 100644 --- a/utils/replicate-translate.ts +++ b/utils/replicate-translate.ts @@ -90,12 +90,13 @@ async function translateViaCloud( return extractText(data.output as ReplicateOutput); } -async function translateViaLocal( - text: string, - targetLanguage: string -): Promise { - const settings = readSettings(); +// The local Cog model handles exactly one prediction at a time. +// This queue ensures calls are strictly serialised regardless of +// how many batches / concurrent requests come in. +let localQueue: Promise = Promise.resolve(); +async function callLocalModel(text: string, targetLanguage: string): Promise { + const settings = readSettings(); if (!settings.jigsawApiKey) throw new Error("JigsawStack API key not configured"); const endpoint = (settings.localEndpoint || "http://localhost:5030/predictions").replace(/\/$/, ""); @@ -118,14 +119,24 @@ async function translateViaLocal( } const data: CogOutput = await response.json(); - if (data.error) throw new Error(`Local model error: ${data.error}`); - // Cog wraps output in { status, output } or returns output directly const output = data.output !== undefined ? data.output : data; return extractText(output); } +async function translateViaLocal( + text: string, + targetLanguage: string +): Promise { + // Enqueue — wait for any in-flight local call to finish first + let resolve!: () => void; + const slot = new Promise(r => { resolve = r; }); + const turn = localQueue.then(() => callLocalModel(text, targetLanguage)); + localQueue = turn.then(resolve, resolve); // advance queue whether success or error + return turn; +} + export async function replicateTranslate( text: string, targetLanguage: string