mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
fix(telegram): add UND_ERR_CONNECT_TIMEOUT to PRE_CONNECT_ERROR_CODES (#101258)
* fix(telegram): add UND_ERR_CONNECT_TIMEOUT to PRE_CONNECT_ERROR_CODES UND_ERR_CONNECT_TIMEOUT occurs during TCP/TLS connect handshake, before any HTTP request data is sent. Adding it to the pre-connect set allows isSafeToRetrySendError to safely retry sendMessage when undici's connect timeout fires — the message was never transmitted. * test(telegram): cover connect-timeout retry funnels --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -218,9 +218,10 @@ function createHtmlParseError(operation = "sendMessage") {
|
||||
);
|
||||
}
|
||||
|
||||
function createWrappedPreConnectHttpError(operation = "sendMessage") {
|
||||
const root = Object.assign(new Error("getaddrinfo ENOTFOUND api.telegram.org"), {
|
||||
code: "ENOTFOUND",
|
||||
function createWrappedConnectTimeoutHttpError(operation = "sendMessage") {
|
||||
const root = Object.assign(new Error("Connect Timeout Error"), {
|
||||
name: "ConnectTimeoutError",
|
||||
code: "UND_ERR_CONNECT_TIMEOUT",
|
||||
});
|
||||
const fetchError = Object.assign(new TypeError("fetch failed"), { cause: root });
|
||||
return Object.assign(new Error(`Network request for '${operation}' failed!`), {
|
||||
@@ -1027,12 +1028,12 @@ describe("deliverReplies", () => {
|
||||
expect(runtime.error).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("retries final text sends for wrapped pre-connect grammY HttpError envelopes", async () => {
|
||||
it("retries final text sends for wrapped Undici connect timeouts", async () => {
|
||||
vi.useFakeTimers();
|
||||
const runtime = createRuntime();
|
||||
const sendMessage = vi
|
||||
.fn()
|
||||
.mockRejectedValueOnce(createWrappedPreConnectHttpError("sendMessage"))
|
||||
.mockRejectedValueOnce(createWrappedConnectTimeoutHttpError("sendMessage"))
|
||||
.mockResolvedValueOnce({
|
||||
message_id: 12,
|
||||
chat: { id: "123" },
|
||||
|
||||
@@ -239,7 +239,7 @@ describe("isSafeToRetrySendError", () => {
|
||||
["ECONNRESET", "read ECONNRESET", false],
|
||||
["ETIMEDOUT", "connect ETIMEDOUT", false],
|
||||
["EPIPE", "write EPIPE", false],
|
||||
["UND_ERR_CONNECT_TIMEOUT", "connect timeout", false],
|
||||
["UND_ERR_CONNECT_TIMEOUT", "connect timeout", true],
|
||||
])("returns %s => %s", (code, message, expected) => {
|
||||
expect(isSafeToRetrySendError(errorWithCode(message, code))).toBe(expected);
|
||||
});
|
||||
|
||||
@@ -47,6 +47,7 @@ const PRE_CONNECT_ERROR_CODES = new Set([
|
||||
"ENETDOWN", // Local network interface is down before connect completes (never sent)
|
||||
"ENETUNREACH", // No route to host (never sent)
|
||||
"EHOSTUNREACH", // Host unreachable (never sent)
|
||||
"UND_ERR_CONNECT_TIMEOUT", // TCP/TLS connect timeout (request never sent)
|
||||
]);
|
||||
|
||||
const RECOVERABLE_ERROR_NAMES = new Set([
|
||||
|
||||
@@ -2401,11 +2401,12 @@ describe("sendMessageTelegram", () => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("retries wrapped pre-connect HttpError sends", async () => {
|
||||
it("retries wrapped Undici connect timeout sends", async () => {
|
||||
vi.useFakeTimers();
|
||||
const chatId = "123";
|
||||
const root = Object.assign(new Error("connect ECONNREFUSED api.telegram.org"), {
|
||||
code: "ECONNREFUSED",
|
||||
const root = Object.assign(new Error("Connect Timeout Error"), {
|
||||
name: "ConnectTimeoutError",
|
||||
code: "UND_ERR_CONNECT_TIMEOUT",
|
||||
});
|
||||
const fetchError = Object.assign(new TypeError("fetch failed"), { cause: root });
|
||||
const err = Object.assign(new Error("Network request for 'sendMessage' failed!"), {
|
||||
|
||||
Reference in New Issue
Block a user