diff --git a/extensions/synology-chat/src/webhook-handler.ts b/extensions/synology-chat/src/webhook-handler.ts index b4c73934db9..b4dd96876a3 100644 --- a/extensions/synology-chat/src/webhook-handler.ts +++ b/extensions/synology-chat/src/webhook-handler.ts @@ -369,17 +369,22 @@ export function createWebhookHandler(deps: WebhookHandlerDeps) { chatUserId: replyUserId, }); - const timeoutPromise = new Promise((_, reject) => - setTimeout(() => reject(new Error("Agent response timeout (120s)")), 120_000), - ); + let timer: ReturnType | undefined; + const timeoutPromise = new Promise((_, reject) => { + timer = setTimeout(() => reject(new Error("Agent response timeout (120s)")), 120_000); + }); - const reply = await Promise.race([deliverPromise, timeoutPromise]); + try { + const reply = await Promise.race([deliverPromise, timeoutPromise]); - // Send reply back to Synology Chat using the resolved Chat user_id - if (reply) { - await sendMessage(account.incomingUrl, reply, replyUserId, account.allowInsecureSsl); - const replyPreview = reply.length > 100 ? `${reply.slice(0, 100)}...` : reply; - log?.info(`Reply sent to ${payload.username} (${replyUserId}): ${replyPreview}`); + // Send reply back to Synology Chat using the resolved Chat user_id + if (reply) { + await sendMessage(account.incomingUrl, reply, replyUserId, account.allowInsecureSsl); + const replyPreview = reply.length > 100 ? `${reply.slice(0, 100)}...` : reply; + log?.info(`Reply sent to ${payload.username} (${replyUserId}): ${replyPreview}`); + } + } finally { + clearTimeout(timer); } } catch (err) { const errMsg = err instanceof Error ? `${err.message}\n${err.stack}` : String(err); diff --git a/extensions/twitch/src/probe.ts b/extensions/twitch/src/probe.ts index 7ce02501007..9d0c93c0f62 100644 --- a/extensions/twitch/src/probe.ts +++ b/extensions/twitch/src/probe.ts @@ -82,12 +82,17 @@ export async function probeTwitch( }); }); + let timer: ReturnType | undefined; const timeout = new Promise((_, reject) => { - setTimeout(() => reject(new Error(`timeout after ${timeoutMs}ms`)), timeoutMs); + timer = setTimeout(() => reject(new Error(`timeout after ${timeoutMs}ms`)), timeoutMs); }); client.connect(); - await Promise.race([connectionPromise, timeout]); + try { + await Promise.race([connectionPromise, timeout]); + } finally { + clearTimeout(timer); + } client.quit(); client = undefined; diff --git a/extensions/zalouser/src/probe.ts b/extensions/zalouser/src/probe.ts index b3213010f26..0db956684fe 100644 --- a/extensions/zalouser/src/probe.ts +++ b/extensions/zalouser/src/probe.ts @@ -11,14 +11,22 @@ export async function probeZalouser( timeoutMs?: number, ): Promise { try { - const user = timeoutMs - ? await Promise.race([ + let user: ZcaUserInfo | null; + if (timeoutMs) { + let timer: ReturnType | undefined; + try { + user = await Promise.race([ getZaloUserInfo(profile), - new Promise((resolve) => - setTimeout(() => resolve(null), Math.max(timeoutMs, 1000)), - ), - ]) - : await getZaloUserInfo(profile); + new Promise((resolve) => { + timer = setTimeout(() => resolve(null), Math.max(timeoutMs, 1000)); + }), + ]); + } finally { + clearTimeout(timer); + } + } else { + user = await getZaloUserInfo(profile); + } if (!user) { return { ok: false, error: "Not authenticated" };