Bound shutdown and print single-line startup failures
Claude-Session: https://claude.ai/code/session_01JtuZTCMW9TyogEmBgGf8JT
This commit is contained in:
35
src/main.ts
35
src/main.ts
@@ -13,6 +13,13 @@ import { Outbound } from "./telegram/outbound.js";
|
|||||||
import { createScheduleTool } from "./tools/schedule.js";
|
import { createScheduleTool } from "./tools/schedule.js";
|
||||||
import { ensureWorkspace } from "./workspace.js";
|
import { ensureWorkspace } from "./workspace.js";
|
||||||
|
|
||||||
|
function sleep(ms: number): Promise<void> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const timer = setTimeout(() => resolve(), ms);
|
||||||
|
timer.unref?.();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
const config = (() => {
|
const config = (() => {
|
||||||
try {
|
try {
|
||||||
@@ -57,8 +64,11 @@ async function main(): Promise<void> {
|
|||||||
stopping = true;
|
stopping = true;
|
||||||
logger.info(`shutting down (${reason})`);
|
logger.info(`shutting down (${reason})`);
|
||||||
await bot.stop().catch(() => undefined);
|
await bot.stop().catch(() => undefined);
|
||||||
await host?.abort().catch(() => undefined);
|
await Promise.race([host?.abort().catch(() => undefined), sleep(5000)]);
|
||||||
await scheduler.stop();
|
await scheduler.stop();
|
||||||
|
// Give in-flight Telegram API calls (the online message, a reply being sent, progress-message
|
||||||
|
// cleanup triggered by the abort) time to finish before the process exits.
|
||||||
|
await sleep(1000);
|
||||||
await host?.dispose().catch((err) => logger.warn("dispose failed", err));
|
await host?.dispose().catch((err) => logger.warn("dispose failed", err));
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
};
|
};
|
||||||
@@ -86,8 +96,20 @@ async function main(): Promise<void> {
|
|||||||
logger.info(`scheduler ready with ${scheduler.list().length} job(s)`);
|
logger.info(`scheduler ready with ${scheduler.list().length} job(s)`);
|
||||||
|
|
||||||
bot.catch((err) => logger.error("telegram handler error", err.error));
|
bot.catch((err) => logger.error("telegram handler error", err.error));
|
||||||
process.on("SIGINT", () => void shutdown("SIGINT"));
|
process.on("SIGINT", () => {
|
||||||
process.on("SIGTERM", () => void shutdown("SIGTERM"));
|
if (stopping) {
|
||||||
|
logger.warn("forced exit");
|
||||||
|
process.exit(130);
|
||||||
|
}
|
||||||
|
void shutdown("SIGINT");
|
||||||
|
});
|
||||||
|
process.on("SIGTERM", () => {
|
||||||
|
if (stopping) {
|
||||||
|
logger.warn("forced exit");
|
||||||
|
process.exit(130);
|
||||||
|
}
|
||||||
|
void shutdown("SIGTERM");
|
||||||
|
});
|
||||||
process.on("unhandledRejection", (err) => {
|
process.on("unhandledRejection", (err) => {
|
||||||
logger.error("unhandled rejection", err);
|
logger.error("unhandled rejection", err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -107,6 +129,11 @@ async function main(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main().catch((err) => {
|
main().catch((err) => {
|
||||||
console.error(err instanceof Error ? (err.stack ?? err.message) : String(err));
|
if (err instanceof Error) {
|
||||||
|
console.error(`Startup failed: ${err.name}: ${err.message}`);
|
||||||
|
if (process.env.LOG_LEVEL === "debug" && err.stack) console.error(err.stack);
|
||||||
|
} else {
|
||||||
|
console.error(`Startup failed: ${String(err)}`);
|
||||||
|
}
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user