mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-12 18:56:02 +00:00
fix(telegram): add missing 'action' retry context for sendChatAction (#100762)
* fix(telegram): add missing 'action' retry context for sendChatAction * fix(telegram): cover all sendChatAction retry paths --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
@@ -140,14 +140,15 @@ describe("isRecoverableTelegramNetworkError", () => {
|
||||
expect(isRecoverableTelegramNetworkError(undiciSnippetErr, { context: "polling" })).toBe(true);
|
||||
});
|
||||
|
||||
it("treats delete/react/edit (idempotent) contexts like polling, not send", () => {
|
||||
it("treats delete/react/edit/action (idempotent) contexts like polling, not send", () => {
|
||||
const undiciSnippetErr = new Error("Undici: socket failure");
|
||||
// delete, react, and edit are idempotent Telegram operations; a transient
|
||||
// snippet-only error must be retried (allowMessageMatch defaults true),
|
||||
// delete, react, edit, and action are idempotent or non-message operations;
|
||||
// a transient snippet-only error must be retried (allowMessageMatch defaults true),
|
||||
// matching polling/webhook. send stays strict as the regression guard.
|
||||
expect(isRecoverableTelegramNetworkError(undiciSnippetErr, { context: "delete" })).toBe(true);
|
||||
expect(isRecoverableTelegramNetworkError(undiciSnippetErr, { context: "react" })).toBe(true);
|
||||
expect(isRecoverableTelegramNetworkError(undiciSnippetErr, { context: "edit" })).toBe(true);
|
||||
expect(isRecoverableTelegramNetworkError(undiciSnippetErr, { context: "action" })).toBe(true);
|
||||
expect(isRecoverableTelegramNetworkError(undiciSnippetErr, { context: "send" })).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
@@ -148,6 +148,7 @@ export type TelegramNetworkErrorContext =
|
||||
| "delete"
|
||||
| "react"
|
||||
| "edit"
|
||||
| "action"
|
||||
| "unknown";
|
||||
export type TelegramNetworkErrorOrigin = {
|
||||
method?: string | null;
|
||||
|
||||
@@ -638,6 +638,28 @@ describe("sendMessageTelegram", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("retries snippet-only network errors when sending typing", async () => {
|
||||
loadConfig.mockReturnValue({
|
||||
channels: {
|
||||
telegram: {
|
||||
botToken: "tok",
|
||||
},
|
||||
},
|
||||
});
|
||||
botApi.sendChatAction
|
||||
.mockRejectedValueOnce(new Error("socket hang up"))
|
||||
.mockResolvedValue(true);
|
||||
|
||||
await sendTypingTelegram("telegram:group:-1001234567890", {
|
||||
cfg: TELEGRAM_TEST_CFG,
|
||||
token: "tok",
|
||||
accountId: "default",
|
||||
retry: { attempts: 2, minDelayMs: 0, maxDelayMs: 0, jitter: 0 },
|
||||
});
|
||||
|
||||
expect(botApi.sendChatAction).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("pins and unpins Telegram messages", async () => {
|
||||
loadConfig.mockReturnValue({
|
||||
channels: {
|
||||
|
||||
@@ -1438,7 +1438,7 @@ export async function sendTypingTelegram(
|
||||
account,
|
||||
retry: opts.retry,
|
||||
verbose: opts.verbose,
|
||||
shouldRetry: (err) => isRecoverableTelegramNetworkError(err, { context: "send" }),
|
||||
shouldRetry: (err) => isRecoverableTelegramNetworkError(err, { context: "action" }),
|
||||
});
|
||||
const threadParams = buildTypingThreadParams(target.messageThreadId ?? opts.messageThreadId);
|
||||
await requestWithDiag(
|
||||
|
||||
@@ -178,6 +178,7 @@ describe("createTelegramSendChatActionHandler", () => {
|
||||
|
||||
it.each([
|
||||
["recoverable network", () => makeNetworkError(), 1000],
|
||||
["snippet-only network", () => new Error("socket hang up"), 1000],
|
||||
["Telegram 429", () => makeTelegramError("Too Many Requests", 429, { retry_after: 2 }), 2000],
|
||||
["Telegram 5xx", () => makeTelegramError("Bad Gateway", 502), 1000],
|
||||
])("cools down transient %s errors", async (_name, makeError, expectedCooldownMs) => {
|
||||
|
||||
@@ -100,7 +100,7 @@ function isTransientSendChatActionError(error: unknown): boolean {
|
||||
return (
|
||||
isTelegramRateLimitError(error) ||
|
||||
isTelegramServerError(error) ||
|
||||
isRecoverableTelegramNetworkError(error, { context: "send" })
|
||||
isRecoverableTelegramNetworkError(error, { context: "action" })
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user