dicom-curate 0.26.1 → 0.26.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/applyMappingsWorker.js +25 -1
- package/dist/esm/curateOne.js +25 -1
- package/dist/esm/fetchWithRetry.js +26 -0
- package/dist/esm/index.js +25 -1
- package/dist/types/fetchWithRetry.d.ts +12 -0
- package/dist/umd/dicom-curate.umd.js +70 -2
- package/dist/umd/dicom-curate.umd.js.map +1 -1
- package/dist/umd/dicom-curate.umd.min.js +2 -2
- package/dist/umd/dicom-curate.umd.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -79661,6 +79661,30 @@ function curateDict(inputFilePath, dicomData, mappingOptions) {
|
|
|
79661
79661
|
return { dicomData: mappedDicomData, mapResults: (0, import_lodash4.cloneDeep)(mapResults) };
|
|
79662
79662
|
}
|
|
79663
79663
|
|
|
79664
|
+
// src/fetchWithRetry.ts
|
|
79665
|
+
var MAX_ATTEMPTS = 5;
|
|
79666
|
+
var BASE_DELAY_MS = 1e3;
|
|
79667
|
+
var BACKOFF_MULTIPLIER = 3;
|
|
79668
|
+
async function fetchWithRetry(...args) {
|
|
79669
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
79670
|
+
try {
|
|
79671
|
+
return await fetch(...args);
|
|
79672
|
+
} catch (error2) {
|
|
79673
|
+
const isNetworkError = error2 instanceof TypeError;
|
|
79674
|
+
const isLastAttempt = attempt === MAX_ATTEMPTS;
|
|
79675
|
+
if (!isNetworkError || isLastAttempt) {
|
|
79676
|
+
throw error2;
|
|
79677
|
+
}
|
|
79678
|
+
const delayMs = BASE_DELAY_MS * BACKOFF_MULTIPLIER ** (attempt - 1);
|
|
79679
|
+
console.warn(
|
|
79680
|
+
`fetch attempt ${attempt}/${MAX_ATTEMPTS} failed: ${error2.message}. Retrying in ${delayMs}ms...`
|
|
79681
|
+
);
|
|
79682
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
79683
|
+
}
|
|
79684
|
+
}
|
|
79685
|
+
throw new Error("fetchWithRetry: unreachable");
|
|
79686
|
+
}
|
|
79687
|
+
|
|
79664
79688
|
// src/hash.ts
|
|
79665
79689
|
var import_md5 = __toESM(require_md5(), 1);
|
|
79666
79690
|
var import_js_crc = __toESM(require_crc(), 1);
|
|
@@ -80034,7 +80058,7 @@ async function curateOne({
|
|
|
80034
80058
|
}
|
|
80035
80059
|
if (postMappedHashHeader && postMappedHash)
|
|
80036
80060
|
headers[postMappedHashHeader] = postMappedHash;
|
|
80037
|
-
const resp = await
|
|
80061
|
+
const resp = await fetchWithRetry(uploadUrl, {
|
|
80038
80062
|
method: "PUT",
|
|
80039
80063
|
headers,
|
|
80040
80064
|
body: clonedMapResults.mappedBlob
|
package/dist/esm/curateOne.js
CHANGED
|
@@ -73370,6 +73370,30 @@ function curateDict(inputFilePath, dicomData, mappingOptions) {
|
|
|
73370
73370
|
return { dicomData: mappedDicomData, mapResults: (0, import_lodash4.cloneDeep)(mapResults) };
|
|
73371
73371
|
}
|
|
73372
73372
|
|
|
73373
|
+
// src/fetchWithRetry.ts
|
|
73374
|
+
var MAX_ATTEMPTS = 5;
|
|
73375
|
+
var BASE_DELAY_MS = 1e3;
|
|
73376
|
+
var BACKOFF_MULTIPLIER = 3;
|
|
73377
|
+
async function fetchWithRetry(...args) {
|
|
73378
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
73379
|
+
try {
|
|
73380
|
+
return await fetch(...args);
|
|
73381
|
+
} catch (error2) {
|
|
73382
|
+
const isNetworkError = error2 instanceof TypeError;
|
|
73383
|
+
const isLastAttempt = attempt === MAX_ATTEMPTS;
|
|
73384
|
+
if (!isNetworkError || isLastAttempt) {
|
|
73385
|
+
throw error2;
|
|
73386
|
+
}
|
|
73387
|
+
const delayMs = BASE_DELAY_MS * BACKOFF_MULTIPLIER ** (attempt - 1);
|
|
73388
|
+
console.warn(
|
|
73389
|
+
`fetch attempt ${attempt}/${MAX_ATTEMPTS} failed: ${error2.message}. Retrying in ${delayMs}ms...`
|
|
73390
|
+
);
|
|
73391
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
73392
|
+
}
|
|
73393
|
+
}
|
|
73394
|
+
throw new Error("fetchWithRetry: unreachable");
|
|
73395
|
+
}
|
|
73396
|
+
|
|
73373
73397
|
// src/hash.ts
|
|
73374
73398
|
var import_md5 = __toESM(require_md5(), 1);
|
|
73375
73399
|
var import_js_crc = __toESM(require_crc(), 1);
|
|
@@ -73743,7 +73767,7 @@ async function curateOne({
|
|
|
73743
73767
|
}
|
|
73744
73768
|
if (postMappedHashHeader && postMappedHash)
|
|
73745
73769
|
headers[postMappedHashHeader] = postMappedHash;
|
|
73746
|
-
const resp = await
|
|
73770
|
+
const resp = await fetchWithRetry(uploadUrl, {
|
|
73747
73771
|
method: "PUT",
|
|
73748
73772
|
headers,
|
|
73749
73773
|
body: clonedMapResults.mappedBlob
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/fetchWithRetry.ts
|
|
2
|
+
var MAX_ATTEMPTS = 5;
|
|
3
|
+
var BASE_DELAY_MS = 1e3;
|
|
4
|
+
var BACKOFF_MULTIPLIER = 3;
|
|
5
|
+
async function fetchWithRetry(...args) {
|
|
6
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
7
|
+
try {
|
|
8
|
+
return await fetch(...args);
|
|
9
|
+
} catch (error) {
|
|
10
|
+
const isNetworkError = error instanceof TypeError;
|
|
11
|
+
const isLastAttempt = attempt === MAX_ATTEMPTS;
|
|
12
|
+
if (!isNetworkError || isLastAttempt) {
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
const delayMs = BASE_DELAY_MS * BACKOFF_MULTIPLIER ** (attempt - 1);
|
|
16
|
+
console.warn(
|
|
17
|
+
`fetch attempt ${attempt}/${MAX_ATTEMPTS} failed: ${error.message}. Retrying in ${delayMs}ms...`
|
|
18
|
+
);
|
|
19
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
throw new Error("fetchWithRetry: unreachable");
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
fetchWithRetry
|
|
26
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -81221,6 +81221,30 @@ function curateDict(inputFilePath, dicomData, mappingOptions) {
|
|
|
81221
81221
|
return { dicomData: mappedDicomData, mapResults: (0, import_lodash4.cloneDeep)(mapResults) };
|
|
81222
81222
|
}
|
|
81223
81223
|
|
|
81224
|
+
// src/fetchWithRetry.ts
|
|
81225
|
+
var MAX_ATTEMPTS = 5;
|
|
81226
|
+
var BASE_DELAY_MS = 1e3;
|
|
81227
|
+
var BACKOFF_MULTIPLIER = 3;
|
|
81228
|
+
async function fetchWithRetry(...args) {
|
|
81229
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
81230
|
+
try {
|
|
81231
|
+
return await fetch(...args);
|
|
81232
|
+
} catch (error2) {
|
|
81233
|
+
const isNetworkError = error2 instanceof TypeError;
|
|
81234
|
+
const isLastAttempt = attempt === MAX_ATTEMPTS;
|
|
81235
|
+
if (!isNetworkError || isLastAttempt) {
|
|
81236
|
+
throw error2;
|
|
81237
|
+
}
|
|
81238
|
+
const delayMs = BASE_DELAY_MS * BACKOFF_MULTIPLIER ** (attempt - 1);
|
|
81239
|
+
console.warn(
|
|
81240
|
+
`fetch attempt ${attempt}/${MAX_ATTEMPTS} failed: ${error2.message}. Retrying in ${delayMs}ms...`
|
|
81241
|
+
);
|
|
81242
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
81243
|
+
}
|
|
81244
|
+
}
|
|
81245
|
+
throw new Error("fetchWithRetry: unreachable");
|
|
81246
|
+
}
|
|
81247
|
+
|
|
81224
81248
|
// src/hash.ts
|
|
81225
81249
|
var import_md5 = __toESM(require_md5(), 1);
|
|
81226
81250
|
var import_js_crc = __toESM(require_crc(), 1);
|
|
@@ -81594,7 +81618,7 @@ async function curateOne({
|
|
|
81594
81618
|
}
|
|
81595
81619
|
if (postMappedHashHeader && postMappedHash)
|
|
81596
81620
|
headers[postMappedHashHeader] = postMappedHash;
|
|
81597
|
-
const resp = await
|
|
81621
|
+
const resp = await fetchWithRetry(uploadUrl, {
|
|
81598
81622
|
method: "PUT",
|
|
81599
81623
|
headers,
|
|
81600
81624
|
body: clonedMapResults.mappedBlob
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wraps fetch() with retry logic for transient network errors.
|
|
3
|
+
*
|
|
4
|
+
* Retries only on TypeError (network failure — request never reached the
|
|
5
|
+
* server). Does NOT retry on HTTP error responses (4xx, 5xx) since those
|
|
6
|
+
* indicate the request was received and a retry without changing the request
|
|
7
|
+
* would likely produce the same result.
|
|
8
|
+
*
|
|
9
|
+
* Uses exponential backoff (1s, 3s, 9s, 27s, 81s) which also acts as natural
|
|
10
|
+
* backpressure — workers block during backoff, reducing concurrent uploads.
|
|
11
|
+
*/
|
|
12
|
+
export declare function fetchWithRetry(...args: Parameters<typeof fetch>): Promise<Response>;
|
|
@@ -47934,6 +47934,40 @@
|
|
|
47934
47934
|
return { dicomData: mappedDicomData, mapResults: lodashExports.cloneDeep(mapResults) };
|
|
47935
47935
|
}
|
|
47936
47936
|
|
|
47937
|
+
/**
|
|
47938
|
+
* Wraps fetch() with retry logic for transient network errors.
|
|
47939
|
+
*
|
|
47940
|
+
* Retries only on TypeError (network failure — request never reached the
|
|
47941
|
+
* server). Does NOT retry on HTTP error responses (4xx, 5xx) since those
|
|
47942
|
+
* indicate the request was received and a retry without changing the request
|
|
47943
|
+
* would likely produce the same result.
|
|
47944
|
+
*
|
|
47945
|
+
* Uses exponential backoff (1s, 3s, 9s, 27s, 81s) which also acts as natural
|
|
47946
|
+
* backpressure — workers block during backoff, reducing concurrent uploads.
|
|
47947
|
+
*/
|
|
47948
|
+
const MAX_ATTEMPTS = 5;
|
|
47949
|
+
const BASE_DELAY_MS = 1000;
|
|
47950
|
+
const BACKOFF_MULTIPLIER = 3;
|
|
47951
|
+
async function fetchWithRetry(...args) {
|
|
47952
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
47953
|
+
try {
|
|
47954
|
+
return await fetch(...args);
|
|
47955
|
+
}
|
|
47956
|
+
catch (error) {
|
|
47957
|
+
const isNetworkError = error instanceof TypeError;
|
|
47958
|
+
const isLastAttempt = attempt === MAX_ATTEMPTS;
|
|
47959
|
+
if (!isNetworkError || isLastAttempt) {
|
|
47960
|
+
throw error;
|
|
47961
|
+
}
|
|
47962
|
+
const delayMs = BASE_DELAY_MS * BACKOFF_MULTIPLIER ** (attempt - 1);
|
|
47963
|
+
console.warn(`fetch attempt ${attempt}/${MAX_ATTEMPTS} failed: ${error.message}. Retrying in ${delayMs}ms...`);
|
|
47964
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
47965
|
+
}
|
|
47966
|
+
}
|
|
47967
|
+
// Unreachable — the loop either returns or throws on the last attempt.
|
|
47968
|
+
throw new Error('fetchWithRetry: unreachable');
|
|
47969
|
+
}
|
|
47970
|
+
|
|
47937
47971
|
var md5$1 = {exports: {}};
|
|
47938
47972
|
|
|
47939
47973
|
var crypt = {exports: {}};
|
|
@@ -49116,7 +49150,7 @@
|
|
|
49116
49150
|
}
|
|
49117
49151
|
if (postMappedHashHeader && postMappedHash)
|
|
49118
49152
|
headers[postMappedHashHeader] = postMappedHash;
|
|
49119
|
-
const resp = await
|
|
49153
|
+
const resp = await fetchWithRetry(uploadUrl, {
|
|
49120
49154
|
method: 'PUT',
|
|
49121
49155
|
headers,
|
|
49122
49156
|
body: clonedMapResults.mappedBlob,
|
|
@@ -109949,6 +109983,40 @@
|
|
|
109949
109983
|
return { dicomData: mappedDicomData, mapResults: lodashExports.cloneDeep(mapResults) };
|
|
109950
109984
|
}
|
|
109951
109985
|
|
|
109986
|
+
/**
|
|
109987
|
+
* Wraps fetch() with retry logic for transient network errors.
|
|
109988
|
+
*
|
|
109989
|
+
* Retries only on TypeError (network failure — request never reached the
|
|
109990
|
+
* server). Does NOT retry on HTTP error responses (4xx, 5xx) since those
|
|
109991
|
+
* indicate the request was received and a retry without changing the request
|
|
109992
|
+
* would likely produce the same result.
|
|
109993
|
+
*
|
|
109994
|
+
* Uses exponential backoff (1s, 3s, 9s, 27s, 81s) which also acts as natural
|
|
109995
|
+
* backpressure — workers block during backoff, reducing concurrent uploads.
|
|
109996
|
+
*/
|
|
109997
|
+
const MAX_ATTEMPTS = 5;
|
|
109998
|
+
const BASE_DELAY_MS = 1000;
|
|
109999
|
+
const BACKOFF_MULTIPLIER = 3;
|
|
110000
|
+
async function fetchWithRetry(...args) {
|
|
110001
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
110002
|
+
try {
|
|
110003
|
+
return await fetch(...args);
|
|
110004
|
+
}
|
|
110005
|
+
catch (error) {
|
|
110006
|
+
const isNetworkError = error instanceof TypeError;
|
|
110007
|
+
const isLastAttempt = attempt === MAX_ATTEMPTS;
|
|
110008
|
+
if (!isNetworkError || isLastAttempt) {
|
|
110009
|
+
throw error;
|
|
110010
|
+
}
|
|
110011
|
+
const delayMs = BASE_DELAY_MS * BACKOFF_MULTIPLIER ** (attempt - 1);
|
|
110012
|
+
console.warn(`fetch attempt ${attempt}/${MAX_ATTEMPTS} failed: ${error.message}. Retrying in ${delayMs}ms...`);
|
|
110013
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
110014
|
+
}
|
|
110015
|
+
}
|
|
110016
|
+
// Unreachable — the loop either returns or throws on the last attempt.
|
|
110017
|
+
throw new Error('fetchWithRetry: unreachable');
|
|
110018
|
+
}
|
|
110019
|
+
|
|
109952
110020
|
var md5$1 = {exports: {}};
|
|
109953
110021
|
|
|
109954
110022
|
var crypt = {exports: {}};
|
|
@@ -111133,7 +111201,7 @@
|
|
|
111133
111201
|
}
|
|
111134
111202
|
if (postMappedHashHeader && postMappedHash)
|
|
111135
111203
|
headers[postMappedHashHeader] = postMappedHash;
|
|
111136
|
-
const resp = await
|
|
111204
|
+
const resp = await fetchWithRetry(uploadUrl, {
|
|
111137
111205
|
method: 'PUT',
|
|
111138
111206
|
headers,
|
|
111139
111207
|
body: clonedMapResults.mappedBlob,
|