fix(gateway): handle SIGTERM shutdown cleanly

This commit is contained in:
Peter Steinberger
2025-12-12 18:28:08 +00:00
parent c86cb4e9a5
commit 8fb3aef917
6 changed files with 72 additions and 7 deletions

View File

@@ -244,9 +244,16 @@ describe("partial reply gating", () => {
replyResolver,
);
const stored = JSON.parse(await fs.readFile(store.storePath, "utf8")) as {
main?: { lastChannel?: string; lastTo?: string };
};
let stored: { main?: { lastChannel?: string; lastTo?: string } } | null =
null;
for (let attempt = 0; attempt < 50; attempt += 1) {
stored = JSON.parse(await fs.readFile(store.storePath, "utf8")) as {
main?: { lastChannel?: string; lastTo?: string };
};
if (stored.main?.lastChannel && stored.main?.lastTo) break;
await new Promise((resolve) => setTimeout(resolve, 5));
}
if (!stored) throw new Error("store not loaded");
expect(stored.main?.lastChannel).toBe("whatsapp");
expect(stored.main?.lastTo).toBe("+1000");

View File

@@ -752,6 +752,7 @@ export async function monitorWebProvider(
// Batch inbound messages per conversation while command queue is busy.
type PendingBatch = { messages: WebInboundMsg[]; timer?: NodeJS.Timeout };
const pendingBatches = new Map<string, PendingBatch>();
const backgroundTasks = new Set<Promise<unknown>>();
const buildLine = (msg: WebInboundMsg) => {
// Build message prefix: explicit config > default based on allowFrom
@@ -863,7 +864,7 @@ export async function monitorWebProvider(
return normalizeE164(latest.from);
})();
if (to) {
void updateLastRoute({
const task = updateLastRoute({
storePath,
sessionKey: mainKey,
channel: "whatsapp",
@@ -874,6 +875,10 @@ export async function monitorWebProvider(
"failed updating last route",
);
});
backgroundTasks.add(task);
task.finally(() => {
backgroundTasks.delete(task);
});
}
}
@@ -1053,6 +1058,10 @@ export async function monitorWebProvider(
if (heartbeat) clearInterval(heartbeat);
if (replyHeartbeatTimer) clearInterval(replyHeartbeatTimer);
if (watchdogTimer) clearInterval(watchdogTimer);
if (backgroundTasks.size > 0) {
await Promise.allSettled(backgroundTasks);
backgroundTasks.clear();
}
try {
await listener.close();
} catch (err) {