fix: serialise local Cog model calls with a queue to prevent 409 conflicts

This commit is contained in:
2026-03-10 10:39:06 +01:00
parent 41d2aa7295
commit 171b40f525

View File

@@ -90,12 +90,13 @@ async function translateViaCloud(
return extractText(data.output as ReplicateOutput);
}
async function translateViaLocal(
text: string,
targetLanguage: string
): Promise<string> {
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<void> = Promise.resolve();
async function callLocalModel(text: string, targetLanguage: string): Promise<string> {
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<string> {
// Enqueue — wait for any in-flight local call to finish first
let resolve!: () => void;
const slot = new Promise<void>(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