@funnelsgrove/runtime 0.7.19 → 0.7.20
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.
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const inflightByFunnelId = new Map();
|
|
2
|
+
const TRANSIENT_RUNTIME_CONFIG_STATUSES = new Set([408, 429, 500, 502, 503, 504]);
|
|
3
|
+
const RUNTIME_CONFIG_RETRY_DELAYS_MS = [250, 750];
|
|
4
|
+
const wait = (delayMs) => (new Promise((resolve) => setTimeout(resolve, delayMs)));
|
|
2
5
|
const isRecord = (value) => (value !== null && typeof value === 'object' && !Array.isArray(value));
|
|
3
6
|
const readString = (value) => (typeof value === 'string' && value.trim() ? value.trim() : null);
|
|
4
7
|
const readNumber = (value) => (typeof value === 'number' && Number.isFinite(value) ? value : null);
|
|
@@ -297,19 +300,38 @@ export const loadFunnelRuntimeConfig = (funnelId, options = {}) => {
|
|
|
297
300
|
}
|
|
298
301
|
const fetcher = options.fetcher || globalThis.fetch;
|
|
299
302
|
const basePath = (options.basePath || '/api/funnel-config').replace(/\/$/, '');
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
303
|
+
const requestUrl = `${basePath}/${encodeURIComponent(normalizedFunnelId)}?versionId=${encodeURIComponent(versionId)}`;
|
|
304
|
+
const request = (async () => {
|
|
305
|
+
for (let attempt = 0;; attempt += 1) {
|
|
306
|
+
let response;
|
|
307
|
+
try {
|
|
308
|
+
response = await fetcher(requestUrl, {
|
|
309
|
+
cache: 'no-store',
|
|
310
|
+
headers: { accept: 'application/json', 'cache-control': 'no-cache' },
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
const retryDelay = RUNTIME_CONFIG_RETRY_DELAYS_MS[attempt];
|
|
315
|
+
if (retryDelay === undefined)
|
|
316
|
+
throw error;
|
|
317
|
+
await wait(retryDelay);
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (!response.ok) {
|
|
321
|
+
const retryDelay = RUNTIME_CONFIG_RETRY_DELAYS_MS[attempt];
|
|
322
|
+
if (retryDelay !== undefined && TRANSIENT_RUNTIME_CONFIG_STATUSES.has(response.status)) {
|
|
323
|
+
await wait(retryDelay);
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
throw new Error(`Unable to load funnel runtime config (${response.status})`);
|
|
327
|
+
}
|
|
328
|
+
const published = parsePublishedRuntimeConfig(await response.json());
|
|
329
|
+
if (published.config.funnelId !== normalizedFunnelId) {
|
|
330
|
+
throw new Error('Funnel runtime config belongs to a different funnel');
|
|
331
|
+
}
|
|
332
|
+
return published;
|
|
310
333
|
}
|
|
311
|
-
|
|
312
|
-
}).finally(() => {
|
|
334
|
+
})().finally(() => {
|
|
313
335
|
inflightByFunnelId.delete(cacheKey);
|
|
314
336
|
});
|
|
315
337
|
inflightByFunnelId.set(cacheKey, request);
|