Harden loopback worker shutdown
This commit is contained in:
69
src/index.ts
69
src/index.ts
@@ -12,6 +12,52 @@ async function runLoopback(): Promise<void> {
|
||||
const config = loadConfig();
|
||||
const logger = new Logger(config.LOG_LEVEL);
|
||||
const stt = new FasterWhisperSttService(config, logger);
|
||||
let capture = null as ReturnType<typeof spawnLoopbackCapture> | null;
|
||||
let shuttingDown: Promise<void> | null = null;
|
||||
|
||||
const shutdown = async (exitCode: number, reason: string, error?: unknown): Promise<void> => {
|
||||
if (shuttingDown) {
|
||||
return await shuttingDown;
|
||||
}
|
||||
|
||||
shuttingDown = (async () => {
|
||||
if (error) {
|
||||
logger.error(`Shutting down: ${reason}`, error);
|
||||
} else {
|
||||
logger.info("Shutting down", reason);
|
||||
}
|
||||
|
||||
if (capture && !capture.killed && capture.exitCode === null) {
|
||||
capture.kill("SIGTERM");
|
||||
}
|
||||
|
||||
await stt.destroy().catch((destroyError) => {
|
||||
logger.warn("STT destroy failed", destroyError);
|
||||
});
|
||||
})();
|
||||
|
||||
await shuttingDown;
|
||||
process.exit(exitCode);
|
||||
};
|
||||
|
||||
process.once("SIGINT", () => {
|
||||
void shutdown(0, "SIGINT");
|
||||
});
|
||||
process.once("SIGTERM", () => {
|
||||
void shutdown(0, "SIGTERM");
|
||||
});
|
||||
process.once("uncaughtException", (error) => {
|
||||
void shutdown(1, "uncaughtException", error);
|
||||
});
|
||||
process.once("unhandledRejection", (reason) => {
|
||||
void shutdown(1, "unhandledRejection", reason);
|
||||
});
|
||||
process.once("exit", () => {
|
||||
if (capture && !capture.killed && capture.exitCode === null) {
|
||||
capture.kill("SIGKILL");
|
||||
}
|
||||
void stt.destroy();
|
||||
});
|
||||
|
||||
await stt.warmup();
|
||||
|
||||
@@ -53,7 +99,7 @@ async function runLoopback(): Promise<void> {
|
||||
},
|
||||
});
|
||||
|
||||
const capture = spawnLoopbackCapture(config, logger);
|
||||
capture = spawnLoopbackCapture(config, logger);
|
||||
capture.stdout.on("data", (chunk: Buffer) => {
|
||||
segmenter.pushChunk(chunk);
|
||||
});
|
||||
@@ -63,29 +109,20 @@ async function runLoopback(): Promise<void> {
|
||||
logger.debug("[capture]", text);
|
||||
}
|
||||
});
|
||||
capture.on("error", (error) => {
|
||||
void shutdown(1, "capture-error", error);
|
||||
});
|
||||
capture.on("exit", (code, signal) => {
|
||||
logger.warn("capture exited", { code, signal });
|
||||
if (!shuttingDown) {
|
||||
void shutdown(1, "capture-exit");
|
||||
}
|
||||
});
|
||||
|
||||
console.log("실시간 출력장치 STT를 시작합니다. Ctrl+C 로 종료합니다.");
|
||||
console.log(`source: ${config.AUDIO_SOURCE ?? "unset"}`);
|
||||
console.log(`model: ${config.WHISPER_MODEL}`);
|
||||
console.log(`language: ${config.WHISPER_LANGUAGE}`);
|
||||
|
||||
const shutdown = async (): Promise<void> => {
|
||||
if (!capture.killed) {
|
||||
capture.kill("SIGTERM");
|
||||
}
|
||||
await stt.destroy();
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
process.on("SIGINT", () => {
|
||||
void shutdown();
|
||||
});
|
||||
process.on("SIGTERM", () => {
|
||||
void shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
|
||||
Reference in New Issue
Block a user