From 8628d05ecd3490ea260b84ff63c565551497fa98 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 13 Apr 2026 17:16:31 +0100 Subject: [PATCH] fix(telegram): retry failed group migration updates --- .../telegram/src/bot-handlers.runtime.ts | 1 + .../src/bot.create-telegram-bot.test.ts | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/extensions/telegram/src/bot-handlers.runtime.ts b/extensions/telegram/src/bot-handlers.runtime.ts index fbae1c1c967..a79bba721e9 100644 --- a/extensions/telegram/src/bot-handlers.runtime.ts +++ b/extensions/telegram/src/bot-handlers.runtime.ts @@ -1686,6 +1686,7 @@ export const registerTelegramHandlers = ({ } } catch (err) { runtime.error?.(danger(`[telegram] Group migration handler failed: ${String(err)}`)); + throw err; } }); diff --git a/extensions/telegram/src/bot.create-telegram-bot.test.ts b/extensions/telegram/src/bot.create-telegram-bot.test.ts index 01fec728459..d36305fdd13 100644 --- a/extensions/telegram/src/bot.create-telegram-bot.test.ts +++ b/extensions/telegram/src/bot.create-telegram-bot.test.ts @@ -2746,4 +2746,62 @@ describe("createTelegramBot", () => { expect(loadConfigCallsAfterFailure).toBe(loadConfigCallsBeforeRetry + 1); expect(loadConfig.mock.calls.length).toBeGreaterThan(loadConfigCallsAfterFailure); }); + + it("retries group migration updates after a bubbled handler failure", async () => { + loadConfig.mockReturnValue({ + channels: { + telegram: { + groups: { + "-1001": { + enabled: true, + }, + }, + }, + }, + }); + + createTelegramBot({ token: "tok" }); + const migrationHandler = getOnHandler("message:migrate_to_chat_id"); + const middlewares = middlewareUseSpy.mock.calls + .map((call) => call[0]) + .filter( + (fn): fn is (ctx: Record, next: () => Promise) => Promise => + typeof fn === "function", + ); + const runMiddlewareChain = async (ctx: Record) => { + let idx = -1; + const dispatch = async (i: number): Promise => { + if (i <= idx) { + throw new Error("middleware dispatch called multiple times"); + } + idx = i; + const fn = middlewares[i]; + if (!fn) { + await migrationHandler(ctx); + return; + } + await fn(ctx, async () => dispatch(i + 1)); + }; + await dispatch(0); + }; + + const ctx = { + update: { update_id: 444 }, + message: { + chat: { id: -1001, type: "supergroup", title: "Old Group" }, + migrate_to_chat_id: -1002, + }, + }; + + const loadConfigCallsBeforeRetry = loadConfig.mock.calls.length; + loadConfig.mockImplementationOnce(() => { + throw new Error("cfg boom"); + }); + await expect(runMiddlewareChain(ctx)).rejects.toThrow("cfg boom"); + const loadConfigCallsAfterFailure = loadConfig.mock.calls.length; + await runMiddlewareChain(ctx); + + expect(loadConfigCallsAfterFailure).toBe(loadConfigCallsBeforeRetry + 1); + expect(loadConfig.mock.calls.length).toBeGreaterThan(loadConfigCallsAfterFailure); + }); });