@splitsoftware/splitio-commons 1.6.2-rc.9 → 1.7.0
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/CHANGES.txt +3 -1
- package/cjs/consent/sdkUserConsent.js +2 -2
- package/cjs/listeners/browser.js +11 -12
- package/cjs/logger/constants.js +2 -1
- package/cjs/sdkClient/sdkClient.js +3 -1
- package/cjs/sdkFactory/index.js +26 -26
- package/cjs/services/splitApi.js +20 -0
- package/cjs/storages/AbstractSplitsCacheAsync.js +1 -1
- package/cjs/storages/AbstractSplitsCacheSync.js +1 -1
- package/cjs/storages/KeyBuilderSS.js +10 -43
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +0 -1
- package/cjs/storages/inLocalStorage/index.js +17 -9
- package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +12 -1
- package/cjs/storages/inMemory/InMemoryStorage.js +13 -6
- package/cjs/storages/inMemory/InMemoryStorageCS.js +13 -6
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +60 -35
- package/cjs/storages/inMemory/UniqueKeysCacheInMemory.js +72 -0
- package/cjs/storages/inMemory/UniqueKeysCacheInMemoryCS.js +76 -0
- package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +85 -0
- package/cjs/storages/inRedis/ImpressionsCacheInRedis.js +2 -19
- package/cjs/storages/inRedis/TelemetryCacheInRedis.js +4 -4
- package/cjs/storages/inRedis/UniqueKeysCacheInRedis.js +71 -0
- package/cjs/storages/inRedis/constants.js +4 -1
- package/cjs/storages/inRedis/index.js +20 -3
- package/cjs/storages/pluggable/ImpressionCountsCachePluggable.js +81 -0
- package/cjs/storages/pluggable/ImpressionsCachePluggable.js +2 -19
- package/cjs/storages/pluggable/TelemetryCachePluggable.js +4 -4
- package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +61 -0
- package/cjs/storages/pluggable/inMemoryWrapper.js +8 -6
- package/cjs/storages/pluggable/index.js +38 -9
- package/cjs/storages/utils.js +73 -0
- package/cjs/sync/submitters/submitterManager.js +3 -0
- package/cjs/sync/submitters/telemetrySubmitter.js +5 -40
- package/cjs/sync/submitters/uniqueKeysSubmitter.js +27 -0
- package/cjs/trackers/impressionObserver/utils.js +1 -17
- package/cjs/trackers/impressionsTracker.js +22 -41
- package/cjs/trackers/strategy/strategyDebug.js +25 -0
- package/cjs/trackers/strategy/strategyNone.js +29 -0
- package/cjs/trackers/strategy/strategyOptimized.js +35 -0
- package/cjs/trackers/uniqueKeysTracker.js +38 -0
- package/cjs/utils/constants/index.js +4 -2
- package/cjs/utils/redis/RedisMock.js +31 -0
- package/cjs/utils/settingsValidation/impressionsMode.js +2 -2
- package/cjs/utils/settingsValidation/index.js +7 -1
- package/esm/consent/sdkUserConsent.js +2 -2
- package/esm/listeners/browser.js +12 -13
- package/esm/logger/constants.js +1 -0
- package/esm/sdkClient/sdkClient.js +3 -1
- package/esm/sdkFactory/index.js +26 -26
- package/esm/services/splitApi.js +20 -0
- package/esm/storages/AbstractSplitsCacheAsync.js +1 -1
- package/esm/storages/AbstractSplitsCacheSync.js +1 -1
- package/esm/storages/KeyBuilderSS.js +7 -37
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +0 -1
- package/esm/storages/inLocalStorage/index.js +18 -10
- package/esm/storages/inMemory/ImpressionCountsCacheInMemory.js +12 -1
- package/esm/storages/inMemory/InMemoryStorage.js +14 -7
- package/esm/storages/inMemory/InMemoryStorageCS.js +14 -7
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +61 -36
- package/esm/storages/inMemory/UniqueKeysCacheInMemory.js +68 -0
- package/esm/storages/inMemory/UniqueKeysCacheInMemoryCS.js +73 -0
- package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +82 -0
- package/esm/storages/inRedis/ImpressionsCacheInRedis.js +2 -19
- package/esm/storages/inRedis/TelemetryCacheInRedis.js +1 -1
- package/esm/storages/inRedis/UniqueKeysCacheInRedis.js +68 -0
- package/esm/storages/inRedis/constants.js +3 -0
- package/esm/storages/inRedis/index.js +21 -4
- package/esm/storages/pluggable/ImpressionCountsCachePluggable.js +78 -0
- package/esm/storages/pluggable/ImpressionsCachePluggable.js +2 -19
- package/esm/storages/pluggable/TelemetryCachePluggable.js +1 -1
- package/esm/storages/pluggable/UniqueKeysCachePluggable.js +58 -0
- package/esm/storages/pluggable/inMemoryWrapper.js +8 -6
- package/esm/storages/pluggable/index.js +39 -10
- package/esm/storages/utils.js +65 -0
- package/esm/sync/submitters/submitterManager.js +3 -0
- package/esm/sync/submitters/telemetrySubmitter.js +5 -39
- package/esm/sync/submitters/uniqueKeysSubmitter.js +23 -0
- package/esm/trackers/impressionObserver/utils.js +1 -15
- package/esm/trackers/impressionsTracker.js +22 -41
- package/esm/trackers/strategy/strategyDebug.js +21 -0
- package/esm/trackers/strategy/strategyNone.js +25 -0
- package/esm/trackers/strategy/strategyOptimized.js +31 -0
- package/esm/trackers/uniqueKeysTracker.js +34 -0
- package/esm/utils/constants/index.js +2 -0
- package/esm/utils/redis/RedisMock.js +28 -0
- package/esm/utils/settingsValidation/impressionsMode.js +3 -3
- package/esm/utils/settingsValidation/index.js +7 -1
- package/package.json +1 -2
- package/src/consent/sdkUserConsent.ts +2 -2
- package/src/listeners/browser.ts +12 -15
- package/src/logger/constants.ts +1 -0
- package/src/sdkClient/sdkClient.ts +3 -1
- package/src/sdkFactory/index.ts +29 -31
- package/src/sdkFactory/types.ts +7 -4
- package/src/services/splitApi.ts +22 -0
- package/src/services/types.ts +6 -0
- package/src/storages/AbstractSplitsCacheAsync.ts +1 -1
- package/src/storages/AbstractSplitsCacheSync.ts +1 -1
- package/src/storages/KeyBuilderSS.ts +9 -43
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +0 -1
- package/src/storages/inLocalStorage/index.ts +18 -10
- package/src/storages/inMemory/AttributesCacheInMemory.ts +7 -7
- package/src/storages/inMemory/ImpressionCountsCacheInMemory.ts +16 -1
- package/src/storages/inMemory/InMemoryStorage.ts +14 -7
- package/src/storages/inMemory/InMemoryStorageCS.ts +14 -7
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +69 -34
- package/src/storages/inMemory/UniqueKeysCacheInMemory.ts +80 -0
- package/src/storages/inMemory/UniqueKeysCacheInMemoryCS.ts +86 -0
- package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +95 -0
- package/src/storages/inRedis/ImpressionsCacheInRedis.ts +2 -22
- package/src/storages/inRedis/TelemetryCacheInRedis.ts +3 -2
- package/src/storages/inRedis/UniqueKeysCacheInRedis.ts +77 -0
- package/src/storages/inRedis/constants.ts +3 -0
- package/src/storages/inRedis/index.ts +18 -5
- package/src/storages/pluggable/ImpressionCountsCachePluggable.ts +92 -0
- package/src/storages/pluggable/ImpressionsCachePluggable.ts +3 -23
- package/src/storages/pluggable/TelemetryCachePluggable.ts +3 -2
- package/src/storages/pluggable/UniqueKeysCachePluggable.ts +67 -0
- package/src/storages/pluggable/inMemoryWrapper.ts +6 -6
- package/src/storages/pluggable/index.ts +41 -9
- package/src/storages/types.ts +56 -55
- package/src/storages/utils.ts +78 -0
- package/src/sync/submitters/submitter.ts +2 -2
- package/src/sync/submitters/submitterManager.ts +2 -0
- package/src/sync/submitters/telemetrySubmitter.ts +8 -43
- package/src/sync/submitters/types.ts +29 -27
- package/src/sync/submitters/uniqueKeysSubmitter.ts +36 -0
- package/src/trackers/impressionObserver/utils.ts +1 -16
- package/src/trackers/impressionsTracker.ts +25 -46
- package/src/trackers/strategy/strategyDebug.ts +28 -0
- package/src/trackers/strategy/strategyNone.ts +34 -0
- package/src/trackers/strategy/strategyOptimized.ts +42 -0
- package/src/trackers/types.ts +28 -0
- package/src/trackers/uniqueKeysTracker.ts +48 -0
- package/src/types.ts +1 -1
- package/src/utils/constants/index.ts +2 -0
- package/src/utils/redis/RedisMock.ts +33 -0
- package/src/utils/settingsValidation/impressionsMode.ts +3 -3
- package/src/utils/settingsValidation/index.ts +5 -1
- package/types/logger/constants.d.ts +1 -0
- package/types/sdkFactory/types.d.ts +4 -2
- package/types/services/types.d.ts +4 -0
- package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
- package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
- package/types/storages/KeyBuilderSS.d.ts +3 -3
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +0 -1
- package/types/storages/inMemory/ImpressionCountsCacheInMemory.d.ts +5 -1
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +20 -9
- package/types/storages/inMemory/uniqueKeysCacheInMemory.d.ts +35 -0
- package/types/storages/inMemory/uniqueKeysCacheInMemoryCS.d.ts +35 -0
- package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +16 -0
- package/types/storages/inRedis/ImpressionsCacheInRedis.d.ts +0 -1
- package/types/storages/inRedis/constants.d.ts +3 -0
- package/types/storages/inRedis/uniqueKeysCacheInRedis.d.ts +21 -0
- package/types/storages/pluggable/ImpressionCountsCachePluggable.d.ts +16 -0
- package/types/storages/pluggable/ImpressionsCachePluggable.d.ts +1 -2
- package/types/storages/pluggable/UniqueKeysCachePluggable.d.ts +20 -0
- package/types/storages/types.d.ts +39 -38
- package/types/storages/utils.d.ts +8 -0
- package/types/sync/submitters/submitter.d.ts +2 -2
- package/types/sync/submitters/telemetrySubmitter.d.ts +2 -10
- package/types/sync/submitters/types.d.ts +27 -7
- package/types/sync/submitters/uniqueKeysSubmitter.d.ts +5 -0
- package/types/trackers/impressionObserver/utils.d.ts +0 -8
- package/types/trackers/impressionsTracker.d.ts +4 -6
- package/types/trackers/strategy/strategyDebug.d.ts +9 -0
- package/types/trackers/strategy/strategyNone.d.ts +10 -0
- package/types/trackers/strategy/strategyOptimized.d.ts +11 -0
- package/types/trackers/types.d.ts +23 -0
- package/types/trackers/uniqueKeysTracker.d.ts +13 -0
- package/types/types.d.ts +1 -1
- package/types/utils/constants/index.d.ts +2 -0
- package/types/utils/redis/RedisMock.d.ts +4 -0
- package/cjs/storages/metadataBuilder.js +0 -12
- package/esm/storages/metadataBuilder.js +0 -8
- package/src/storages/metadataBuilder.ts +0 -11
|
@@ -61,7 +61,7 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
|
|
|
61
61
|
* @param {string} name
|
|
62
62
|
* @param {string} defaultTreatment
|
|
63
63
|
* @param {number} changeNumber
|
|
64
|
-
* @returns {
|
|
64
|
+
* @returns {boolean} `true` if the operation successed updating the split, or `false` if no split is updated,
|
|
65
65
|
* for instance, if the `changeNumber` is old, or if the split is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
|
|
66
66
|
*/
|
|
67
67
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { KeyBuilder } from './KeyBuilder';
|
|
2
2
|
import { IMetadata } from '../dtos/types';
|
|
3
3
|
import { Method } from '../sync/submitters/types';
|
|
4
|
-
import { MAX_LATENCY_BUCKET_COUNT } from './inMemory/TelemetryCacheInMemory';
|
|
5
4
|
|
|
6
|
-
const METHOD_NAMES: Record<Method, string> = {
|
|
5
|
+
export const METHOD_NAMES: Record<Method, string> = {
|
|
7
6
|
t: 'treatment',
|
|
8
7
|
ts: 'treatments',
|
|
9
8
|
tc: 'treatmentWithConfig',
|
|
@@ -34,6 +33,14 @@ export class KeyBuilderSS extends KeyBuilder {
|
|
|
34
33
|
return `${this.prefix}.impressions`;
|
|
35
34
|
}
|
|
36
35
|
|
|
36
|
+
buildImpressionsCountKey() {
|
|
37
|
+
return `${this.prefix}.impressions.count`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
buildUniqueKeysKey() {
|
|
41
|
+
return `${this.prefix}.uniquekeys`;
|
|
42
|
+
}
|
|
43
|
+
|
|
37
44
|
buildEventsKey() {
|
|
38
45
|
return `${this.prefix}.events`;
|
|
39
46
|
}
|
|
@@ -57,44 +64,3 @@ export class KeyBuilderSS extends KeyBuilder {
|
|
|
57
64
|
}
|
|
58
65
|
|
|
59
66
|
}
|
|
60
|
-
|
|
61
|
-
// Used by consumer methods of TelemetryCacheInRedis and TelemetryCachePluggable
|
|
62
|
-
|
|
63
|
-
const REVERSE_METHOD_NAMES = Object.keys(METHOD_NAMES).reduce((acc, key) => {
|
|
64
|
-
acc[METHOD_NAMES[key as Method]] = key as Method;
|
|
65
|
-
return acc;
|
|
66
|
-
}, {} as Record<string, Method>);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
export function parseMetadata(field: string): [metadata: string] | string {
|
|
70
|
-
const parts = field.split('/');
|
|
71
|
-
if (parts.length !== 3) return `invalid subsection count. Expected 4, got: ${parts.length}`;
|
|
72
|
-
|
|
73
|
-
const [s /* metadata.s */, n /* metadata.n */, i /* metadata.i */] = parts;
|
|
74
|
-
return [JSON.stringify({ s, n, i })];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function parseExceptionField(field: string): [metadata: string, method: Method] | string {
|
|
78
|
-
const parts = field.split('/');
|
|
79
|
-
if (parts.length !== 4) return `invalid subsection count. Expected 4, got: ${parts.length}`;
|
|
80
|
-
|
|
81
|
-
const [s /* metadata.s */, n /* metadata.n */, i /* metadata.i */, m] = parts;
|
|
82
|
-
const method = REVERSE_METHOD_NAMES[m];
|
|
83
|
-
if (!method) return `unknown method '${m}'`;
|
|
84
|
-
|
|
85
|
-
return [JSON.stringify({ s, n, i }), method];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function parseLatencyField(field: string): [metadata: string, method: Method, bucket: number] | string {
|
|
89
|
-
const parts = field.split('/');
|
|
90
|
-
if (parts.length !== 5) return `invalid subsection count. Expected 5, got: ${parts.length}`;
|
|
91
|
-
|
|
92
|
-
const [s /* metadata.s */, n /* metadata.n */, i /* metadata.i */, m, b] = parts;
|
|
93
|
-
const method = REVERSE_METHOD_NAMES[m];
|
|
94
|
-
if (!method) return `unknown method '${m}'`;
|
|
95
|
-
|
|
96
|
-
const bucket = parseInt(b);
|
|
97
|
-
if (isNaN(bucket) || bucket >= MAX_LATENCY_BUCKET_COUNT) return `invalid bucket. Expected a number between 0 and 22, got: ${b}`;
|
|
98
|
-
|
|
99
|
-
return [JSON.stringify({ s, n, i }), method, bucket];
|
|
100
|
-
}
|
|
@@ -229,7 +229,6 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
229
229
|
|
|
230
230
|
/**
|
|
231
231
|
* Clean Splits cache if its `lastUpdated` timestamp is older than the given `expirationTimestamp`,
|
|
232
|
-
* Clean operation (clear) also updates `lastUpdated` timestamp with current time.
|
|
233
232
|
*
|
|
234
233
|
* @param {number | undefined} expirationTimestamp if the value is not a number, data will not be cleaned
|
|
235
234
|
*/
|
|
@@ -12,8 +12,10 @@ import { SplitsCacheInMemory } from '../inMemory/SplitsCacheInMemory';
|
|
|
12
12
|
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
|
|
13
13
|
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
|
|
14
14
|
import { LOG_PREFIX } from './constants';
|
|
15
|
-
import { STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
15
|
+
import { DEBUG, NONE, STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
16
16
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
|
|
17
|
+
import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
|
|
18
|
+
import { getMatching } from '../../utils/key';
|
|
17
19
|
|
|
18
20
|
export interface InLocalStorageOptions {
|
|
19
21
|
prefix?: string
|
|
@@ -30,21 +32,26 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
|
|
|
30
32
|
|
|
31
33
|
// Fallback to InMemoryStorage if LocalStorage API is not available
|
|
32
34
|
if (!isLocalStorageAvailable()) {
|
|
33
|
-
params.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
|
|
35
|
+
params.settings.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
|
|
34
36
|
return InMemoryStorageCSFactory(params);
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
const log = params
|
|
38
|
-
const
|
|
39
|
+
const { settings, settings: { log, scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation } } } = params;
|
|
40
|
+
const matchingKey = getMatching(settings.core.key);
|
|
41
|
+
const keys = new KeyBuilderCS(prefix, matchingKey as string);
|
|
39
42
|
const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
|
|
40
43
|
|
|
44
|
+
const splits = new SplitsCacheInLocal(log, keys, expirationTimestamp, __splitFiltersValidation);
|
|
45
|
+
const segments = new MySegmentsCacheInLocal(log, keys);
|
|
46
|
+
|
|
41
47
|
return {
|
|
42
|
-
splits
|
|
43
|
-
segments
|
|
44
|
-
impressions: new ImpressionsCacheInMemory(
|
|
45
|
-
impressionCounts:
|
|
46
|
-
events: new EventsCacheInMemory(
|
|
47
|
-
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
|
|
48
|
+
splits,
|
|
49
|
+
segments,
|
|
50
|
+
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
51
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
52
|
+
events: new EventsCacheInMemory(eventsQueueSize),
|
|
53
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
54
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
|
|
48
55
|
|
|
49
56
|
destroy() {
|
|
50
57
|
this.splits = new SplitsCacheInMemory();
|
|
@@ -52,6 +59,7 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
|
|
|
52
59
|
this.impressions.clear();
|
|
53
60
|
this.impressionCounts && this.impressionCounts.clear();
|
|
54
61
|
this.events.clear();
|
|
62
|
+
this.uniqueKeys?.clear();
|
|
55
63
|
},
|
|
56
64
|
|
|
57
65
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are customer per key).
|
|
@@ -7,10 +7,10 @@ export class AttributesCacheInMemory {
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Create or update the value for the given attribute
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
11
|
* @param {string} attributeName attribute name
|
|
12
12
|
* @param {Object} attributeValue attribute value
|
|
13
|
-
* @returns {boolean} the attribute was stored
|
|
13
|
+
* @returns {boolean} the attribute was stored
|
|
14
14
|
*/
|
|
15
15
|
setAttribute(attributeName: string, attributeValue: Object): boolean {
|
|
16
16
|
this.attributesCache[attributeName] = attributeValue;
|
|
@@ -19,7 +19,7 @@ export class AttributesCacheInMemory {
|
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Retrieves the value of a given attribute
|
|
22
|
-
*
|
|
22
|
+
*
|
|
23
23
|
* @param {string} attributeName attribute name
|
|
24
24
|
* @returns {Object?} stored attribute value
|
|
25
25
|
*/
|
|
@@ -29,7 +29,7 @@ export class AttributesCacheInMemory {
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Create or update all the given attributes
|
|
32
|
-
*
|
|
32
|
+
*
|
|
33
33
|
* @param {[string, Object]} attributes attributes to create or update
|
|
34
34
|
* @returns {boolean} attributes were stored
|
|
35
35
|
*/
|
|
@@ -40,7 +40,7 @@ export class AttributesCacheInMemory {
|
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Retrieve the full attributes map
|
|
43
|
-
*
|
|
43
|
+
*
|
|
44
44
|
* @returns {Map<string, Object>} stored attributes
|
|
45
45
|
*/
|
|
46
46
|
getAll(): Record<string, Object> {
|
|
@@ -49,7 +49,7 @@ export class AttributesCacheInMemory {
|
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Removes a given attribute from the map
|
|
52
|
-
*
|
|
52
|
+
*
|
|
53
53
|
* @param {string} attributeName attribute to remove
|
|
54
54
|
* @returns {boolean} attribute removed
|
|
55
55
|
*/
|
|
@@ -63,7 +63,7 @@ export class AttributesCacheInMemory {
|
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* Clears all attributes stored in the SDK
|
|
66
|
-
*
|
|
66
|
+
*
|
|
67
67
|
*/
|
|
68
68
|
clear() {
|
|
69
69
|
this.attributesCache = {};
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { truncateTimeFrame } from '../../utils/time';
|
|
2
|
+
import { DEFAULT_CACHE_SIZE } from '../inRedis/constants';
|
|
2
3
|
import { IImpressionCountsCacheSync } from '../types';
|
|
3
4
|
|
|
4
5
|
export class ImpressionCountsCacheInMemory implements IImpressionCountsCacheSync {
|
|
5
|
-
|
|
6
|
+
protected cache: Record<string, number> = {};
|
|
7
|
+
private readonly maxStorage: number;
|
|
8
|
+
protected onFullQueue?: () => void;
|
|
9
|
+
private cacheSize = 0;
|
|
10
|
+
|
|
11
|
+
constructor(impressionCountsCacheSize = DEFAULT_CACHE_SIZE) {
|
|
12
|
+
this.maxStorage = impressionCountsCacheSize;
|
|
13
|
+
}
|
|
6
14
|
|
|
7
15
|
/**
|
|
8
16
|
* Builds key to be stored in the cache with the featureName and the timeFrame truncated.
|
|
@@ -18,6 +26,13 @@ export class ImpressionCountsCacheInMemory implements IImpressionCountsCacheSync
|
|
|
18
26
|
const key = this._makeKey(featureName, timeFrame);
|
|
19
27
|
const currentAmount = this.cache[key];
|
|
20
28
|
this.cache[key] = currentAmount ? currentAmount + amount : amount;
|
|
29
|
+
if (this.onFullQueue) {
|
|
30
|
+
this.cacheSize = this.cacheSize + amount;
|
|
31
|
+
if (this.cacheSize >= this.maxStorage) {
|
|
32
|
+
this.onFullQueue();
|
|
33
|
+
this.cacheSize = 0;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
21
36
|
}
|
|
22
37
|
|
|
23
38
|
|
|
@@ -4,8 +4,9 @@ import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { IStorageFactoryParams, IStorageSync } from '../types';
|
|
6
6
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
7
|
-
import { STORAGE_MEMORY } from '../../utils/constants';
|
|
7
|
+
import { DEBUG, NONE, STORAGE_MEMORY } from '../../utils/constants';
|
|
8
8
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
|
+
import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* InMemory storage factory for standalone server-side SplitFactory
|
|
@@ -13,14 +14,19 @@ import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheI
|
|
|
13
14
|
* @param params parameters required by EventsCacheSync
|
|
14
15
|
*/
|
|
15
16
|
export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageSync {
|
|
17
|
+
const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode } } } = params;
|
|
18
|
+
|
|
19
|
+
const splits = new SplitsCacheInMemory();
|
|
20
|
+
const segments = new SegmentsCacheInMemory();
|
|
16
21
|
|
|
17
22
|
return {
|
|
18
|
-
splits
|
|
19
|
-
segments
|
|
20
|
-
impressions: new ImpressionsCacheInMemory(
|
|
21
|
-
impressionCounts:
|
|
22
|
-
events: new EventsCacheInMemory(
|
|
23
|
-
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
|
|
23
|
+
splits,
|
|
24
|
+
segments,
|
|
25
|
+
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
26
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
27
|
+
events: new EventsCacheInMemory(eventsQueueSize),
|
|
28
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
29
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemory() : undefined,
|
|
24
30
|
|
|
25
31
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
26
32
|
destroy() {
|
|
@@ -29,6 +35,7 @@ export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageS
|
|
|
29
35
|
this.impressions.clear();
|
|
30
36
|
this.impressionCounts && this.impressionCounts.clear();
|
|
31
37
|
this.events.clear();
|
|
38
|
+
this.uniqueKeys?.clear();
|
|
32
39
|
}
|
|
33
40
|
};
|
|
34
41
|
}
|
|
@@ -4,8 +4,9 @@ import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { IStorageSync, IStorageFactoryParams } from '../types';
|
|
6
6
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
7
|
-
import { STORAGE_MEMORY } from '../../utils/constants';
|
|
7
|
+
import { DEBUG, NONE, STORAGE_MEMORY } from '../../utils/constants';
|
|
8
8
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
|
+
import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* InMemory storage factory for standalone client-side SplitFactory
|
|
@@ -13,14 +14,19 @@ import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheI
|
|
|
13
14
|
* @param params parameters required by EventsCacheSync
|
|
14
15
|
*/
|
|
15
16
|
export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorageSync {
|
|
17
|
+
const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode } } } = params;
|
|
18
|
+
|
|
19
|
+
const splits = new SplitsCacheInMemory();
|
|
20
|
+
const segments = new MySegmentsCacheInMemory();
|
|
16
21
|
|
|
17
22
|
return {
|
|
18
|
-
splits
|
|
19
|
-
segments
|
|
20
|
-
impressions: new ImpressionsCacheInMemory(
|
|
21
|
-
impressionCounts:
|
|
22
|
-
events: new EventsCacheInMemory(
|
|
23
|
-
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
|
|
23
|
+
splits,
|
|
24
|
+
segments,
|
|
25
|
+
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
26
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
27
|
+
events: new EventsCacheInMemory(eventsQueueSize),
|
|
28
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
29
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
|
|
24
30
|
|
|
25
31
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
26
32
|
destroy() {
|
|
@@ -29,6 +35,7 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
29
35
|
this.impressions.clear();
|
|
30
36
|
this.impressionCounts && this.impressionCounts.clear();
|
|
31
37
|
this.events.clear();
|
|
38
|
+
this.uniqueKeys?.clear();
|
|
32
39
|
},
|
|
33
40
|
|
|
34
41
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are unique per key)
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { ImpressionDataType, EventDataType, LastSync, HttpErrors, HttpLatencies, StreamingEvent, Method, OperationType, MethodExceptions, MethodLatencies } from '../../sync/submitters/types';
|
|
2
|
-
import { LOCALHOST_MODE } from '../../utils/constants';
|
|
1
|
+
import { ImpressionDataType, EventDataType, LastSync, HttpErrors, HttpLatencies, StreamingEvent, Method, OperationType, MethodExceptions, MethodLatencies, TelemetryUsageStatsPayload } from '../../sync/submitters/types';
|
|
2
|
+
import { DEDUPED, DROPPED, LOCALHOST_MODE, QUEUED } from '../../utils/constants';
|
|
3
3
|
import { findLatencyIndex } from '../findLatencyIndex';
|
|
4
|
-
import { IStorageFactoryParams, ITelemetryCacheSync } from '../types';
|
|
4
|
+
import { ISegmentsCacheSync, ISplitsCacheSync, IStorageFactoryParams, ITelemetryCacheSync } from '../types';
|
|
5
5
|
|
|
6
6
|
const MAX_STREAMING_EVENTS = 20;
|
|
7
7
|
const MAX_TAGS = 10;
|
|
8
8
|
export const MAX_LATENCY_BUCKET_COUNT = 23;
|
|
9
9
|
|
|
10
10
|
export function newBuckets() {
|
|
11
|
-
|
|
11
|
+
// MAX_LATENCY_BUCKET_COUNT (length) is 23
|
|
12
|
+
// Not using Array.fill for old browsers compatibility
|
|
13
|
+
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
const ACCEPTANCE_RANGE = 0.001;
|
|
@@ -17,12 +19,48 @@ const ACCEPTANCE_RANGE = 0.001;
|
|
|
17
19
|
* Record telemetry if mode is not localhost.
|
|
18
20
|
* All factory instances track telemetry on server-side, and 0.1% on client-side.
|
|
19
21
|
*/
|
|
20
|
-
export function shouldRecordTelemetry(
|
|
21
|
-
return
|
|
22
|
+
export function shouldRecordTelemetry({ settings }: IStorageFactoryParams) {
|
|
23
|
+
return settings.mode !== LOCALHOST_MODE && (settings.core.key === undefined || Math.random() <= ACCEPTANCE_RANGE);
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
25
27
|
|
|
28
|
+
constructor(private splits?: ISplitsCacheSync, private segments?: ISegmentsCacheSync) { }
|
|
29
|
+
|
|
30
|
+
// isEmpty flag
|
|
31
|
+
private e = true;
|
|
32
|
+
|
|
33
|
+
isEmpty() { return this.e; }
|
|
34
|
+
|
|
35
|
+
clear() { /* no-op */ }
|
|
36
|
+
|
|
37
|
+
pop(): TelemetryUsageStatsPayload {
|
|
38
|
+
this.e = true;
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
lS: this.getLastSynchronization(),
|
|
42
|
+
mL: this.popLatencies(),
|
|
43
|
+
mE: this.popExceptions(),
|
|
44
|
+
hE: this.popHttpErrors(),
|
|
45
|
+
hL: this.popHttpLatencies(),
|
|
46
|
+
tR: this.popTokenRefreshes(),
|
|
47
|
+
aR: this.popAuthRejections(),
|
|
48
|
+
iQ: this.getImpressionStats(QUEUED),
|
|
49
|
+
iDe: this.getImpressionStats(DEDUPED),
|
|
50
|
+
iDr: this.getImpressionStats(DROPPED),
|
|
51
|
+
spC: this.splits && this.splits.getSplitNames().length,
|
|
52
|
+
seC: this.segments && this.segments.getRegisteredSegments().length,
|
|
53
|
+
skC: this.segments && this.segments.getKeysCount(),
|
|
54
|
+
sL: this.getSessionLength(),
|
|
55
|
+
eQ: this.getEventStats(QUEUED),
|
|
56
|
+
eD: this.getEventStats(DROPPED),
|
|
57
|
+
sE: this.popStreamingEvents(),
|
|
58
|
+
t: this.popTags(),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Config stats */
|
|
63
|
+
|
|
26
64
|
private timeUntilReady?: number;
|
|
27
65
|
|
|
28
66
|
getTimeUntilReady() {
|
|
@@ -53,6 +91,8 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
53
91
|
this.notReadyUsage++;
|
|
54
92
|
}
|
|
55
93
|
|
|
94
|
+
/** Usage stats */
|
|
95
|
+
|
|
56
96
|
private impressionStats = [0, 0, 0];
|
|
57
97
|
|
|
58
98
|
getImpressionStats(type: ImpressionDataType) {
|
|
@@ -61,6 +101,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
61
101
|
|
|
62
102
|
recordImpressionStats(type: ImpressionDataType, count: number) {
|
|
63
103
|
this.impressionStats[type] += count;
|
|
104
|
+
this.e = false;
|
|
64
105
|
}
|
|
65
106
|
|
|
66
107
|
private eventStats = [0, 0];
|
|
@@ -71,9 +112,9 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
71
112
|
|
|
72
113
|
recordEventStats(type: EventDataType, count: number) {
|
|
73
114
|
this.eventStats[type] += count;
|
|
115
|
+
this.e = false;
|
|
74
116
|
}
|
|
75
117
|
|
|
76
|
-
// @ts-expect-error
|
|
77
118
|
private lastSync: LastSync = {};
|
|
78
119
|
|
|
79
120
|
getLastSynchronization() {
|
|
@@ -82,40 +123,35 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
82
123
|
|
|
83
124
|
recordSuccessfulSync(resource: OperationType, timeMs: number) {
|
|
84
125
|
this.lastSync[resource] = timeMs;
|
|
126
|
+
this.e = false;
|
|
85
127
|
}
|
|
86
128
|
|
|
87
|
-
// @ts-expect-error
|
|
88
129
|
private httpErrors: HttpErrors = {};
|
|
89
130
|
|
|
90
131
|
popHttpErrors() {
|
|
91
|
-
const result = this.httpErrors;
|
|
132
|
+
const result = this.httpErrors;
|
|
92
133
|
this.httpErrors = {};
|
|
93
134
|
return result;
|
|
94
135
|
}
|
|
95
136
|
|
|
96
137
|
recordHttpError(resource: OperationType, status: number) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
} else {
|
|
101
|
-
this.httpErrors[resource][status]++;
|
|
102
|
-
}
|
|
138
|
+
const statusErrors = (this.httpErrors[resource] = this.httpErrors[resource] || {});
|
|
139
|
+
statusErrors[status] = (statusErrors[status] || 0) + 1;
|
|
140
|
+
this.e = false;
|
|
103
141
|
}
|
|
104
142
|
|
|
105
|
-
// @ts-expect-error
|
|
106
143
|
private httpLatencies: HttpLatencies = {};
|
|
107
144
|
|
|
108
145
|
popHttpLatencies() {
|
|
109
|
-
const result = this.httpLatencies;
|
|
146
|
+
const result = this.httpLatencies;
|
|
110
147
|
this.httpLatencies = {};
|
|
111
148
|
return result;
|
|
112
149
|
}
|
|
113
150
|
|
|
114
151
|
recordHttpLatency(resource: OperationType, latencyMs: number) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
this.httpLatencies[resource][findLatencyIndex(latencyMs)]++;
|
|
152
|
+
const latencyBuckets = (this.httpLatencies[resource] = this.httpLatencies[resource] || newBuckets());
|
|
153
|
+
latencyBuckets[findLatencyIndex(latencyMs)]++;
|
|
154
|
+
this.e = false;
|
|
119
155
|
}
|
|
120
156
|
|
|
121
157
|
private authRejections = 0;
|
|
@@ -128,6 +164,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
128
164
|
|
|
129
165
|
recordAuthRejections() {
|
|
130
166
|
this.authRejections++;
|
|
167
|
+
this.e = false;
|
|
131
168
|
}
|
|
132
169
|
|
|
133
170
|
private tokenRefreshes = 0;
|
|
@@ -140,6 +177,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
140
177
|
|
|
141
178
|
recordTokenRefreshes() {
|
|
142
179
|
this.tokenRefreshes++;
|
|
180
|
+
this.e = false;
|
|
143
181
|
}
|
|
144
182
|
|
|
145
183
|
private streamingEvents: StreamingEvent[] = []
|
|
@@ -152,6 +190,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
152
190
|
if (this.streamingEvents.length < MAX_STREAMING_EVENTS) {
|
|
153
191
|
this.streamingEvents.push(streamingEvent);
|
|
154
192
|
}
|
|
193
|
+
this.e = false;
|
|
155
194
|
}
|
|
156
195
|
|
|
157
196
|
private tags: string[] = [];
|
|
@@ -164,6 +203,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
164
203
|
if (this.tags.length < MAX_TAGS) {
|
|
165
204
|
this.tags.push(tag);
|
|
166
205
|
}
|
|
206
|
+
this.e = false;
|
|
167
207
|
}
|
|
168
208
|
|
|
169
209
|
private sessionLength?: number;
|
|
@@ -174,39 +214,34 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
174
214
|
|
|
175
215
|
recordSessionLength(ms: number) {
|
|
176
216
|
this.sessionLength = ms;
|
|
217
|
+
this.e = false;
|
|
177
218
|
}
|
|
178
219
|
|
|
179
|
-
// @ts-expect-error
|
|
180
220
|
private exceptions: MethodExceptions = {};
|
|
181
221
|
|
|
182
222
|
popExceptions() {
|
|
183
|
-
const result = this.exceptions;
|
|
223
|
+
const result = this.exceptions;
|
|
184
224
|
this.exceptions = {};
|
|
185
225
|
return result;
|
|
186
226
|
}
|
|
187
227
|
|
|
188
228
|
recordException(method: Method) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
} else {
|
|
192
|
-
this.exceptions[method]++;
|
|
193
|
-
}
|
|
229
|
+
this.exceptions[method] = (this.exceptions[method] || 0) + 1;
|
|
230
|
+
this.e = false;
|
|
194
231
|
}
|
|
195
232
|
|
|
196
|
-
// @ts-expect-error
|
|
197
233
|
private latencies: MethodLatencies = {};
|
|
198
234
|
|
|
199
235
|
popLatencies() {
|
|
200
|
-
const result = this.latencies;
|
|
236
|
+
const result = this.latencies;
|
|
201
237
|
this.latencies = {};
|
|
202
238
|
return result;
|
|
203
239
|
}
|
|
204
240
|
|
|
205
241
|
recordLatency(method: Method, latencyMs: number) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
this.latencies[method][findLatencyIndex(latencyMs)]++;
|
|
242
|
+
const latencyBuckets = (this.latencies[method] = this.latencies[method] || newBuckets());
|
|
243
|
+
latencyBuckets[findLatencyIndex(latencyMs)]++;
|
|
244
|
+
this.e = false;
|
|
210
245
|
}
|
|
211
246
|
|
|
212
247
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { IUniqueKeysCacheBase } from '../types';
|
|
2
|
+
import { ISet, setToArray, _Set } from '../../utils/lang/sets';
|
|
3
|
+
import { UniqueKeysPayloadSs } from '../../sync/submitters/types';
|
|
4
|
+
import { DEFAULT_CACHE_SIZE } from '../inRedis/constants';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Converts `uniqueKeys` data from cache into request payload for SS.
|
|
8
|
+
*/
|
|
9
|
+
export function fromUniqueKeysCollector(uniqueKeys: { [featureName: string]: ISet<string> }): UniqueKeysPayloadSs {
|
|
10
|
+
const payload = [];
|
|
11
|
+
const featureNames = Object.keys(uniqueKeys);
|
|
12
|
+
for (let i = 0; i < featureNames.length; i++) {
|
|
13
|
+
const featureName = featureNames[i];
|
|
14
|
+
const userKeys = setToArray(uniqueKeys[featureName]);
|
|
15
|
+
const uniqueKeysPayload = {
|
|
16
|
+
f: featureName,
|
|
17
|
+
ks: userKeys
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
payload.push(uniqueKeysPayload);
|
|
21
|
+
}
|
|
22
|
+
return { keys: payload };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class UniqueKeysCacheInMemory implements IUniqueKeysCacheBase {
|
|
26
|
+
|
|
27
|
+
protected onFullQueue?: () => void;
|
|
28
|
+
private readonly maxStorage: number;
|
|
29
|
+
private uniqueTrackerSize = 0;
|
|
30
|
+
protected uniqueKeysTracker: { [featureName: string]: ISet<string> };
|
|
31
|
+
|
|
32
|
+
constructor(uniqueKeysQueueSize = DEFAULT_CACHE_SIZE) {
|
|
33
|
+
this.maxStorage = uniqueKeysQueueSize;
|
|
34
|
+
this.uniqueKeysTracker = {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setOnFullQueueCb(cb: () => void) {
|
|
38
|
+
this.onFullQueue = cb;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Store unique keys per feature.
|
|
43
|
+
*/
|
|
44
|
+
track(userKey: string, featureName: string) {
|
|
45
|
+
if (!this.uniqueKeysTracker[featureName]) this.uniqueKeysTracker[featureName] = new _Set();
|
|
46
|
+
const tracker = this.uniqueKeysTracker[featureName];
|
|
47
|
+
if (!tracker.has(userKey)) {
|
|
48
|
+
tracker.add(userKey);
|
|
49
|
+
this.uniqueTrackerSize++;
|
|
50
|
+
}
|
|
51
|
+
if (this.uniqueTrackerSize >= this.maxStorage && this.onFullQueue) {
|
|
52
|
+
this.uniqueTrackerSize = 0;
|
|
53
|
+
this.onFullQueue();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Clear the data stored on the cache.
|
|
59
|
+
*/
|
|
60
|
+
clear() {
|
|
61
|
+
this.uniqueKeysTracker = {};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Pop the collected data, used as payload for posting.
|
|
66
|
+
*/
|
|
67
|
+
pop() {
|
|
68
|
+
const data = this.uniqueKeysTracker;
|
|
69
|
+
this.uniqueKeysTracker = {};
|
|
70
|
+
return fromUniqueKeysCollector(data);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Check if the cache is empty.
|
|
75
|
+
*/
|
|
76
|
+
isEmpty() {
|
|
77
|
+
return Object.keys(this.uniqueKeysTracker).length === 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
}
|