mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-29 01:52:04 +00:00
fix(telegram): land #34238 from @hal-crackbot
Landed from contributor PR #34238 by @hal-crackbot. Co-authored-by: Hal Crackbot <hal@crackbot.dev>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isRecoverableTelegramNetworkError } from "./network-errors.js";
|
||||
import { isRecoverableTelegramNetworkError, isSafeToRetrySendError } from "./network-errors.js";
|
||||
|
||||
describe("isRecoverableTelegramNetworkError", () => {
|
||||
it("detects recoverable error codes", () => {
|
||||
@@ -106,3 +106,61 @@ describe("isRecoverableTelegramNetworkError", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("isSafeToRetrySendError", () => {
|
||||
it("allows retry for ECONNREFUSED (pre-connect, message not sent)", () => {
|
||||
const err = Object.assign(new Error("connect ECONNREFUSED"), { code: "ECONNREFUSED" });
|
||||
expect(isSafeToRetrySendError(err)).toBe(true);
|
||||
});
|
||||
|
||||
it("allows retry for ENOTFOUND (DNS failure, message not sent)", () => {
|
||||
const err = Object.assign(new Error("getaddrinfo ENOTFOUND"), { code: "ENOTFOUND" });
|
||||
expect(isSafeToRetrySendError(err)).toBe(true);
|
||||
});
|
||||
|
||||
it("allows retry for EAI_AGAIN (transient DNS, message not sent)", () => {
|
||||
const err = Object.assign(new Error("getaddrinfo EAI_AGAIN"), { code: "EAI_AGAIN" });
|
||||
expect(isSafeToRetrySendError(err)).toBe(true);
|
||||
});
|
||||
|
||||
it("allows retry for ENETUNREACH (no route to host, message not sent)", () => {
|
||||
const err = Object.assign(new Error("connect ENETUNREACH"), { code: "ENETUNREACH" });
|
||||
expect(isSafeToRetrySendError(err)).toBe(true);
|
||||
});
|
||||
|
||||
it("allows retry for EHOSTUNREACH (host unreachable, message not sent)", () => {
|
||||
const err = Object.assign(new Error("connect EHOSTUNREACH"), { code: "EHOSTUNREACH" });
|
||||
expect(isSafeToRetrySendError(err)).toBe(true);
|
||||
});
|
||||
|
||||
it("does NOT allow retry for ECONNRESET (message may already be delivered)", () => {
|
||||
const err = Object.assign(new Error("read ECONNRESET"), { code: "ECONNRESET" });
|
||||
expect(isSafeToRetrySendError(err)).toBe(false);
|
||||
});
|
||||
|
||||
it("does NOT allow retry for ETIMEDOUT (message may already be delivered)", () => {
|
||||
const err = Object.assign(new Error("connect ETIMEDOUT"), { code: "ETIMEDOUT" });
|
||||
expect(isSafeToRetrySendError(err)).toBe(false);
|
||||
});
|
||||
|
||||
it("does NOT allow retry for EPIPE (connection broken mid-transfer, message may be delivered)", () => {
|
||||
const err = Object.assign(new Error("write EPIPE"), { code: "EPIPE" });
|
||||
expect(isSafeToRetrySendError(err)).toBe(false);
|
||||
});
|
||||
|
||||
it("does NOT allow retry for UND_ERR_CONNECT_TIMEOUT (ambiguous timing)", () => {
|
||||
const err = Object.assign(new Error("connect timeout"), { code: "UND_ERR_CONNECT_TIMEOUT" });
|
||||
expect(isSafeToRetrySendError(err)).toBe(false);
|
||||
});
|
||||
|
||||
it("does NOT allow retry for non-network errors", () => {
|
||||
expect(isSafeToRetrySendError(new Error("400: Bad Request"))).toBe(false);
|
||||
expect(isSafeToRetrySendError(null)).toBe(false);
|
||||
});
|
||||
|
||||
it("detects pre-connect error nested in cause chain", () => {
|
||||
const root = Object.assign(new Error("ECONNREFUSED"), { code: "ECONNREFUSED" });
|
||||
const wrapped = Object.assign(new Error("fetch failed"), { cause: root });
|
||||
expect(isSafeToRetrySendError(wrapped)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user