Skip to content

Commit 3b1fd86

Browse files
committed
ack comment
1 parent dcc3035 commit 3b1fd86

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

apps/sim/tools/index.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,5 +1116,49 @@ describe('MCP Tool Execution', () => {
11161116
expect(global.fetch).toHaveBeenCalledTimes(2)
11171117
expect(result.success).toBe(true)
11181118
})
1119+
1120+
it('skips retry when Retry-After header exceeds maxDelayMs', async () => {
1121+
global.fetch = Object.assign(
1122+
vi
1123+
.fn()
1124+
.mockResolvedValueOnce(
1125+
makeJsonResponse(429, { error: 'rate limited' }, { 'retry-after': '60' })
1126+
)
1127+
.mockResolvedValueOnce(makeJsonResponse(200, { ok: true })),
1128+
{ preconnect: vi.fn() }
1129+
) as typeof fetch
1130+
1131+
const result = await executeTool('http_request', {
1132+
url: '/api/test',
1133+
method: 'GET',
1134+
retries: 3,
1135+
retryMaxDelayMs: 5000,
1136+
})
1137+
1138+
expect(global.fetch).toHaveBeenCalledTimes(1)
1139+
expect(result.success).toBe(false)
1140+
})
1141+
1142+
it('retries when Retry-After header is within maxDelayMs', async () => {
1143+
global.fetch = Object.assign(
1144+
vi
1145+
.fn()
1146+
.mockResolvedValueOnce(
1147+
makeJsonResponse(429, { error: 'rate limited' }, { 'retry-after': '1' })
1148+
)
1149+
.mockResolvedValueOnce(makeJsonResponse(200, { ok: true })),
1150+
{ preconnect: vi.fn() }
1151+
) as typeof fetch
1152+
1153+
const result = await executeTool('http_request', {
1154+
url: '/api/test',
1155+
method: 'GET',
1156+
retries: 2,
1157+
retryMaxDelayMs: 5000,
1158+
})
1159+
1160+
expect(global.fetch).toHaveBeenCalledTimes(2)
1161+
expect(result.success).toBe(true)
1162+
})
11191163
})
11201164
})

apps/sim/tools/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -831,13 +831,19 @@ async function executeToolRequest(
831831
} catch {
832832
// Ignore errors when consuming body
833833
}
834+
const retryAfterMs = parseRetryAfterHeader(response.headers.get('retry-after'))
835+
if (retryAfterMs > retryConfig.maxDelayMs) {
836+
logger.warn(
837+
`[${requestId}] Retry-After (${retryAfterMs}ms) exceeds maxDelayMs (${retryConfig.maxDelayMs}ms), skipping retry`
838+
)
839+
break
840+
}
834841
const backoffMs = calculateBackoff(
835842
attempt,
836843
retryConfig.initialDelayMs,
837844
retryConfig.maxDelayMs
838845
)
839-
const retryAfterMs = parseRetryAfterHeader(response.headers.get('retry-after'))
840-
const delayMs = Math.min(retryConfig.maxDelayMs, Math.max(backoffMs, retryAfterMs))
846+
const delayMs = Math.max(backoffMs, retryAfterMs)
841847
logger.warn(
842848
`[${requestId}] Retrying ${toolId} after HTTP ${response.status} (attempt ${attempt + 1}/${maxAttempts})`,
843849
{ delayMs }

0 commit comments

Comments
 (0)