Skip to content

Commit 7eb0f51

Browse files
committed
fix(firewall): keep retry budget after a non-retryable miss
1 parent 6601666 commit 7eb0f51

3 files changed

Lines changed: 81 additions & 25 deletions

File tree

‎dist/main.js‎

Lines changed: 13 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/tools/firewall.js‎

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -258,37 +258,39 @@ export async function downloadFirewall({ edition = 'free', ...inputs }) {
258258
*/
259259
export async function downloadToolWithRetry(urls) {
260260
let lastError
261+
const remaining = urls.slice()
262+
let attempt = 0
261263

262-
for (
263-
let attempt = 0;
264-
attempt <= DOWNLOAD_RETRY_DELAYS_SECONDS.length;
265-
attempt += 1
266-
) {
267-
const url = urls[attempt % urls.length]
264+
while (remaining.length > 0) {
265+
const url = remaining[attempt % remaining.length]
268266

269267
try {
270268
return await downloadTool(url)
271269
} catch (error) {
272270
lastError = error
273271

272+
if (!isRetryableDownloadError(error)) {
273+
remaining.splice(remaining.indexOf(url), 1)
274+
if (remaining.length === 0) {
275+
break
276+
}
277+
warning(
278+
`Socket Firewall binary download from ${url} failed: ${errorMessage(error)}. Trying ${remaining[attempt % remaining.length]}.`,
279+
)
280+
continue
281+
}
282+
274283
const seconds = DOWNLOAD_RETRY_DELAYS_SECONDS[attempt]
275284

276285
if (seconds === undefined) {
277286
break
278287
}
279288

280-
if (isRetryableDownloadError(error)) {
281-
warning(
282-
`Socket Firewall binary download from ${url} failed (attempt ${attempt + 1} of ${DOWNLOAD_RETRY_DELAYS_SECONDS.length + 1}): ${errorMessage(error)}. Retrying in ${seconds}s.`,
283-
)
284-
await setTimeout(seconds * 1000)
285-
} else if (attempt < urls.length - 1) {
286-
warning(
287-
`Socket Firewall binary download from ${url} failed: ${errorMessage(error)}. Trying ${urls[(attempt + 1) % urls.length]}.`,
288-
)
289-
} else {
290-
break
291-
}
289+
warning(
290+
`Socket Firewall binary download from ${url} failed (attempt ${attempt + 1} of ${DOWNLOAD_RETRY_DELAYS_SECONDS.length + 1}): ${errorMessage(error)}. Retrying in ${seconds}s.`,
291+
)
292+
await setTimeout(seconds * 1000)
293+
attempt += 1
292294
}
293295
}
294296

‎test/unit/tools/firewall.test.mts‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,54 @@ describe('downloadToolWithRetry', () => {
215215
expect(mockDownloadTool).toHaveBeenCalledTimes(2)
216216
expect(sleepDelays).toEqual([])
217217
})
218+
219+
it('keeps the healthy origin on the delay table after a miss', async () => {
220+
mockDownloadTool
221+
.mockRejectedValueOnce(httpError(504))
222+
.mockRejectedValueOnce(httpError(404))
223+
.mockResolvedValueOnce('/tmp/sfw')
224+
225+
await expect(downloadToolWithRetry([GITHUB, MIRROR])).resolves.toBe(
226+
'/tmp/sfw',
227+
)
228+
expect(mockDownloadTool.mock.calls).toEqual([[GITHUB], [MIRROR], [GITHUB]])
229+
expect(sleepDelays).toEqual([30_000])
230+
})
231+
232+
it('does not spend the delay table on a miss before a flaky origin', async () => {
233+
mockDownloadTool
234+
.mockRejectedValueOnce(httpError(404))
235+
.mockRejectedValue(httpError(504))
236+
237+
await expect(downloadToolWithRetry([MIRROR, GITHUB])).rejects.toThrow(
238+
'Unexpected HTTP response: 504',
239+
)
240+
expect(mockDownloadTool.mock.calls).toEqual([
241+
[MIRROR],
242+
[GITHUB],
243+
[GITHUB],
244+
[GITHUB],
245+
])
246+
expect(sleepDelays).toEqual([30_000, 60_000])
247+
})
248+
249+
it('rethrows the flaky origin after a later miss burns no retries', async () => {
250+
mockDownloadTool
251+
.mockRejectedValueOnce(httpError(504))
252+
.mockRejectedValueOnce(httpError(404))
253+
.mockRejectedValue(httpError(504))
254+
255+
await expect(downloadToolWithRetry([GITHUB, MIRROR])).rejects.toThrow(
256+
'Unexpected HTTP response: 504',
257+
)
258+
expect(mockDownloadTool.mock.calls).toEqual([
259+
[GITHUB],
260+
[MIRROR],
261+
[GITHUB],
262+
[GITHUB],
263+
])
264+
expect(sleepDelays).toEqual([30_000, 60_000])
265+
})
218266
})
219267

220268
describe('firewallDownloadUrls', () => {

0 commit comments

Comments
 (0)