From 1c9560044fe00ad97b6515c8dfdf7348864a2054 Mon Sep 17 00:00:00 2001 From: igoroctaviano Date: Wed, 5 May 2021 15:46:02 -0300 Subject: [PATCH 01/11] Implement handlers to retry metadata requests --- platform/core/package.json | 1 + .../wado/retrieveMetadataLoaderAsync.js | 37 +++++++++++++++++++ yarn.lock | 28 +++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/platform/core/package.json b/platform/core/package.json index ced3f230f5e..605c82ab4f3 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -46,6 +46,7 @@ "lodash.clonedeep": "^4.5.0", "lodash.merge": "^4.6.1", "mousetrap": "^1.6.3", + "retry": "^0.12.0", "validate.js": "^0.12.0" } } diff --git a/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js b/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js index 81585772b67..a008c5154ca 100644 --- a/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js +++ b/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js @@ -1,5 +1,6 @@ import { api } from 'dicomweb-client'; import dcmjs from 'dcmjs'; +import retry, { operation } from 'retry'; import DICOMWeb from '../../../DICOMWeb/'; import RetrieveMetadataLoader from './retrieveMetadataLoader'; import { sortStudySeries, sortingCriteria } from '../../sortStudy'; @@ -76,6 +77,42 @@ export default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader url: server.qidoRoot, headers: DICOMWeb.getAuthorizationHeader(server), errorInterceptor: errorHandler.getHTTPErrorHandler(), + enhancers: [ + (request, metadata) => { + function faultTolerantRequestSend(...args) { + const operation = retry.operation({ + retries: 10, + }); + /** + * retries: 5, + * factor: 3, + * minTimeout: 1 * 1000, + * maxTimeout: 60 * 1000, + * randomize: true + */ + + operation.attempt(function(currentAttempt) { + const originalOnReadyStateChange = request.onreadystatechange; + + request.onreadystatechange = function() { + originalOnReadyStateChange.call(request); + if (request.status === 429 || request.status >= 500) { + operation.retry(new Error('Attempt failed!')); + } + }; + + console.debug(`${metadata.url} (attempt: ${currentAttempt})`); + request.open(metadata.method, metadata.url, true); + originalRequestSend.call(request, ...args); + }); + } + + const originalRequestSend = request.send; + request.send = faultTolerantRequestSend; + + return request; + }, + ], }); this.client = client; diff --git a/yarn.lock b/yarn.lock index 7d49192bb5a..db9b980d319 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1247,13 +1247,34 @@ pirates "^4.0.0" source-map-support "^0.5.9" -"@babel/runtime@7.1.2", "@babel/runtime@7.5.5", "@babel/runtime@7.6.0", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6": +"@babel/runtime@7.1.2": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.1.2.tgz#81c89935f4647706fc54541145e6b4ecfef4b8e3" + integrity sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg== + dependencies: + regenerator-runtime "^0.12.0" + +"@babel/runtime@7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.0.tgz#4fc1d642a9fd0299754e8b5de62c631cf5568205" + integrity sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ== + dependencies: + regenerator-runtime "^0.13.2" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== dependencies: regenerator-runtime "^0.13.2" +"@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" + integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" @@ -16523,6 +16544,11 @@ regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== +regenerator-runtime@^0.12.0: + version "0.12.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" + integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== + regenerator-runtime@^0.13.1, regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" From 863fe0590761b45fba8f8a22bdd2bbb9e33cf943 Mon Sep 17 00:00:00 2001 From: igoroctaviano Date: Wed, 5 May 2021 16:07:23 -0300 Subject: [PATCH 02/11] Update naming --- .../src/studies/services/wado/retrieveMetadataLoaderAsync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js b/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js index a008c5154ca..1f10b660d6e 100644 --- a/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js +++ b/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js @@ -77,7 +77,7 @@ export default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader url: server.qidoRoot, headers: DICOMWeb.getAuthorizationHeader(server), errorInterceptor: errorHandler.getHTTPErrorHandler(), - enhancers: [ + requestInterceptors: [ (request, metadata) => { function faultTolerantRequestSend(...args) { const operation = retry.operation({ From 35aaad175c96caba65e3d4e63858d149cae62652 Mon Sep 17 00:00:00 2001 From: igoroctaviano Date: Wed, 12 May 2021 19:00:19 -0300 Subject: [PATCH 03/11] Update naming --- .../src/studies/services/wado/retrieveMetadataLoaderAsync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js b/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js index 1f10b660d6e..b1bb79cfe36 100644 --- a/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js +++ b/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js @@ -77,7 +77,7 @@ export default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader url: server.qidoRoot, headers: DICOMWeb.getAuthorizationHeader(server), errorInterceptor: errorHandler.getHTTPErrorHandler(), - requestInterceptors: [ + requestHooks: [ (request, metadata) => { function faultTolerantRequestSend(...args) { const operation = retry.operation({ From 2ea227ca0664ca47d1d6c654fce1725a4266b5cd Mon Sep 17 00:00:00 2001 From: igoroctaviano Date: Thu, 13 May 2021 09:06:11 -0300 Subject: [PATCH 04/11] Extract hook and add config and documentation --- .webpack/webpack.base.js | 6 ++ .../src/DICOMSR/handleStructuredReport.js | 3 + .../src/classes/metadata/StudyMetadata.js | 2 + .../core/src/studies/services/qido/studies.js | 2 + .../wado/retrieveMetadataLoaderAsync.js | 39 +------- .../wado/retrieveMetadataLoaderSync.js | 2 + platform/core/src/utils/dicomLoaderService.js | 2 + platform/core/src/utils/index.js | 3 + platform/core/src/utils/index.test.js | 1 + .../metadataProvider/fetchOverlayData.js | 2 + .../fetchPaletteColorLookupTableData.js | 2 + .../core/src/utils/xhrRetryRequestHook.js | 91 +++++++++++++++++++ yarn.lock | 28 +----- 13 files changed, 119 insertions(+), 64 deletions(-) create mode 100644 platform/core/src/utils/xhrRetryRequestHook.js diff --git a/.webpack/webpack.base.js b/.webpack/webpack.base.js index ea5c83aa499..59fe02ddf06 100644 --- a/.webpack/webpack.base.js +++ b/.webpack/webpack.base.js @@ -85,6 +85,12 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => { 'process.env.USE_LOCIZE': JSON.stringify(process.env.USE_LOCIZE || ''), 'process.env.LOCIZE_PROJECTID': JSON.stringify(process.env.LOCIZE_PROJECTID || ''), 'process.env.LOCIZE_API_KEY': JSON.stringify(process.env.LOCIZE_API_KEY || ''), + /** DICOMWebClient Retry options */ + 'process.env.DICOMWEB_CLIENT_RETRY_RETRIES': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_RETRIES || 5), + 'process.env.DICOMWEB_CLIENT_RETRY_FACTOR': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_FACTOR || 3), + 'process.env.DICOMWEB_CLIENT_RETRY_MIN_TIMEOUT': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_MIN_TIMEOUT || 1 * 1000), + 'process.env.DICOMWEB_CLIENT_RETRY_MAX_TIMEOUT': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_MAX_TIMEOUT || 60 * 1000), + 'process.env.DICOMWEB_CLIENT_RETRY_RANDOMIZE': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_RANDOMIZE || true), }), ], // Fix: https://github.com/webpack-contrib/css-loader/issues/447#issuecomment-285598881 diff --git a/platform/core/src/DICOMSR/handleStructuredReport.js b/platform/core/src/DICOMSR/handleStructuredReport.js index fcaa19890b4..5bb8180387e 100644 --- a/platform/core/src/DICOMSR/handleStructuredReport.js +++ b/platform/core/src/DICOMSR/handleStructuredReport.js @@ -6,6 +6,7 @@ import parseDicomStructuredReport from './parseDicomStructuredReport'; import parseMeasurementsData from './parseMeasurementsData'; import getAllDisplaySets from './utils/getAllDisplaySets'; import errorHandler from '../errorHandler'; +import getXHRRetryRequestHook from '../utils/xhrRetryRequestHook'; const VERSION_NAME = 'dcmjs-0.0'; const TRANSFER_SYNTAX_UID = '1.2.840.10008.1.2.1'; @@ -23,6 +24,7 @@ const retrieveMeasurementFromSR = async (series, studies, serverUrl) => { url: serverUrl, headers: DICOMWeb.getAuthorizationHeader(), errorInterceptor: errorHandler.getHTTPErrorHandler(), + requestHooks: [getXHRRetryRequestHook()], }; const dicomWeb = new api.DICOMwebClient(config); @@ -74,6 +76,7 @@ const stowSRFromMeasurements = async (measurements, serverUrl) => { url: serverUrl, headers: DICOMWeb.getAuthorizationHeader(), errorInterceptor: errorHandler.getHTTPErrorHandler(), + requestHooks: [getXHRRetryRequestHook()], }; const dicomWeb = new api.DICOMwebClient(config); diff --git a/platform/core/src/classes/metadata/StudyMetadata.js b/platform/core/src/classes/metadata/StudyMetadata.js index 2e6531f9ad1..582c84e24fe 100644 --- a/platform/core/src/classes/metadata/StudyMetadata.js +++ b/platform/core/src/classes/metadata/StudyMetadata.js @@ -12,6 +12,7 @@ import { isImage } from '../../utils/isImage'; import { isDisplaySetReconstructable, isSpacingUniform } from '../../utils/isDisplaySetReconstructable'; import errorHandler from '../../errorHandler'; import isLowPriorityModality from '../../utils/isLowPriorityModality'; +import getXHRRetryRequestHook from '../../utils/xhrRetryRequestHook'; class StudyMetadata extends Metadata { constructor(data, uid) { @@ -889,6 +890,7 @@ function _getDisplaySetFromSopClassModule( url: study.getData().wadoRoot, headers, errorInterceptor, + requestHooks: [getXHRRetryRequestHook()], }); let displaySet = plugin.getDisplaySetFromSeries( diff --git a/platform/core/src/studies/services/qido/studies.js b/platform/core/src/studies/services/qido/studies.js index 93cb292d4d2..7a66c88f4c8 100644 --- a/platform/core/src/studies/services/qido/studies.js +++ b/platform/core/src/studies/services/qido/studies.js @@ -2,6 +2,7 @@ import { api } from 'dicomweb-client'; import DICOMWeb from '../../../DICOMWeb/'; import errorHandler from '../../../errorHandler'; +import getXHRRetryRequestHook from '../../../utils/xhrRetryRequestHook'; /** * Creates a QIDO date string for a date range query @@ -118,6 +119,7 @@ export default function Studies(server, filter) { url: server.qidoRoot, headers: DICOMWeb.getAuthorizationHeader(server), errorInterceptor: errorHandler.getHTTPErrorHandler(), + requestHooks: [getXHRRetryRequestHook()], }; const dicomWeb = new api.DICOMwebClient(config); diff --git a/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js b/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js index b1bb79cfe36..8e88302391a 100644 --- a/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js +++ b/platform/core/src/studies/services/wado/retrieveMetadataLoaderAsync.js @@ -1,6 +1,5 @@ import { api } from 'dicomweb-client'; import dcmjs from 'dcmjs'; -import retry, { operation } from 'retry'; import DICOMWeb from '../../../DICOMWeb/'; import RetrieveMetadataLoader from './retrieveMetadataLoader'; import { sortStudySeries, sortingCriteria } from '../../sortStudy'; @@ -11,6 +10,7 @@ import { } from './studyInstanceHelpers'; import errorHandler from '../../../errorHandler'; +import { getXHRRetryRequestHook } from '../../../utils/xhrRetryRequestHook'; const { naturalizeDataset } = dcmjs.data.DicomMetaDictionary; @@ -77,42 +77,7 @@ export default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader url: server.qidoRoot, headers: DICOMWeb.getAuthorizationHeader(server), errorInterceptor: errorHandler.getHTTPErrorHandler(), - requestHooks: [ - (request, metadata) => { - function faultTolerantRequestSend(...args) { - const operation = retry.operation({ - retries: 10, - }); - /** - * retries: 5, - * factor: 3, - * minTimeout: 1 * 1000, - * maxTimeout: 60 * 1000, - * randomize: true - */ - - operation.attempt(function(currentAttempt) { - const originalOnReadyStateChange = request.onreadystatechange; - - request.onreadystatechange = function() { - originalOnReadyStateChange.call(request); - if (request.status === 429 || request.status >= 500) { - operation.retry(new Error('Attempt failed!')); - } - }; - - console.debug(`${metadata.url} (attempt: ${currentAttempt})`); - request.open(metadata.method, metadata.url, true); - originalRequestSend.call(request, ...args); - }); - } - - const originalRequestSend = request.send; - request.send = faultTolerantRequestSend; - - return request; - }, - ], + requestHooks: [getXHRRetryRequestHook()], }); this.client = client; diff --git a/platform/core/src/studies/services/wado/retrieveMetadataLoaderSync.js b/platform/core/src/studies/services/wado/retrieveMetadataLoaderSync.js index 90d1ae98842..eebea975e01 100644 --- a/platform/core/src/studies/services/wado/retrieveMetadataLoaderSync.js +++ b/platform/core/src/studies/services/wado/retrieveMetadataLoaderSync.js @@ -4,6 +4,7 @@ import { createStudyFromSOPInstanceList } from './studyInstanceHelpers'; import RetrieveMetadataLoader from './retrieveMetadataLoader'; import errorHandler from '../../../errorHandler'; +import getXHRRetryRequestHook from '../../../utils/xhrRetryRequestHook'; /** * Class for sync load of study metadata. @@ -61,6 +62,7 @@ export default class RetrieveMetadataLoaderSync extends RetrieveMetadataLoader { url: server.wadoRoot, headers: DICOMWeb.getAuthorizationHeader(server), errorInterceptor: errorHandler.getHTTPErrorHandler(), + requestHooks: [getXHRRetryRequestHook()], }); this.client = client; diff --git a/platform/core/src/utils/dicomLoaderService.js b/platform/core/src/utils/dicomLoaderService.js index f0792129a2a..b354c61fffa 100644 --- a/platform/core/src/utils/dicomLoaderService.js +++ b/platform/core/src/utils/dicomLoaderService.js @@ -4,6 +4,7 @@ import { api } from 'dicomweb-client'; import DICOMWeb from '../DICOMWeb'; import errorHandler from '../errorHandler'; +import getXHRRetryRequestHook from './xhrRetryRequestHook'; const getImageId = imageObj => { if (!imageObj) { @@ -66,6 +67,7 @@ const wadorsRetriever = ( url, headers, errorInterceptor, + requestHooks: [getXHRRetryRequestHook()], }; const dicomWeb = new api.DICOMwebClient(config); diff --git a/platform/core/src/utils/index.js b/platform/core/src/utils/index.js index 6e9ea3140d5..87d6e19fd96 100644 --- a/platform/core/src/utils/index.js +++ b/platform/core/src/utils/index.js @@ -18,6 +18,7 @@ import isDicomUid from './isDicomUid'; import resolveObjectPath from './resolveObjectPath'; import * as hierarchicalListUtils from './hierarchicalListUtils'; import * as progressTrackingUtils from './progressTrackingUtils'; +import xhrRetryRequestHook from './xhrRetryRequestHook'; const utils = { guid, @@ -40,6 +41,7 @@ const utils = { resolveObjectPath, hierarchicalListUtils, progressTrackingUtils, + xhrRetryRequestHook, }; export { @@ -63,6 +65,7 @@ export { resolveObjectPath, hierarchicalListUtils, progressTrackingUtils, + xhrRetryRequestHook, }; export default utils; diff --git a/platform/core/src/utils/index.test.js b/platform/core/src/utils/index.test.js index 85eb382304a..a3ea78aa304 100644 --- a/platform/core/src/utils/index.test.js +++ b/platform/core/src/utils/index.test.js @@ -23,6 +23,7 @@ describe('Top level exports', () => { 'resolveObjectPath', 'hierarchicalListUtils', 'progressTrackingUtils', + 'xhrRetryRequestHook', ].sort(); const exports = Object.keys(utils.default).sort(); diff --git a/platform/core/src/utils/metadataProvider/fetchOverlayData.js b/platform/core/src/utils/metadataProvider/fetchOverlayData.js index 11e4d99cda7..42af12e0447 100644 --- a/platform/core/src/utils/metadataProvider/fetchOverlayData.js +++ b/platform/core/src/utils/metadataProvider/fetchOverlayData.js @@ -4,6 +4,7 @@ import str2ab from '../str2ab'; import unpackOverlay from './unpackOverlay'; import errorHandler from '../../errorHandler'; +import getXHRRetryRequestHook from '../xhrRetryRequestHook'; export default async function fetchOverlayData(instance, server) { const OverlayDataPromises = []; @@ -69,6 +70,7 @@ async function _getOverlayData(tag, server) { url: server.wadoRoot, //BulkDataURI is absolute, so this isn't used headers: DICOMWeb.getAuthorizationHeader(server), errorInterceptor: errorHandler.getHTTPErrorHandler(), + requestHooks: [getXHRRetryRequestHook()], }; const dicomWeb = new api.DICOMwebClient(config); const options = { diff --git a/platform/core/src/utils/metadataProvider/fetchPaletteColorLookupTableData.js b/platform/core/src/utils/metadataProvider/fetchPaletteColorLookupTableData.js index 8aba64ec4b0..26c65df577d 100644 --- a/platform/core/src/utils/metadataProvider/fetchPaletteColorLookupTableData.js +++ b/platform/core/src/utils/metadataProvider/fetchPaletteColorLookupTableData.js @@ -3,6 +3,7 @@ import DICOMWeb from '../../DICOMWeb'; import str2ab from '../str2ab'; import errorHandler from '../../errorHandler'; +import getXHRRetryRequestHook from '../xhrRetryRequestHook'; export default async function fetchPaletteColorLookupTableData( instance, @@ -141,6 +142,7 @@ function _getPaletteColor(server, paletteColorLookupTableData, lutDescriptor) { url: server.wadoRoot, //BulkDataURI is absolute, so this isn't used headers: DICOMWeb.getAuthorizationHeader(server), errorInterceptor: errorHandler.getHTTPErrorHandler(), + requestHooks: [getXHRRetryRequestHook()], }; const dicomWeb = new api.DICOMwebClient(config); const options = { diff --git a/platform/core/src/utils/xhrRetryRequestHook.js b/platform/core/src/utils/xhrRetryRequestHook.js new file mode 100644 index 00000000000..4b109621ec0 --- /dev/null +++ b/platform/core/src/utils/xhrRetryRequestHook.js @@ -0,0 +1,91 @@ +import retry from 'retry'; + +const defaultRetryOptions = { + retries: process.env.DICOMWEB_CLIENT_RETRY_RETRIES || 5, + factor: process.env.DICOMWEB_CLIENT_RETRY_FACTOR || 3, + minTimeout: process.env.DICOMWEB_CLIENT_RETRY_MIN_TIMEOUT || 1 * 1000, + maxTimeout: process.env.DICOMWEB_CLIENT_RETRY_MAX_TIMEOUT || 60 * 1000, + randomize: process.env.DICOMWEB_CLIENT_RETRY_RANDOMIZE || true, +}; + +let retryOptions = { ...defaultRetryOptions }; + +/** + * Request hook used to add retry functionality to XHR requests. + * + * @param {XMLHttpRequest} request XHR request instance + * @param {object} metadata Metadata about the request + * @param {object} metadata.url URL + * @param {object} metadata.method HTTP method + * @returns {XMLHttpRequest} request instance optionally modified + */ +const xhrRetryRequestHook = (request, metadata) => { + const { url, method } = metadata; + + function faultTolerantRequestSend(...args) { + const operation = retry.operation(retryOptions); + + operation.attempt(function operationAttempt(currentAttempt) { + const originalOnReadyStateChange = request.onreadystatechange; + + request.onreadystatechange = function onReadyStateChange() { + originalOnReadyStateChange.call(request); + if (request.status === 429 || request.status >= 500) { + const errorMessage = `Attempt to request ${url} failed.`; + const attemptFailedError = new Error(errorMessage); + operation.retry(attemptFailedError); + } + }; + + console.warn(`Requesting ${url}... (attempt: ${currentAttempt})`); + request.open(method, url, true); + originalRequestSend.call(request, ...args); + }); + } + + const originalRequestSend = request.send; + request.send = faultTolerantRequestSend; + + return request; +}; + +/** + * Returns a configured retry request hook function + * that can be used to add retry functionality to XHR request. + * + * Default options: + * retries: 5 + * factor: 3 + * minTimeout: 1 * 1000 + * maxTimeout: 60 * 1000 + * randomize: true + * + * @param {*} options + * @param {*} options.retires number of retries + * @param {*} options.factor factor + * @param {*} options.minTimeout the min timeout + * @param {*} options.maxTimeout the max timeout + * @param {*} options.randomize randomize + * @returns {function} the configured retry request function + */ +export const getXHRRetryRequestHook = (options = {}) => { + retryOptions = { ...defaultRetryOptions }; + if ('retries' in options) { + retryOptions.retries = options.retries; + } + if ('factor' in options) { + retryOptions.factor = options.factor; + } + if ('minTimeout' in options) { + retryOptions.minTimeout = options.minTimeout; + } + if ('maxTimeout' in options) { + retryOptions.maxTimeout = options.maxTimeout; + } + if ('randomize' in options) { + retryOptions.randomize = options.randomize; + } + return xhrRetryRequestHook; +}; + +export default getXHRRetryRequestHook; diff --git a/yarn.lock b/yarn.lock index db9b980d319..7d49192bb5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1247,34 +1247,13 @@ pirates "^4.0.0" source-map-support "^0.5.9" -"@babel/runtime@7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.1.2.tgz#81c89935f4647706fc54541145e6b4ecfef4b8e3" - integrity sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg== - dependencies: - regenerator-runtime "^0.12.0" - -"@babel/runtime@7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.0.tgz#4fc1d642a9fd0299754e8b5de62c631cf5568205" - integrity sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ== - dependencies: - regenerator-runtime "^0.13.2" - -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5": +"@babel/runtime@7.1.2", "@babel/runtime@7.5.5", "@babel/runtime@7.6.0", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" - integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== - dependencies: - regenerator-runtime "^0.13.4" - "@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" @@ -16544,11 +16523,6 @@ regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.12.0: - version "0.12.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" - integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== - regenerator-runtime@^0.13.1, regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" From 05444f48d4f86f4e193ad8fa371116e40985cf8b Mon Sep 17 00:00:00 2001 From: igoroctaviano Date: Thu, 13 May 2021 09:30:52 -0300 Subject: [PATCH 05/11] Improve docs remove env variables --- .webpack/webpack.base.js | 6 ---- .../core/src/utils/xhrRetryRequestHook.js | 29 +++++++++++-------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/.webpack/webpack.base.js b/.webpack/webpack.base.js index 59fe02ddf06..ea5c83aa499 100644 --- a/.webpack/webpack.base.js +++ b/.webpack/webpack.base.js @@ -85,12 +85,6 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => { 'process.env.USE_LOCIZE': JSON.stringify(process.env.USE_LOCIZE || ''), 'process.env.LOCIZE_PROJECTID': JSON.stringify(process.env.LOCIZE_PROJECTID || ''), 'process.env.LOCIZE_API_KEY': JSON.stringify(process.env.LOCIZE_API_KEY || ''), - /** DICOMWebClient Retry options */ - 'process.env.DICOMWEB_CLIENT_RETRY_RETRIES': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_RETRIES || 5), - 'process.env.DICOMWEB_CLIENT_RETRY_FACTOR': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_FACTOR || 3), - 'process.env.DICOMWEB_CLIENT_RETRY_MIN_TIMEOUT': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_MIN_TIMEOUT || 1 * 1000), - 'process.env.DICOMWEB_CLIENT_RETRY_MAX_TIMEOUT': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_MAX_TIMEOUT || 60 * 1000), - 'process.env.DICOMWEB_CLIENT_RETRY_RANDOMIZE': JSON.stringify(process.env.DICOMWEB_CLIENT_RETRY_RANDOMIZE || true), }), ], // Fix: https://github.com/webpack-contrib/css-loader/issues/447#issuecomment-285598881 diff --git a/platform/core/src/utils/xhrRetryRequestHook.js b/platform/core/src/utils/xhrRetryRequestHook.js index 4b109621ec0..3e7f09da2c4 100644 --- a/platform/core/src/utils/xhrRetryRequestHook.js +++ b/platform/core/src/utils/xhrRetryRequestHook.js @@ -1,11 +1,12 @@ import retry from 'retry'; const defaultRetryOptions = { - retries: process.env.DICOMWEB_CLIENT_RETRY_RETRIES || 5, - factor: process.env.DICOMWEB_CLIENT_RETRY_FACTOR || 3, - minTimeout: process.env.DICOMWEB_CLIENT_RETRY_MIN_TIMEOUT || 1 * 1000, - maxTimeout: process.env.DICOMWEB_CLIENT_RETRY_MAX_TIMEOUT || 60 * 1000, - randomize: process.env.DICOMWEB_CLIENT_RETRY_RANDOMIZE || true, + retries: 5, + factor: 3, + minTimeout: 1 * 1000, + maxTimeout: 60 * 1000, + randomize: true, + retryableStatusCodes: [429, 500], }; let retryOptions = { ...defaultRetryOptions }; @@ -28,9 +29,11 @@ const xhrRetryRequestHook = (request, metadata) => { operation.attempt(function operationAttempt(currentAttempt) { const originalOnReadyStateChange = request.onreadystatechange; + /** Overriding/extending XHR function */ request.onreadystatechange = function onReadyStateChange() { originalOnReadyStateChange.call(request); - if (request.status === 429 || request.status >= 500) { + + if (retryOptions.retryableStatusCodes.includes(request.status)) { const errorMessage = `Attempt to request ${url} failed.`; const attemptFailedError = new Error(errorMessage); operation.retry(attemptFailedError); @@ -43,6 +46,7 @@ const xhrRetryRequestHook = (request, metadata) => { }); } + /** Overriding/extending XHR function */ const originalRequestSend = request.send; request.send = faultTolerantRequestSend; @@ -60,12 +64,13 @@ const xhrRetryRequestHook = (request, metadata) => { * maxTimeout: 60 * 1000 * randomize: true * - * @param {*} options - * @param {*} options.retires number of retries - * @param {*} options.factor factor - * @param {*} options.minTimeout the min timeout - * @param {*} options.maxTimeout the max timeout - * @param {*} options.randomize randomize + * @param {object} options + * @param {number} options.retires number of retries + * @param {number} options.factor factor + * @param {number} options.minTimeout the min timeout + * @param {number} options.maxTimeout the max timeout + * @param {boolean} options.randomize randomize + * @param {array} options.retryableStatusCodes status codes that can trigger retry * @returns {function} the configured retry request function */ export const getXHRRetryRequestHook = (options = {}) => { From 5627e9c9196b168293491889365e2e265f4ee096 Mon Sep 17 00:00:00 2001 From: Davide Punzo Date: Thu, 3 Jun 2021 09:31:11 +0200 Subject: [PATCH 06/11] update dicomweb-client to version 0.8.0 --- extensions/debugging/package.json | 5 ++--- extensions/dicom-tag-browser/package.json | 2 +- platform/core/package.json | 2 +- platform/viewer/package.json | 2 +- yarn.lock | 13 ++++--------- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/extensions/debugging/package.json b/extensions/debugging/package.json index 3f8640c7e81..1222fd3d007 100644 --- a/extensions/debugging/package.json +++ b/extensions/debugging/package.json @@ -28,13 +28,12 @@ }, "peerDependencies": { "@ohif/core": "^2.6.0", - "dicom-parser": "^1.8.3", - "dicomweb-client": "^0.5.2" + "dicom-parser": "^1.8.3" }, "dependencies": { "@babel/runtime": "^7.5.5", "detect-browser": "5.1.1", - "dicomweb-client": "^0.6.0", + "dicomweb-client": "^0.8.0", "file-saver": "^2.0.2", "jszip": "^3.2.2" } diff --git a/extensions/dicom-tag-browser/package.json b/extensions/dicom-tag-browser/package.json index c111bb25d44..7739ecb3c32 100644 --- a/extensions/dicom-tag-browser/package.json +++ b/extensions/dicom-tag-browser/package.json @@ -33,7 +33,7 @@ }, "dependencies": { "@babel/runtime": "^7.5.5", - "dicomweb-client": "^0.6.0", + "dicomweb-client": "^0.8.0", "moment": "2.24.0", "react-select": "^3.0.8" } diff --git a/platform/core/package.json b/platform/core/package.json index 6e388dd619c..b95d34ed1cc 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -40,7 +40,7 @@ "@babel/runtime": "^7.5.5", "ajv": "^6.10.0", "dcmjs": "0.18.8", - "dicomweb-client": "^0.6.0", + "dicomweb-client": "^0.8.0", "immer": "6.0.2", "isomorphic-base64": "^1.0.2", "lodash.clonedeep": "^4.5.0", diff --git a/platform/viewer/package.json b/platform/viewer/package.json index a5f22547039..713fb99f619 100644 --- a/platform/viewer/package.json +++ b/platform/viewer/package.json @@ -70,7 +70,7 @@ "cornerstone-wado-image-loader": "^3.1.0", "dcmjs": "0.18.8", "dicom-parser": "^1.8.3", - "dicomweb-client": "^0.4.4", + "dicomweb-client": "^0.8.0", "hammerjs": "^2.0.8", "i18next": "^17.0.3", "i18next-browser-languagedetector": "^3.0.1", diff --git a/yarn.lock b/yarn.lock index b1ab3c665fc..5d9489f5a09 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6940,20 +6940,15 @@ dicom-parser@^1.8.3: resolved "https://registry.yarnpkg.com/dicom-parser/-/dicom-parser-1.8.3.tgz#6e4b862898112304db30143147562011c1ce6a4d" integrity sha512-CMeUr+jea7Ml70N+/Z5Pd2MYtvLp6IU+TnvdLe6VRVKzZuTeYLYyuAQa9R+sFK4v4N39hig+hKHN+Wfi9sQ6GA== -dicomweb-client@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.4.4.tgz#0ca0c7706556f3114330a3c40946ee66808148e4" - integrity sha512-5S7wLYxQgHnOyEgR1zlZlt79IjzOk+YDB/Jjzte6ijRZsAoj9RUiIZcsTyxvBD9gLMYs/954n2kYHdbz83Xbtw== - dicomweb-client@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.5.2.tgz#aa5a4a6a5044b0702bb0a8a2662c86cd16901951" integrity sha512-e11n2+g7HfBuMyopWq76W11eSZJ707g4U1XiO8URA+23aoe0g1kGAtlPB29NKXl7zX7RznTJ7wfRBxFkW6EJDA== -dicomweb-client@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.6.0.tgz#5e35ada52fe0155af1cc1f0e84f9c7f76477f92d" - integrity sha512-VAkBg4W6odIo2XsFxqjN/rptd7bQ8oHpRuKH5d46E9BUIPzRschazE8Dx1xg7/l3N3f1M70jB7yJ339arAXiDQ== +dicomweb-client@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.8.0.tgz#cab2d8266e6d2da6fadb023173ca9be0cd06cbfe" + integrity sha512-R4Vz/INGGSVMfV1X1dhbhYD0Wxp0znoU/KMPU4qMIGZLxtvS2b9xyh8H5PU8jTnjDmVAdHK3roxOMyJJvB6nKw== diff-sequences@^24.9.0: version "24.9.0" From 26b7b34bd4cd6af13ec0786f2e6aa22e0e783ade Mon Sep 17 00:00:00 2001 From: igoroctaviano Date: Thu, 3 Jun 2021 07:10:33 -0300 Subject: [PATCH 07/11] Add check for metadata --- platform/core/src/utils/xhrRetryRequestHook.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/core/src/utils/xhrRetryRequestHook.js b/platform/core/src/utils/xhrRetryRequestHook.js index 3e7f09da2c4..68d72b4350e 100644 --- a/platform/core/src/utils/xhrRetryRequestHook.js +++ b/platform/core/src/utils/xhrRetryRequestHook.js @@ -21,6 +21,10 @@ let retryOptions = { ...defaultRetryOptions }; * @returns {XMLHttpRequest} request instance optionally modified */ const xhrRetryRequestHook = (request, metadata) => { + if (!metadata) { + return request; + } + const { url, method } = metadata; function faultTolerantRequestSend(...args) { From bd2ddd7702d85a218386cd0a8217f5488fd81d00 Mon Sep 17 00:00:00 2001 From: igoroctaviano Date: Thu, 3 Jun 2021 07:20:49 -0300 Subject: [PATCH 08/11] Remove metadata check --- platform/core/src/utils/xhrRetryRequestHook.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platform/core/src/utils/xhrRetryRequestHook.js b/platform/core/src/utils/xhrRetryRequestHook.js index 68d72b4350e..3e7f09da2c4 100644 --- a/platform/core/src/utils/xhrRetryRequestHook.js +++ b/platform/core/src/utils/xhrRetryRequestHook.js @@ -21,10 +21,6 @@ let retryOptions = { ...defaultRetryOptions }; * @returns {XMLHttpRequest} request instance optionally modified */ const xhrRetryRequestHook = (request, metadata) => { - if (!metadata) { - return request; - } - const { url, method } = metadata; function faultTolerantRequestSend(...args) { From f847633cf347bb3b8831a17fd70e498646bd1f13 Mon Sep 17 00:00:00 2001 From: Davide Punzo Date: Thu, 3 Jun 2021 16:25:06 +0200 Subject: [PATCH 09/11] update dicomweb-client to version 0.8.1 --- extensions/debugging/package.json | 2 +- extensions/dicom-tag-browser/package.json | 2 +- platform/core/package.json | 2 +- platform/viewer/package.json | 2 +- yarn.lock | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/debugging/package.json b/extensions/debugging/package.json index 1222fd3d007..40ed709b43a 100644 --- a/extensions/debugging/package.json +++ b/extensions/debugging/package.json @@ -33,7 +33,7 @@ "dependencies": { "@babel/runtime": "^7.5.5", "detect-browser": "5.1.1", - "dicomweb-client": "^0.8.0", + "dicomweb-client": "^0.8.1", "file-saver": "^2.0.2", "jszip": "^3.2.2" } diff --git a/extensions/dicom-tag-browser/package.json b/extensions/dicom-tag-browser/package.json index 7739ecb3c32..9c223045833 100644 --- a/extensions/dicom-tag-browser/package.json +++ b/extensions/dicom-tag-browser/package.json @@ -33,7 +33,7 @@ }, "dependencies": { "@babel/runtime": "^7.5.5", - "dicomweb-client": "^0.8.0", + "dicomweb-client": "^0.8.1", "moment": "2.24.0", "react-select": "^3.0.8" } diff --git a/platform/core/package.json b/platform/core/package.json index b95d34ed1cc..fd3ca9c4323 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -40,7 +40,7 @@ "@babel/runtime": "^7.5.5", "ajv": "^6.10.0", "dcmjs": "0.18.8", - "dicomweb-client": "^0.8.0", + "dicomweb-client": "^0.8.1", "immer": "6.0.2", "isomorphic-base64": "^1.0.2", "lodash.clonedeep": "^4.5.0", diff --git a/platform/viewer/package.json b/platform/viewer/package.json index 713fb99f619..510791c75be 100644 --- a/platform/viewer/package.json +++ b/platform/viewer/package.json @@ -70,7 +70,7 @@ "cornerstone-wado-image-loader": "^3.1.0", "dcmjs": "0.18.8", "dicom-parser": "^1.8.3", - "dicomweb-client": "^0.8.0", + "dicomweb-client": "^0.8.1", "hammerjs": "^2.0.8", "i18next": "^17.0.3", "i18next-browser-languagedetector": "^3.0.1", diff --git a/yarn.lock b/yarn.lock index 5d9489f5a09..d439562f6c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6945,10 +6945,10 @@ dicomweb-client@^0.5.2: resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.5.2.tgz#aa5a4a6a5044b0702bb0a8a2662c86cd16901951" integrity sha512-e11n2+g7HfBuMyopWq76W11eSZJ707g4U1XiO8URA+23aoe0g1kGAtlPB29NKXl7zX7RznTJ7wfRBxFkW6EJDA== -dicomweb-client@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.8.0.tgz#cab2d8266e6d2da6fadb023173ca9be0cd06cbfe" - integrity sha512-R4Vz/INGGSVMfV1X1dhbhYD0Wxp0znoU/KMPU4qMIGZLxtvS2b9xyh8H5PU8jTnjDmVAdHK3roxOMyJJvB6nKw== +dicomweb-client@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/dicomweb-client/-/dicomweb-client-0.8.1.tgz#12bdf0e9698bcf82730f38829ac30158164bb3fd" + integrity sha512-5EbK8epfSuonSnCW3nr2tkA1CcO1aFT3grEVvKXqv0tVyHsBvbEcEmBcPEbu1m/cF6t7+3uQRLOQ4dw4CodxFg== diff-sequences@^24.9.0: version "24.9.0" From 98fcabfcb5bd58d18006fe0cb7e6d8cfc91e4753 Mon Sep 17 00:00:00 2001 From: igoroctaviano Date: Thu, 3 Jun 2021 12:08:33 -0300 Subject: [PATCH 10/11] Resolve opening connection before previsouly setting headers --- platform/core/src/utils/xhrRetryRequestHook.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/platform/core/src/utils/xhrRetryRequestHook.js b/platform/core/src/utils/xhrRetryRequestHook.js index 3e7f09da2c4..487b0439c1e 100644 --- a/platform/core/src/utils/xhrRetryRequestHook.js +++ b/platform/core/src/utils/xhrRetryRequestHook.js @@ -30,8 +30,8 @@ const xhrRetryRequestHook = (request, metadata) => { const originalOnReadyStateChange = request.onreadystatechange; /** Overriding/extending XHR function */ - request.onreadystatechange = function onReadyStateChange() { - originalOnReadyStateChange.call(request); + request.onreadystatechange = function onReadyStateChange(...args) { + originalOnReadyStateChange.apply(request, args); if (retryOptions.retryableStatusCodes.includes(request.status)) { const errorMessage = `Attempt to request ${url} failed.`; @@ -40,10 +40,14 @@ const xhrRetryRequestHook = (request, metadata) => { } }; - console.warn(`Requesting ${url}... (attempt: ${currentAttempt})`); - request.open(method, url, true); - originalRequestSend.call(request, ...args); + /** Call open only on retry (after headers and other things were set in the xhr instance) */ + if (currentAttempt > 1) { + console.warn(`Requesting ${url}... (attempt: ${currentAttempt})`); + request.open(method, url, true); + } }); + + originalRequestSend.apply(request, args); } /** Overriding/extending XHR function */ From d575e36879e0f3911d30e449d514c75491426b24 Mon Sep 17 00:00:00 2001 From: igoroctaviano Date: Thu, 3 Jun 2021 17:24:39 -0300 Subject: [PATCH 11/11] Expose retryable option --- platform/core/src/utils/xhrRetryRequestHook.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/core/src/utils/xhrRetryRequestHook.js b/platform/core/src/utils/xhrRetryRequestHook.js index 487b0439c1e..2b492971da6 100644 --- a/platform/core/src/utils/xhrRetryRequestHook.js +++ b/platform/core/src/utils/xhrRetryRequestHook.js @@ -94,6 +94,9 @@ export const getXHRRetryRequestHook = (options = {}) => { if ('randomize' in options) { retryOptions.randomize = options.randomize; } + if ('retryableStatusCodes' in options) { + retryOptions.retryableStatusCodes = options.retryableStatusCodes; + } return xhrRetryRequestHook; };