This is an automated email from the ASF dual-hosted git repository.
CoverRyan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil-vscode.git
The following commit(s) were added to refs/heads/main by this push:
new ad6dfce2 add fetch retry logic
ad6dfce2 is described below
commit ad6dfce2480671249a37b735baab2a10f9db743e
Author: CoverRyan <[email protected]>
AuthorDate: Tue Jun 23 00:56:07 2026 -0400
add fetch retry logic
---
src/daffodilDebugger/daffodilJars.ts | 10 ++++-----
src/utils.ts | 41 +++++++++++++++++++++++++++++++-----
2 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/src/daffodilDebugger/daffodilJars.ts
b/src/daffodilDebugger/daffodilJars.ts
index dcef2419..e6cee07e 100644
--- a/src/daffodilDebugger/daffodilJars.ts
+++ b/src/daffodilDebugger/daffodilJars.ts
@@ -19,7 +19,7 @@ import * as path from 'path'
import * as fs from 'fs'
import * as vscode from 'vscode'
import { outputChannel } from '../adapter/activateDaffodilDebug'
-import { downloadAndExtract } from '../utils'
+import { downloadAndExtract, fetchRetry } from '../utils'
import { parseStringPromise } from 'xml2js'
/**
@@ -69,11 +69,9 @@ export async function checkIfDaffodilJarsNeeded(
async function getValidDaffodilVersions(): Promise<string[]> {
const url = 'https://daffodil.apache.org/doap.rdf'
- const resp = await fetch(url)
- if (!resp.ok) {
- throw new Error(
- `Failed to fetch DOAP RDF: ${resp.status} ${resp.statusText}`
- )
+ const resp = await fetchRetry(url)
+ if (!resp) {
+ throw new Error(`Failed to fetch DOAP RDF ${url}`)
}
const xmlText = await resp.text()
diff --git a/src/utils.ts b/src/utils.ts
index 1626a7b0..ca66f66d 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -508,6 +508,39 @@ export const displayModalError = async (
vscode.window.showErrorMessage(message, { modal: false })
)
+/**
+ * Make HTTP request with retries and exponential backoff
+ *
+ * @param url The url to fetch
+ * @param options The options for the fetch
+ * @param retries Max number of retries
+ * @param delay Initial delay in ms
+ * @returns Response object
+ */
+export async function fetchRetry(
+ url,
+ options = {},
+ retries = 5,
+ delay = 4000
+): Promise<Response | undefined> {
+ let backoff = delay
+ for (let i = 1; i <= retries; i++) {
+ const res = await fetch(url, options)
+ if (!res.ok || !res.body) {
+ if (i === retries) {
+ throw new Error(
+ `Failed request to ${url}: ${res.status} ${res.statusText}`
+ )
+ } else {
+ await new Promise((r) => setTimeout(r, backoff))
+ backoff = backoff * 2
+ }
+ } else {
+ return res
+ }
+ }
+}
+
/**
* Download and extract a files with a progress bar
*
@@ -529,11 +562,9 @@ export async function downloadAndExtract(
async (progress) => {
progress.report({ increment: 0, message: 'Starting download...' })
- const res = await fetch(url)
- if (!res.ok || !res.body) {
- throw new Error(
- `Failed to download ${url}: ${res.status} ${res.statusText}`
- )
+ const res = await fetchRetry(url)
+ if (!res) {
+ throw new Error(`Failed to download ${url}`)
}
const totalBytes = Number(res.headers.get('content-length')) || 0