diff --git a/packages/analytics-js-common/src/types/LoadOptions.ts b/packages/analytics-js-common/src/types/LoadOptions.ts index 540298706..9865b5a53 100644 --- a/packages/analytics-js-common/src/types/LoadOptions.ts +++ b/packages/analytics-js-common/src/types/LoadOptions.ts @@ -78,6 +78,8 @@ export type QueueOpts = { maxItems?: number; // Options for batched requests batch?: BatchOpts; + // The scale factor applied to the default timer values + timerScaleFactor?: number; }; /** diff --git a/packages/analytics-js-plugins/src/utilities/retryQueue/RetryQueue.ts b/packages/analytics-js-plugins/src/utilities/retryQueue/RetryQueue.ts index 9aeaef8a1..263927d48 100644 --- a/packages/analytics-js-plugins/src/utilities/retryQueue/RetryQueue.ts +++ b/packages/analytics-js-plugins/src/utilities/retryQueue/RetryQueue.ts @@ -32,6 +32,8 @@ import { DEFAULT_RECLAIM_TIMEOUT_MS, DEFAULT_RECLAIM_WAIT_MS, DEFAULT_BATCH_FLUSH_INTERVAL_MS, + MIN_TIMER_SCALE_FACTOR, + MAX_TIMER_SCALE_FACTOR, } from './constants'; const sortByTime = (a: QueueItem, b: QueueItem) => a.time - b.time; @@ -97,12 +99,21 @@ class RetryQueue implements IQueue { jitter: options.backoffJitter || DEFAULT_BACKOFF_JITTER, }; + // Limit the timer scale factor to the minimum value + let timerScaleFactor = Math.max( + options.timerScaleFactor ?? MIN_TIMER_SCALE_FACTOR, + MIN_TIMER_SCALE_FACTOR, + ); + + // Limit the timer scale factor to the maximum value + timerScaleFactor = Math.min(timerScaleFactor, MAX_TIMER_SCALE_FACTOR); + // painstakingly tuned. that's why they're not "easily" configurable this.timeouts = { - ackTimer: DEFAULT_ACK_TIMER_MS, - reclaimTimer: DEFAULT_RECLAIM_TIMER_MS, - reclaimTimeout: DEFAULT_RECLAIM_TIMEOUT_MS, - reclaimWait: DEFAULT_RECLAIM_WAIT_MS, + ackTimer: Math.round(timerScaleFactor * DEFAULT_ACK_TIMER_MS), + reclaimTimer: Math.round(timerScaleFactor * DEFAULT_RECLAIM_TIMER_MS), + reclaimTimeout: Math.round(timerScaleFactor * DEFAULT_RECLAIM_TIMEOUT_MS), + reclaimWait: Math.round(timerScaleFactor * DEFAULT_RECLAIM_WAIT_MS), }; this.schedule = new Schedule(); @@ -311,7 +322,7 @@ class RetryQueue implements IQueue { batchQueue = batchQueue.slice(-batchQueue.length); batchQueue.push(entry); - const batchDispatchInfo = this.getBatchDispInfo(batchQueue); + const batchDispatchInfo = this.getBatchDispatchInfo(batchQueue); // if batch criteria is met, queue the batch events to the main queue and clear batch queue if (batchDispatchInfo.criteriaMet || batchDispatchInfo.criteriaExceeded) { let batchItems; @@ -405,7 +416,7 @@ class RetryQueue implements IQueue { * @param batchItems Prospective batch items * @returns Batch dispatch info */ - getBatchDispInfo(batchItems: QueueItem[]) { + getBatchDispatchInfo(batchItems: QueueItem[]) { let lengthCriteriaMet = false; let lengthCriteriaExceeded = false; const configuredBatchMaxItems = this.batch?.maxItems as number; @@ -626,7 +637,7 @@ class RetryQueue implements IQueue { const maxAttempts = 2; const queueEntryKeys = Object.keys(QueueStatuses); const entry = QueueStatuses[queueEntryKeys[entryIdx] as keyof typeof QueueStatuses]; - + (globalThis as typeof window).setTimeout(() => { try { store.remove(entry); diff --git a/packages/analytics-js-plugins/src/utilities/retryQueue/constants.ts b/packages/analytics-js-plugins/src/utilities/retryQueue/constants.ts index 8e1d190bc..5ed1d8023 100644 --- a/packages/analytics-js-plugins/src/utilities/retryQueue/constants.ts +++ b/packages/analytics-js-plugins/src/utilities/retryQueue/constants.ts @@ -10,6 +10,8 @@ const DEFAULT_ACK_TIMER_MS = 1000; const DEFAULT_RECLAIM_TIMER_MS = 3000; const DEFAULT_RECLAIM_TIMEOUT_MS = 10000; const DEFAULT_RECLAIM_WAIT_MS = 500; +const MIN_TIMER_SCALE_FACTOR = 1; +const MAX_TIMER_SCALE_FACTOR = 10; const DEFAULT_MAX_BATCH_SIZE_BYTES = 512 * 1024; // 512 KB; this is also the max size of a batch const DEFAULT_MAX_BATCH_ITEMS = 100; @@ -29,4 +31,6 @@ export { DEFAULT_MAX_BATCH_SIZE_BYTES, DEFAULT_MAX_BATCH_ITEMS, DEFAULT_BATCH_FLUSH_INTERVAL_MS, + MIN_TIMER_SCALE_FACTOR, + MAX_TIMER_SCALE_FACTOR, };