From 387b5337eccc899b7cf7c9c670cb31dc093c33ef Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 22 Jun 2026 17:45:59 +0800 Subject: [PATCH] fix(synology-chat): remove duplicate local deliver timeout (#95707) Merged via squash. Prepared head SHA: a9860099c9dba6699e3792a50233492f785800c8 Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com> Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com> Reviewed-by: @vincentkoc --- .../synology-chat/src/webhook-handler.test.ts | 31 +++++++++++++++++++ .../synology-chat/src/webhook-handler.ts | 6 +--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/extensions/synology-chat/src/webhook-handler.test.ts b/extensions/synology-chat/src/webhook-handler.test.ts index 97138e8326ee..93f9092595cd 100644 --- a/extensions/synology-chat/src/webhook-handler.test.ts +++ b/extensions/synology-chat/src/webhook-handler.test.ts @@ -619,6 +619,37 @@ describe("createWebhookHandler", () => { expectBotReplySentTo("123"); }); + it("awaits deliver directly with no local hardcoded timeout wrapper", async () => { + // Previously this webhook handler wrapped deliver with a hardcoded 120s + // Promise.race that overrode the configurable agents.defaults.timeoutSeconds + // from core. That wrapper created a setTimeout(_, 120000) on every deliver + // call. We spy on setTimeout to prove no such call exists in the current code. + const setTimeoutSpy = vi.spyOn(global, "setTimeout"); + try { + const deliver = vi.fn().mockResolvedValue("late reply"); + const handler = createWebhookHandler({ + account: makeAccount({ accountId: "no-hardcoded-timeout-" + Date.now() }), + deliver, + log, + }); + + const res = makeRes(); + const req = makeReq("POST", validBody); + await handler(req, res); + + expect(res.status).toBe(204); + + // Collect all setTimeout delays used during this handler run + const delays = setTimeoutSpy.mock.calls.map((call) => call[1]); + // Every delay should be well under 120s — the old hardcoded wrapper would + // have produced exactly one call with delay === 120000. + const longDelays = delays.filter((d) => typeof d === "number" && d >= 120_000); + expect(longDelays).toEqual([]); + } finally { + setTimeoutSpy.mockRestore(); + } + }); + it("sanitizes input before delivery", async () => { const deliver = vi.fn().mockResolvedValue(null); const handler = createWebhookHandler({ diff --git a/extensions/synology-chat/src/webhook-handler.ts b/extensions/synology-chat/src/webhook-handler.ts index c445d3bee4ea..3c2565e8f8ae 100644 --- a/extensions/synology-chat/src/webhook-handler.ts +++ b/extensions/synology-chat/src/webhook-handler.ts @@ -554,7 +554,7 @@ async function processAuthorizedSynologyWebhook(params: { log: params.log, }); - const deliverPromise = params.deliver({ + const reply = await params.deliver({ body: params.message.body, from: authorizedWebhookUserId, senderName: params.message.payload.username, @@ -564,10 +564,6 @@ async function processAuthorizedSynologyWebhook(params: { commandAuthorized: params.message.commandAuthorized, chatUserId: deliveryUserId, }); - const timeoutPromise = new Promise((_, reject) => { - setTimeout(() => reject(new Error("Agent response timeout (120s)")), 120_000); - }); - const reply = await Promise.race([deliverPromise, timeoutPromise]); if (!reply) { return; }