import type { Server } from "node:http"; import { stopScheduledJobs } from "../services/scheduler/scheduler-service.js"; import { closeOcrService } from "../services/session/ocr.js"; import { closeAllTencentBrowserSessions } from "../services/session/session.js"; import { logError, logInfo } from "../utils/logger.js"; import type { StartupState } from "./state.js"; export function createShutdownController(server: Server, startupState: StartupState) { let shutdownStarted = false; async function shutdown(signal: string) { if (shutdownStarted) { return; } shutdownStarted = true; startupState.phase = "shutting_down"; logInfo("[shutdown]", `received ${signal}, closing browser sessions and HTTP server`); stopScheduledJobs(); try { await closeAllTencentBrowserSessions({ markClosed: true }); } catch (error) { logError("[shutdown]", "failed to close browser sessions", error); } try { await closeOcrService(); } catch (error) { logError("[shutdown]", "failed to close OCR service", error); } if (!server.listening) { return; } await new Promise((resolve) => { server.close((error) => { if (error) { logError("[shutdown]", "failed to close HTTP server", error); process.exitCode = 1; } resolve(); }); }); } return { isShutdownStarted: () => shutdownStarted, shutdown, }; }