feat: add initDispatcher() for eager sidecar startup

The dispatcher was lazy-initialized on first AI request, but a race
condition meant the first call always missed it (dispatcherReady still
false) and fell through to cold per-request Python. initDispatcher()
starts the dispatcher eagerly and returns a Promise that resolves with
GPU status once ready (or after a timeout).
This commit is contained in:
SnapOtter
2026-04-30 18:48:15 +08:00
parent 6d5d0a3673
commit b344edf416
3 changed files with 135 additions and 1 deletions
+38
View File
@@ -330,6 +330,44 @@ export function shutdownDispatcher(): void {
}
}
/**
* Eagerly start the Python dispatcher and wait for its readiness signal.
* Returns the GPU status once ready, or {ready: false} on timeout/failure.
* Safe to call multiple times -- idempotent if the dispatcher is already running.
*/
export function initDispatcher(timeoutMs = 30_000): Promise<{ ready: boolean; gpu: boolean }> {
if (dispatcherReady) {
return Promise.resolve({ ready: true, gpu: dispatcherGpuAvailable });
}
if (dispatcherFailed) {
return Promise.resolve({ ready: false, gpu: false });
}
const proc = getDispatcher();
if (!proc) {
return Promise.resolve({ ready: false, gpu: false });
}
return new Promise((resolve) => {
const timer = setTimeout(() => {
clearInterval(poll);
resolve({ ready: false, gpu: false });
}, timeoutMs);
const poll = setInterval(() => {
if (dispatcherReady) {
clearTimeout(timer);
clearInterval(poll);
resolve({ ready: true, gpu: dispatcherGpuAvailable });
} else if (dispatcherFailed) {
clearTimeout(timer);
clearInterval(poll);
resolve({ ready: false, gpu: false });
}
}, 50);
});
}
// ── Per-request fallback (original implementation) ──────────────────
function runPythonPerRequest(