Skip to content

Commit 1366fc4

Browse files
committed
handle timeouts
1 parent e65a670 commit 1366fc4

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

apps/sim/tools/index.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,5 +1160,29 @@ describe('MCP Tool Execution', () => {
11601160
expect(global.fetch).toHaveBeenCalledTimes(2)
11611161
expect(result.success).toBe(true)
11621162
})
1163+
1164+
it('retries on ETIMEDOUT errors for http_request', async () => {
1165+
const etimedoutError = Object.assign(new Error('connect ETIMEDOUT 10.0.0.1:443'), {
1166+
code: 'ETIMEDOUT',
1167+
})
1168+
global.fetch = Object.assign(
1169+
vi
1170+
.fn()
1171+
.mockRejectedValueOnce(etimedoutError)
1172+
.mockResolvedValueOnce(makeJsonResponse(200, { ok: true })),
1173+
{ preconnect: vi.fn() }
1174+
) as typeof fetch
1175+
1176+
const result = await executeTool('http_request', {
1177+
url: '/api/test',
1178+
method: 'GET',
1179+
retries: 1,
1180+
retryDelayMs: 0,
1181+
retryMaxDelayMs: 0,
1182+
})
1183+
1184+
expect(global.fetch).toHaveBeenCalledTimes(2)
1185+
expect(result.success).toBe(true)
1186+
})
11631187
})
11641188
})

apps/sim/tools/index.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -641,9 +641,13 @@ function getRetryConfig(
641641
function isRetryableFailure(error: unknown, status?: number): boolean {
642642
if (status === 429 || (status && status >= 500 && status <= 599)) return true
643643
if (error instanceof Error) {
644+
const code = (error as NodeJS.ErrnoException).code
645+
if (code === 'ETIMEDOUT' || code === 'ECONNRESET' || code === 'ECONNABORTED') {
646+
return true
647+
}
644648
const msg = error.message.toLowerCase()
645649
if (isBodySizeLimitError(msg)) return false
646-
return msg.includes('timeout') || msg.includes('timed out') || msg.includes('econnreset')
650+
return msg.includes('timeout') || msg.includes('timed out')
647651
}
648652
return false
649653
}
@@ -655,8 +659,17 @@ function calculateBackoff(attempt: number, initialDelayMs: number, maxDelayMs: n
655659

656660
function parseRetryAfterHeader(header: string | null): number {
657661
if (!header) return 0
658-
const seconds = Number.parseInt(header, 10)
659-
return Number.isFinite(seconds) && seconds > 0 ? seconds * 1000 : 0
662+
const trimmed = header.trim()
663+
if (/^\d+$/.test(trimmed)) {
664+
const seconds = Number.parseInt(trimmed, 10)
665+
return seconds > 0 ? seconds * 1000 : 0
666+
}
667+
const date = new Date(trimmed)
668+
if (!Number.isNaN(date.getTime())) {
669+
const deltaMs = date.getTime() - Date.now()
670+
return deltaMs > 0 ? deltaMs : 0
671+
}
672+
return 0
660673
}
661674

662675
/**

0 commit comments

Comments
 (0)