UNPKG

donobu

Version:

Create browser automations with an LLM agent and replay them as Playwright scripts.

117 lines 5.08 kB
"use strict"; /** * @fileoverview Application initialization and global error handling setup. * * This module configures comprehensive error handling for the Node.js application, * including unhandled promise rejections, uncaught exceptions, and graceful * shutdown handling for various system signals. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.installCrashHandlers = installCrashHandlers; exports.installShutdownHandlers = installShutdownHandlers; const fileUploadWorkerRegistry_1 = require("./persistence/files/fileUploadWorkerRegistry"); const JsonUtils_1 = require("./utils/JsonUtils"); const Logger_1 = require("./utils/Logger"); const SHUTDOWN_FLUSH_TIMEOUT_MS = 30_000; /** * Installs global error handlers that crash the process on unhandled errors. * * **This must only be called when running as a standalone server** (i.e. from * the CLI entry point), never when the library is imported by external * consumers. Registering process-wide exit handlers from a library hijacks the * host application's error handling and can kill test runners or other * long-lived processes unexpectedly. */ function installCrashHandlers() { /** * Handles unhandled promise rejections to prevent silent failures. * * When a Promise is rejected and no rejection handler is attached, * this handler logs the error details and terminates the process * to ensure failures are not ignored. * * @see {@link https://nodejs.org/api/process.html#event-unhandledrejection} */ process.on('unhandledRejection', (reason, promise) => { const errorDetails = JSON.stringify(JsonUtils_1.JsonUtils.objectToJson({ reason: reason instanceof Error ? { message: reason.message, name: reason.name, stack: reason.stack, } : reason, promise: promise, }), null, 2); Logger_1.appLogger.error(`Unhandled Promise Rejection: ${errorDetails}`); process.exit(1); }); /** * Handles uncaught exceptions to prevent the application from crashing silently. * * When an exception is thrown and not caught by any try-catch block, * this handler logs the error details and terminates the process gracefully. * This is a last resort error handler and indicates a serious application bug. * * @see {@link https://nodejs.org/api/process.html#event-uncaughtexception} */ process.on('uncaughtException', (error) => { const errorDetails = JSON.stringify(JsonUtils_1.JsonUtils.objectToJson({ message: error.message, name: error.name, stack: error.stack, }), null, 2); Logger_1.appLogger.error(`Uncaught Exception: ${errorDetails}`); process.exit(1); }); } /** * Installs SIGTERM/SIGINT handlers that drain any in-flight file uploads * (bounded by {@link SHUTDOWN_FLUSH_TIMEOUT_MS}) before exiting cleanly. * * **Intended primarily as a developer / CLI fallback.** In production the * desktop app drives shutdown explicitly: it queries * `GET /api/uploads/status`, surfaces the count to the user, and either * (a) waits for the worker to drain on its own and then terminates the * backend, or (b) terminates immediately on user request. In that path * these handlers may not fire at all — terminations from the host are * what they are. * * For `node dist/main.js` runs (developers, integration tests), Ctrl+C * still benefits from a graceful drain so test artefacts don't pile up * as `.uploading.<token>` markers. * * Same constraint as {@link installCrashHandlers}: only call this when * running as a standalone server, never when imported as a library — * process-wide signal handlers would hijack the host. * * Uploads that don't complete within the timeout stay on disk as * `.uploading.<token>` markers; another Studio process will reclaim them * once the claim goes stale (5 min default). */ function installShutdownHandlers() { let shuttingDown = false; const handle = (signal) => { if (shuttingDown) { return; } shuttingDown = true; void (async () => { Logger_1.appLogger.info(`Received ${signal}; draining file upload workers.`); try { const result = await (0, fileUploadWorkerRegistry_1.shutdownFileUploadWorkers)(SHUTDOWN_FLUSH_TIMEOUT_MS); if (!result.drained) { Logger_1.appLogger.warn(`File upload queue did not fully drain at shutdown; ` + `${result.totalRemaining} upload(s) remain on disk and will resume on next start.`); } } catch (err) { Logger_1.appLogger.error(`Error draining file upload workers at shutdown: ${err.message}`); } process.exit(0); })(); }; process.on('SIGTERM', handle); process.on('SIGINT', handle); } //# sourceMappingURL=init.js.map