From f4c69a6cfc281fb4ee64546d27aff0e12a692fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E8=89=BA=E9=9F=AC=28yangyitao=29?= Date: Sun, 15 Mar 2026 02:50:46 +0000 Subject: [PATCH] fix(telegram): increase dedup TTL and log offset confirmation failures The Telegram update dedup cache had a 5-minute TTL which could expire during extended polling restart cycles (backoff, stall detection, etc.), allowing already-processed messages to be re-delivered. - Increase dedup cache TTL from 5 to 30 minutes to survive all realistic restart windows - Increase max cache size from 2000 to 5000 to match the longer TTL - Log a warning when confirmPersistedOffset fails so operators can diagnose duplicate-message issues Closes #46674 --- extensions/telegram/src/bot-updates.ts | 7 +++++-- extensions/telegram/src/polling-session.ts | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/extensions/telegram/src/bot-updates.ts b/extensions/telegram/src/bot-updates.ts index 4b08c747f8f..15cb32f5f94 100644 --- a/extensions/telegram/src/bot-updates.ts +++ b/extensions/telegram/src/bot-updates.ts @@ -3,8 +3,11 @@ import { createDedupeCache } from "openclaw/plugin-sdk/infra-runtime"; import type { TelegramContext } from "./bot/types.js"; const MEDIA_GROUP_TIMEOUT_MS = 500; -const RECENT_TELEGRAM_UPDATE_TTL_MS = 5 * 60_000; -const RECENT_TELEGRAM_UPDATE_MAX = 2000; +// Dedup cache TTL must survive the longest possible polling restart cycle +// (backoff up to 30s × multiple attempts + 90s stall threshold + 15s grace). +// 30 minutes keeps entries alive well past any realistic restart window (#46674). +const RECENT_TELEGRAM_UPDATE_TTL_MS = 30 * 60_000; +const RECENT_TELEGRAM_UPDATE_MAX = 5000; export type MediaGroupEntry = { messages: Array<{ diff --git a/extensions/telegram/src/polling-session.ts b/extensions/telegram/src/polling-session.ts index 59cbec7d589..b272849fca9 100644 --- a/extensions/telegram/src/polling-session.ts +++ b/extensions/telegram/src/polling-session.ts @@ -177,8 +177,12 @@ export class TelegramPollingSession { } try { await bot.api.getUpdates({ offset: lastUpdateId + 1, limit: 1, timeout: 0 }); - } catch { + } catch (err) { // Non-fatal: runner middleware still skips duplicates via shouldSkipUpdate. + // Log a warning so operators can diagnose duplicate-message issues (#46674). + this.opts.log( + `[telegram] failed to confirm persisted offset ${lastUpdateId}: ${formatErrorMessage(err)}; relying on dedup cache.`, + ); } }