import type { Server as HttpServer } from "node:http";
import type { ServerManager } from "../client/manager.js";
import logger from "./logger.js";
let isShuttingDown = false;
export function setupGracefulShutdown(
httpServer: HttpServer,
manager: ServerManager,
cleanupFn?: () => Promise<void>
): void {
const shutdown = async (signal: string) => {
if (isShuttingDown) return;
isShuttingDown = true;
logger.info(`Received ${signal}, starting graceful shutdown...`);
// Stop accepting new connections
httpServer.close((err) => {
if (err) {
logger.error("Error closing HTTP server", { error: err.message });
} else {
logger.info("HTTP server closed");
}
});
try {
// Close all MCP client connections
await manager.closeAll();
// Run any additional cleanup
if (cleanupFn) {
await cleanupFn();
}
logger.info("Graceful shutdown complete");
process.exit(0);
} catch (err) {
logger.error("Error during shutdown", { error: (err as Error).message });
process.exit(1);
}
};
process.on("SIGINT", () => shutdown("SIGINT"));
process.on("SIGTERM", () => shutdown("SIGTERM"));
// Handle uncaught errors
process.on("uncaughtException", (err) => {
logger.error("Uncaught exception", { error: err.message, stack: err.stack });
shutdown("uncaughtException").catch(() => process.exit(1));
});
process.on("unhandledRejection", (reason) => {
logger.error("Unhandled rejection", { reason: String(reason) });
});
}