@splitsoftware/splitio-commons 1.6.2-rc.9 → 1.7.1
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 +6 -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 +9 -3
- 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 +9 -3
- 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 +7 -3
- 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
|
@@ -200,7 +200,6 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
200
200
|
};
|
|
201
201
|
/**
|
|
202
202
|
* Clean Splits cache if its `lastUpdated` timestamp is older than the given `expirationTimestamp`,
|
|
203
|
-
* Clean operation (clear) also updates `lastUpdated` timestamp with current time.
|
|
204
203
|
*
|
|
205
204
|
* @param {number | undefined} expirationTimestamp if the value is not a number, data will not be cleaned
|
|
206
205
|
*/
|
|
@@ -11,8 +11,10 @@ import { SplitsCacheInMemory } from '../inMemory/SplitsCacheInMemory';
|
|
|
11
11
|
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
|
|
12
12
|
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
|
|
13
13
|
import { LOG_PREFIX } from './constants';
|
|
14
|
-
import { STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
14
|
+
import { DEBUG, NONE, STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
15
15
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
|
|
16
|
+
import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
|
|
17
|
+
import { getMatching } from '../../utils/key';
|
|
16
18
|
/**
|
|
17
19
|
* InLocal storage factory for standalone client-side SplitFactory
|
|
18
20
|
*/
|
|
@@ -22,25 +24,31 @@ export function InLocalStorage(options) {
|
|
|
22
24
|
function InLocalStorageCSFactory(params) {
|
|
23
25
|
// Fallback to InMemoryStorage if LocalStorage API is not available
|
|
24
26
|
if (!isLocalStorageAvailable()) {
|
|
25
|
-
params.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
|
|
27
|
+
params.settings.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
|
|
26
28
|
return InMemoryStorageCSFactory(params);
|
|
27
29
|
}
|
|
28
|
-
var
|
|
29
|
-
var
|
|
30
|
+
var settings = params.settings, _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, _c = _a.sync, impressionsMode = _c.impressionsMode, __splitFiltersValidation = _c.__splitFiltersValidation;
|
|
31
|
+
var matchingKey = getMatching(settings.core.key);
|
|
32
|
+
var keys = new KeyBuilderCS(prefix, matchingKey);
|
|
30
33
|
var expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
|
|
34
|
+
var splits = new SplitsCacheInLocal(log, keys, expirationTimestamp, __splitFiltersValidation);
|
|
35
|
+
var segments = new MySegmentsCacheInLocal(log, keys);
|
|
31
36
|
return {
|
|
32
|
-
splits:
|
|
33
|
-
segments:
|
|
34
|
-
impressions: new ImpressionsCacheInMemory(
|
|
35
|
-
impressionCounts:
|
|
36
|
-
events: new EventsCacheInMemory(
|
|
37
|
-
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
|
|
37
|
+
splits: splits,
|
|
38
|
+
segments: segments,
|
|
39
|
+
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
40
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
41
|
+
events: new EventsCacheInMemory(eventsQueueSize),
|
|
42
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
43
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
|
|
38
44
|
destroy: function () {
|
|
45
|
+
var _a;
|
|
39
46
|
this.splits = new SplitsCacheInMemory();
|
|
40
47
|
this.segments = new MySegmentsCacheInMemory();
|
|
41
48
|
this.impressions.clear();
|
|
42
49
|
this.impressionCounts && this.impressionCounts.clear();
|
|
43
50
|
this.events.clear();
|
|
51
|
+
(_a = this.uniqueKeys) === null || _a === void 0 ? void 0 : _a.clear();
|
|
44
52
|
},
|
|
45
53
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are customer per key).
|
|
46
54
|
shared: function (matchingKey) {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { truncateTimeFrame } from '../../utils/time';
|
|
2
|
+
import { DEFAULT_CACHE_SIZE } from '../inRedis/constants';
|
|
2
3
|
var ImpressionCountsCacheInMemory = /** @class */ (function () {
|
|
3
|
-
function ImpressionCountsCacheInMemory() {
|
|
4
|
+
function ImpressionCountsCacheInMemory(impressionCountsCacheSize) {
|
|
5
|
+
if (impressionCountsCacheSize === void 0) { impressionCountsCacheSize = DEFAULT_CACHE_SIZE; }
|
|
4
6
|
this.cache = {};
|
|
7
|
+
this.cacheSize = 0;
|
|
8
|
+
this.maxStorage = impressionCountsCacheSize;
|
|
5
9
|
}
|
|
6
10
|
/**
|
|
7
11
|
* Builds key to be stored in the cache with the featureName and the timeFrame truncated.
|
|
@@ -16,6 +20,13 @@ var ImpressionCountsCacheInMemory = /** @class */ (function () {
|
|
|
16
20
|
var key = this._makeKey(featureName, timeFrame);
|
|
17
21
|
var currentAmount = this.cache[key];
|
|
18
22
|
this.cache[key] = currentAmount ? currentAmount + amount : amount;
|
|
23
|
+
if (this.onFullQueue) {
|
|
24
|
+
this.cacheSize = this.cacheSize + amount;
|
|
25
|
+
if (this.cacheSize >= this.maxStorage) {
|
|
26
|
+
this.onFullQueue();
|
|
27
|
+
this.cacheSize = 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
19
30
|
};
|
|
20
31
|
/**
|
|
21
32
|
* Pop the collected data, used as payload for posting.
|
|
@@ -3,28 +3,35 @@ import { SegmentsCacheInMemory } from './SegmentsCacheInMemory';
|
|
|
3
3
|
import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
6
|
-
import { STORAGE_MEMORY } from '../../utils/constants';
|
|
6
|
+
import { DEBUG, NONE, STORAGE_MEMORY } from '../../utils/constants';
|
|
7
7
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
8
|
+
import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
|
|
8
9
|
/**
|
|
9
10
|
* InMemory storage factory for standalone server-side SplitFactory
|
|
10
11
|
*
|
|
11
12
|
* @param params parameters required by EventsCacheSync
|
|
12
13
|
*/
|
|
13
14
|
export function InMemoryStorageFactory(params) {
|
|
15
|
+
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, impressionsMode = _a.sync.impressionsMode;
|
|
16
|
+
var splits = new SplitsCacheInMemory();
|
|
17
|
+
var segments = new SegmentsCacheInMemory();
|
|
14
18
|
return {
|
|
15
|
-
splits:
|
|
16
|
-
segments:
|
|
17
|
-
impressions: new ImpressionsCacheInMemory(
|
|
18
|
-
impressionCounts:
|
|
19
|
-
events: new EventsCacheInMemory(
|
|
20
|
-
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
|
|
19
|
+
splits: splits,
|
|
20
|
+
segments: segments,
|
|
21
|
+
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
22
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
23
|
+
events: new EventsCacheInMemory(eventsQueueSize),
|
|
24
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
25
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemory() : undefined,
|
|
21
26
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
22
27
|
destroy: function () {
|
|
28
|
+
var _a;
|
|
23
29
|
this.splits.clear();
|
|
24
30
|
this.segments.clear();
|
|
25
31
|
this.impressions.clear();
|
|
26
32
|
this.impressionCounts && this.impressionCounts.clear();
|
|
27
33
|
this.events.clear();
|
|
34
|
+
(_a = this.uniqueKeys) === null || _a === void 0 ? void 0 : _a.clear();
|
|
28
35
|
}
|
|
29
36
|
};
|
|
30
37
|
}
|
|
@@ -3,28 +3,35 @@ import { MySegmentsCacheInMemory } from './MySegmentsCacheInMemory';
|
|
|
3
3
|
import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
6
|
-
import { STORAGE_MEMORY } from '../../utils/constants';
|
|
6
|
+
import { DEBUG, NONE, STORAGE_MEMORY } from '../../utils/constants';
|
|
7
7
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
8
|
+
import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
8
9
|
/**
|
|
9
10
|
* InMemory storage factory for standalone client-side SplitFactory
|
|
10
11
|
*
|
|
11
12
|
* @param params parameters required by EventsCacheSync
|
|
12
13
|
*/
|
|
13
14
|
export function InMemoryStorageCSFactory(params) {
|
|
15
|
+
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, impressionsMode = _a.sync.impressionsMode;
|
|
16
|
+
var splits = new SplitsCacheInMemory();
|
|
17
|
+
var segments = new MySegmentsCacheInMemory();
|
|
14
18
|
return {
|
|
15
|
-
splits:
|
|
16
|
-
segments:
|
|
17
|
-
impressions: new ImpressionsCacheInMemory(
|
|
18
|
-
impressionCounts:
|
|
19
|
-
events: new EventsCacheInMemory(
|
|
20
|
-
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
|
|
19
|
+
splits: splits,
|
|
20
|
+
segments: segments,
|
|
21
|
+
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
22
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
23
|
+
events: new EventsCacheInMemory(eventsQueueSize),
|
|
24
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
25
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
|
|
21
26
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
22
27
|
destroy: function () {
|
|
28
|
+
var _a;
|
|
23
29
|
this.splits.clear();
|
|
24
30
|
this.segments.clear();
|
|
25
31
|
this.impressions.clear();
|
|
26
32
|
this.impressionCounts && this.impressionCounts.clear();
|
|
27
33
|
this.events.clear();
|
|
34
|
+
(_a = this.uniqueKeys) === null || _a === void 0 ? void 0 : _a.clear();
|
|
28
35
|
},
|
|
29
36
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are unique per key)
|
|
30
37
|
shared: function () {
|
|
@@ -1,39 +1,67 @@
|
|
|
1
|
-
import { LOCALHOST_MODE } from '../../utils/constants';
|
|
1
|
+
import { DEDUPED, DROPPED, LOCALHOST_MODE, QUEUED } from '../../utils/constants';
|
|
2
2
|
import { findLatencyIndex } from '../findLatencyIndex';
|
|
3
3
|
var MAX_STREAMING_EVENTS = 20;
|
|
4
4
|
var MAX_TAGS = 10;
|
|
5
5
|
export var MAX_LATENCY_BUCKET_COUNT = 23;
|
|
6
6
|
export function newBuckets() {
|
|
7
|
-
|
|
7
|
+
// MAX_LATENCY_BUCKET_COUNT (length) is 23
|
|
8
|
+
// Not using Array.fill for old browsers compatibility
|
|
9
|
+
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
8
10
|
}
|
|
9
11
|
var ACCEPTANCE_RANGE = 0.001;
|
|
10
12
|
/**
|
|
11
13
|
* Record telemetry if mode is not localhost.
|
|
12
14
|
* All factory instances track telemetry on server-side, and 0.1% on client-side.
|
|
13
15
|
*/
|
|
14
|
-
export function shouldRecordTelemetry(
|
|
15
|
-
|
|
16
|
+
export function shouldRecordTelemetry(_a) {
|
|
17
|
+
var settings = _a.settings;
|
|
18
|
+
return settings.mode !== LOCALHOST_MODE && (settings.core.key === undefined || Math.random() <= ACCEPTANCE_RANGE);
|
|
16
19
|
}
|
|
17
20
|
var TelemetryCacheInMemory = /** @class */ (function () {
|
|
18
|
-
function TelemetryCacheInMemory() {
|
|
21
|
+
function TelemetryCacheInMemory(splits, segments) {
|
|
22
|
+
this.splits = splits;
|
|
23
|
+
this.segments = segments;
|
|
24
|
+
// isEmpty flag
|
|
25
|
+
this.e = true;
|
|
19
26
|
this.notReadyUsage = 0;
|
|
27
|
+
/** Usage stats */
|
|
20
28
|
this.impressionStats = [0, 0, 0];
|
|
21
29
|
this.eventStats = [0, 0];
|
|
22
|
-
// @ts-expect-error
|
|
23
30
|
this.lastSync = {};
|
|
24
|
-
// @ts-expect-error
|
|
25
31
|
this.httpErrors = {};
|
|
26
|
-
// @ts-expect-error
|
|
27
32
|
this.httpLatencies = {};
|
|
28
33
|
this.authRejections = 0;
|
|
29
34
|
this.tokenRefreshes = 0;
|
|
30
35
|
this.streamingEvents = [];
|
|
31
36
|
this.tags = [];
|
|
32
|
-
// @ts-expect-error
|
|
33
37
|
this.exceptions = {};
|
|
34
|
-
// @ts-expect-error
|
|
35
38
|
this.latencies = {};
|
|
36
39
|
}
|
|
40
|
+
TelemetryCacheInMemory.prototype.isEmpty = function () { return this.e; };
|
|
41
|
+
TelemetryCacheInMemory.prototype.clear = function () { };
|
|
42
|
+
TelemetryCacheInMemory.prototype.pop = function () {
|
|
43
|
+
this.e = true;
|
|
44
|
+
return {
|
|
45
|
+
lS: this.getLastSynchronization(),
|
|
46
|
+
mL: this.popLatencies(),
|
|
47
|
+
mE: this.popExceptions(),
|
|
48
|
+
hE: this.popHttpErrors(),
|
|
49
|
+
hL: this.popHttpLatencies(),
|
|
50
|
+
tR: this.popTokenRefreshes(),
|
|
51
|
+
aR: this.popAuthRejections(),
|
|
52
|
+
iQ: this.getImpressionStats(QUEUED),
|
|
53
|
+
iDe: this.getImpressionStats(DEDUPED),
|
|
54
|
+
iDr: this.getImpressionStats(DROPPED),
|
|
55
|
+
spC: this.splits && this.splits.getSplitNames().length,
|
|
56
|
+
seC: this.segments && this.segments.getRegisteredSegments().length,
|
|
57
|
+
skC: this.segments && this.segments.getKeysCount(),
|
|
58
|
+
sL: this.getSessionLength(),
|
|
59
|
+
eQ: this.getEventStats(QUEUED),
|
|
60
|
+
eD: this.getEventStats(DROPPED),
|
|
61
|
+
sE: this.popStreamingEvents(),
|
|
62
|
+
t: this.popTags(),
|
|
63
|
+
};
|
|
64
|
+
};
|
|
37
65
|
TelemetryCacheInMemory.prototype.getTimeUntilReady = function () {
|
|
38
66
|
return this.timeUntilReady;
|
|
39
67
|
};
|
|
@@ -57,44 +85,41 @@ var TelemetryCacheInMemory = /** @class */ (function () {
|
|
|
57
85
|
};
|
|
58
86
|
TelemetryCacheInMemory.prototype.recordImpressionStats = function (type, count) {
|
|
59
87
|
this.impressionStats[type] += count;
|
|
88
|
+
this.e = false;
|
|
60
89
|
};
|
|
61
90
|
TelemetryCacheInMemory.prototype.getEventStats = function (type) {
|
|
62
91
|
return this.eventStats[type];
|
|
63
92
|
};
|
|
64
93
|
TelemetryCacheInMemory.prototype.recordEventStats = function (type, count) {
|
|
65
94
|
this.eventStats[type] += count;
|
|
95
|
+
this.e = false;
|
|
66
96
|
};
|
|
67
97
|
TelemetryCacheInMemory.prototype.getLastSynchronization = function () {
|
|
68
98
|
return this.lastSync;
|
|
69
99
|
};
|
|
70
100
|
TelemetryCacheInMemory.prototype.recordSuccessfulSync = function (resource, timeMs) {
|
|
71
101
|
this.lastSync[resource] = timeMs;
|
|
102
|
+
this.e = false;
|
|
72
103
|
};
|
|
73
104
|
TelemetryCacheInMemory.prototype.popHttpErrors = function () {
|
|
74
|
-
var result = this.httpErrors;
|
|
105
|
+
var result = this.httpErrors;
|
|
75
106
|
this.httpErrors = {};
|
|
76
107
|
return result;
|
|
77
108
|
};
|
|
78
109
|
TelemetryCacheInMemory.prototype.recordHttpError = function (resource, status) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
this.httpErrors[resource][status] = 1;
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
this.httpErrors[resource][status]++;
|
|
86
|
-
}
|
|
110
|
+
var statusErrors = (this.httpErrors[resource] = this.httpErrors[resource] || {});
|
|
111
|
+
statusErrors[status] = (statusErrors[status] || 0) + 1;
|
|
112
|
+
this.e = false;
|
|
87
113
|
};
|
|
88
114
|
TelemetryCacheInMemory.prototype.popHttpLatencies = function () {
|
|
89
|
-
var result = this.httpLatencies;
|
|
115
|
+
var result = this.httpLatencies;
|
|
90
116
|
this.httpLatencies = {};
|
|
91
117
|
return result;
|
|
92
118
|
};
|
|
93
119
|
TelemetryCacheInMemory.prototype.recordHttpLatency = function (resource, latencyMs) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
this.httpLatencies[resource][findLatencyIndex(latencyMs)]++;
|
|
120
|
+
var latencyBuckets = (this.httpLatencies[resource] = this.httpLatencies[resource] || newBuckets());
|
|
121
|
+
latencyBuckets[findLatencyIndex(latencyMs)]++;
|
|
122
|
+
this.e = false;
|
|
98
123
|
};
|
|
99
124
|
TelemetryCacheInMemory.prototype.popAuthRejections = function () {
|
|
100
125
|
var result = this.authRejections;
|
|
@@ -103,6 +128,7 @@ var TelemetryCacheInMemory = /** @class */ (function () {
|
|
|
103
128
|
};
|
|
104
129
|
TelemetryCacheInMemory.prototype.recordAuthRejections = function () {
|
|
105
130
|
this.authRejections++;
|
|
131
|
+
this.e = false;
|
|
106
132
|
};
|
|
107
133
|
TelemetryCacheInMemory.prototype.popTokenRefreshes = function () {
|
|
108
134
|
var result = this.tokenRefreshes;
|
|
@@ -111,6 +137,7 @@ var TelemetryCacheInMemory = /** @class */ (function () {
|
|
|
111
137
|
};
|
|
112
138
|
TelemetryCacheInMemory.prototype.recordTokenRefreshes = function () {
|
|
113
139
|
this.tokenRefreshes++;
|
|
140
|
+
this.e = false;
|
|
114
141
|
};
|
|
115
142
|
TelemetryCacheInMemory.prototype.popStreamingEvents = function () {
|
|
116
143
|
return this.streamingEvents.splice(0);
|
|
@@ -119,6 +146,7 @@ var TelemetryCacheInMemory = /** @class */ (function () {
|
|
|
119
146
|
if (this.streamingEvents.length < MAX_STREAMING_EVENTS) {
|
|
120
147
|
this.streamingEvents.push(streamingEvent);
|
|
121
148
|
}
|
|
149
|
+
this.e = false;
|
|
122
150
|
};
|
|
123
151
|
TelemetryCacheInMemory.prototype.popTags = function () {
|
|
124
152
|
return this.tags.splice(0);
|
|
@@ -127,36 +155,33 @@ var TelemetryCacheInMemory = /** @class */ (function () {
|
|
|
127
155
|
if (this.tags.length < MAX_TAGS) {
|
|
128
156
|
this.tags.push(tag);
|
|
129
157
|
}
|
|
158
|
+
this.e = false;
|
|
130
159
|
};
|
|
131
160
|
TelemetryCacheInMemory.prototype.getSessionLength = function () {
|
|
132
161
|
return this.sessionLength;
|
|
133
162
|
};
|
|
134
163
|
TelemetryCacheInMemory.prototype.recordSessionLength = function (ms) {
|
|
135
164
|
this.sessionLength = ms;
|
|
165
|
+
this.e = false;
|
|
136
166
|
};
|
|
137
167
|
TelemetryCacheInMemory.prototype.popExceptions = function () {
|
|
138
|
-
var result = this.exceptions;
|
|
168
|
+
var result = this.exceptions;
|
|
139
169
|
this.exceptions = {};
|
|
140
170
|
return result;
|
|
141
171
|
};
|
|
142
172
|
TelemetryCacheInMemory.prototype.recordException = function (method) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
this.exceptions[method]++;
|
|
148
|
-
}
|
|
173
|
+
this.exceptions[method] = (this.exceptions[method] || 0) + 1;
|
|
174
|
+
this.e = false;
|
|
149
175
|
};
|
|
150
176
|
TelemetryCacheInMemory.prototype.popLatencies = function () {
|
|
151
|
-
var result = this.latencies;
|
|
177
|
+
var result = this.latencies;
|
|
152
178
|
this.latencies = {};
|
|
153
179
|
return result;
|
|
154
180
|
};
|
|
155
181
|
TelemetryCacheInMemory.prototype.recordLatency = function (method, latencyMs) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.latencies[method][findLatencyIndex(latencyMs)]++;
|
|
182
|
+
var latencyBuckets = (this.latencies[method] = this.latencies[method] || newBuckets());
|
|
183
|
+
latencyBuckets[findLatencyIndex(latencyMs)]++;
|
|
184
|
+
this.e = false;
|
|
160
185
|
};
|
|
161
186
|
return TelemetryCacheInMemory;
|
|
162
187
|
}());
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { setToArray, _Set } from '../../utils/lang/sets';
|
|
2
|
+
import { DEFAULT_CACHE_SIZE } from '../inRedis/constants';
|
|
3
|
+
/**
|
|
4
|
+
* Converts `uniqueKeys` data from cache into request payload for SS.
|
|
5
|
+
*/
|
|
6
|
+
export function fromUniqueKeysCollector(uniqueKeys) {
|
|
7
|
+
var payload = [];
|
|
8
|
+
var featureNames = Object.keys(uniqueKeys);
|
|
9
|
+
for (var i = 0; i < featureNames.length; i++) {
|
|
10
|
+
var featureName = featureNames[i];
|
|
11
|
+
var userKeys = setToArray(uniqueKeys[featureName]);
|
|
12
|
+
var uniqueKeysPayload = {
|
|
13
|
+
f: featureName,
|
|
14
|
+
ks: userKeys
|
|
15
|
+
};
|
|
16
|
+
payload.push(uniqueKeysPayload);
|
|
17
|
+
}
|
|
18
|
+
return { keys: payload };
|
|
19
|
+
}
|
|
20
|
+
var UniqueKeysCacheInMemory = /** @class */ (function () {
|
|
21
|
+
function UniqueKeysCacheInMemory(uniqueKeysQueueSize) {
|
|
22
|
+
if (uniqueKeysQueueSize === void 0) { uniqueKeysQueueSize = DEFAULT_CACHE_SIZE; }
|
|
23
|
+
this.uniqueTrackerSize = 0;
|
|
24
|
+
this.maxStorage = uniqueKeysQueueSize;
|
|
25
|
+
this.uniqueKeysTracker = {};
|
|
26
|
+
}
|
|
27
|
+
UniqueKeysCacheInMemory.prototype.setOnFullQueueCb = function (cb) {
|
|
28
|
+
this.onFullQueue = cb;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Store unique keys per feature.
|
|
32
|
+
*/
|
|
33
|
+
UniqueKeysCacheInMemory.prototype.track = function (userKey, featureName) {
|
|
34
|
+
if (!this.uniqueKeysTracker[featureName])
|
|
35
|
+
this.uniqueKeysTracker[featureName] = new _Set();
|
|
36
|
+
var tracker = this.uniqueKeysTracker[featureName];
|
|
37
|
+
if (!tracker.has(userKey)) {
|
|
38
|
+
tracker.add(userKey);
|
|
39
|
+
this.uniqueTrackerSize++;
|
|
40
|
+
}
|
|
41
|
+
if (this.uniqueTrackerSize >= this.maxStorage && this.onFullQueue) {
|
|
42
|
+
this.uniqueTrackerSize = 0;
|
|
43
|
+
this.onFullQueue();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Clear the data stored on the cache.
|
|
48
|
+
*/
|
|
49
|
+
UniqueKeysCacheInMemory.prototype.clear = function () {
|
|
50
|
+
this.uniqueKeysTracker = {};
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Pop the collected data, used as payload for posting.
|
|
54
|
+
*/
|
|
55
|
+
UniqueKeysCacheInMemory.prototype.pop = function () {
|
|
56
|
+
var data = this.uniqueKeysTracker;
|
|
57
|
+
this.uniqueKeysTracker = {};
|
|
58
|
+
return fromUniqueKeysCollector(data);
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Check if the cache is empty.
|
|
62
|
+
*/
|
|
63
|
+
UniqueKeysCacheInMemory.prototype.isEmpty = function () {
|
|
64
|
+
return Object.keys(this.uniqueKeysTracker).length === 0;
|
|
65
|
+
};
|
|
66
|
+
return UniqueKeysCacheInMemory;
|
|
67
|
+
}());
|
|
68
|
+
export { UniqueKeysCacheInMemory };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { setToArray, _Set } from '../../utils/lang/sets';
|
|
2
|
+
import { DEFAULT_CACHE_SIZE } from '../inRedis/constants';
|
|
3
|
+
var UniqueKeysCacheInMemoryCS = /** @class */ (function () {
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param impressionsQueueSize number of queued impressions to call onFullQueueCb.
|
|
7
|
+
* Default value is 0, that means no maximum value, in case we want to avoid this being triggered.
|
|
8
|
+
*/
|
|
9
|
+
function UniqueKeysCacheInMemoryCS(uniqueKeysQueueSize) {
|
|
10
|
+
if (uniqueKeysQueueSize === void 0) { uniqueKeysQueueSize = DEFAULT_CACHE_SIZE; }
|
|
11
|
+
this.uniqueTrackerSize = 0;
|
|
12
|
+
this.maxStorage = uniqueKeysQueueSize;
|
|
13
|
+
this.uniqueKeysTracker = {};
|
|
14
|
+
}
|
|
15
|
+
UniqueKeysCacheInMemoryCS.prototype.setOnFullQueueCb = function (cb) {
|
|
16
|
+
this.onFullQueue = cb;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Store unique keys per feature.
|
|
20
|
+
*/
|
|
21
|
+
UniqueKeysCacheInMemoryCS.prototype.track = function (userKey, featureName) {
|
|
22
|
+
if (!this.uniqueKeysTracker[userKey])
|
|
23
|
+
this.uniqueKeysTracker[userKey] = new _Set();
|
|
24
|
+
var tracker = this.uniqueKeysTracker[userKey];
|
|
25
|
+
if (!tracker.has(featureName)) {
|
|
26
|
+
tracker.add(featureName);
|
|
27
|
+
this.uniqueTrackerSize++;
|
|
28
|
+
}
|
|
29
|
+
if (this.uniqueTrackerSize >= this.maxStorage && this.onFullQueue) {
|
|
30
|
+
this.uniqueTrackerSize = 0;
|
|
31
|
+
this.onFullQueue();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Clear the data stored on the cache.
|
|
36
|
+
*/
|
|
37
|
+
UniqueKeysCacheInMemoryCS.prototype.clear = function () {
|
|
38
|
+
this.uniqueKeysTracker = {};
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Pop the collected data, used as payload for posting.
|
|
42
|
+
*/
|
|
43
|
+
UniqueKeysCacheInMemoryCS.prototype.pop = function () {
|
|
44
|
+
var data = this.uniqueKeysTracker;
|
|
45
|
+
this.uniqueKeysTracker = {};
|
|
46
|
+
return this.fromUniqueKeysCollector(data);
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Check if the cache is empty.
|
|
50
|
+
*/
|
|
51
|
+
UniqueKeysCacheInMemoryCS.prototype.isEmpty = function () {
|
|
52
|
+
return Object.keys(this.uniqueKeysTracker).length === 0;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Converts `uniqueKeys` data from cache into request payload.
|
|
56
|
+
*/
|
|
57
|
+
UniqueKeysCacheInMemoryCS.prototype.fromUniqueKeysCollector = function (uniqueKeys) {
|
|
58
|
+
var payload = [];
|
|
59
|
+
var userKeys = Object.keys(uniqueKeys);
|
|
60
|
+
for (var k = 0; k < userKeys.length; k++) {
|
|
61
|
+
var userKey = userKeys[k];
|
|
62
|
+
var featureNames = setToArray(uniqueKeys[userKey]);
|
|
63
|
+
var uniqueKeysPayload = {
|
|
64
|
+
k: userKey,
|
|
65
|
+
fs: featureNames
|
|
66
|
+
};
|
|
67
|
+
payload.push(uniqueKeysPayload);
|
|
68
|
+
}
|
|
69
|
+
return { keys: payload };
|
|
70
|
+
};
|
|
71
|
+
return UniqueKeysCacheInMemoryCS;
|
|
72
|
+
}());
|
|
73
|
+
export { UniqueKeysCacheInMemoryCS };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { __extends } from "tslib";
|
|
2
|
+
import { forOwn } from '../../utils/lang';
|
|
3
|
+
import { ImpressionCountsCacheInMemory } from '../inMemory/ImpressionCountsCacheInMemory';
|
|
4
|
+
import { LOG_PREFIX, REFRESH_RATE, TTL_REFRESH } from './constants';
|
|
5
|
+
var ImpressionCountsCacheInRedis = /** @class */ (function (_super) {
|
|
6
|
+
__extends(ImpressionCountsCacheInRedis, _super);
|
|
7
|
+
function ImpressionCountsCacheInRedis(log, key, redis, impressionCountsCacheSize, refreshRate) {
|
|
8
|
+
if (refreshRate === void 0) { refreshRate = REFRESH_RATE; }
|
|
9
|
+
var _this = _super.call(this, impressionCountsCacheSize) || this;
|
|
10
|
+
_this.log = log;
|
|
11
|
+
_this.key = key;
|
|
12
|
+
_this.redis = redis;
|
|
13
|
+
_this.refreshRate = refreshRate;
|
|
14
|
+
_this.onFullQueue = function () { _this.postImpressionCountsInRedis(); };
|
|
15
|
+
return _this;
|
|
16
|
+
}
|
|
17
|
+
ImpressionCountsCacheInRedis.prototype.postImpressionCountsInRedis = function () {
|
|
18
|
+
var _this = this;
|
|
19
|
+
var counts = this.pop();
|
|
20
|
+
var keys = Object.keys(counts);
|
|
21
|
+
if (!keys.length)
|
|
22
|
+
return Promise.resolve(false);
|
|
23
|
+
var pipeline = this.redis.pipeline();
|
|
24
|
+
keys.forEach(function (key) {
|
|
25
|
+
pipeline.hincrby(_this.key, key, counts[key]);
|
|
26
|
+
});
|
|
27
|
+
return pipeline.exec()
|
|
28
|
+
.then(function (data) {
|
|
29
|
+
// If this is the creation of the key on Redis, set the expiration for it in 3600 seconds.
|
|
30
|
+
if (data.length && data.length === keys.length) {
|
|
31
|
+
return _this.redis.expire(_this.key, TTL_REFRESH);
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
.catch(function (err) {
|
|
35
|
+
_this.log.error(LOG_PREFIX + "Error in impression counts pipeline: " + err + ".");
|
|
36
|
+
return false;
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
ImpressionCountsCacheInRedis.prototype.start = function () {
|
|
40
|
+
this.intervalId = setInterval(this.postImpressionCountsInRedis.bind(this), this.refreshRate);
|
|
41
|
+
};
|
|
42
|
+
ImpressionCountsCacheInRedis.prototype.stop = function () {
|
|
43
|
+
clearInterval(this.intervalId);
|
|
44
|
+
return this.postImpressionCountsInRedis();
|
|
45
|
+
};
|
|
46
|
+
// Async consumer API, used by synchronizer
|
|
47
|
+
ImpressionCountsCacheInRedis.prototype.getImpressionsCount = function () {
|
|
48
|
+
var _this = this;
|
|
49
|
+
return this.redis.hgetall(this.key)
|
|
50
|
+
.then(function (counts) {
|
|
51
|
+
if (!Object.keys(counts).length)
|
|
52
|
+
return undefined;
|
|
53
|
+
_this.redis.del(_this.key).catch(function () { });
|
|
54
|
+
var pf = [];
|
|
55
|
+
forOwn(counts, function (count, key) {
|
|
56
|
+
var nameAndTime = key.split('::');
|
|
57
|
+
if (nameAndTime.length !== 2) {
|
|
58
|
+
_this.log.error(LOG_PREFIX + "Error spliting key " + key);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
var timeFrame = parseInt(nameAndTime[1]);
|
|
62
|
+
if (isNaN(timeFrame)) {
|
|
63
|
+
_this.log.error(LOG_PREFIX + "Error parsing time frame " + nameAndTime[1]);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
var rawCount = parseInt(count);
|
|
67
|
+
if (isNaN(rawCount)) {
|
|
68
|
+
_this.log.error(LOG_PREFIX + "Error parsing raw count " + count);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
pf.push({
|
|
72
|
+
f: nameAndTime[0],
|
|
73
|
+
m: timeFrame,
|
|
74
|
+
rc: rawCount,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
return { pf: pf };
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
return ImpressionCountsCacheInRedis;
|
|
81
|
+
}(ImpressionCountsCacheInMemory));
|
|
82
|
+
export { ImpressionCountsCacheInRedis };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { impressionsToJSON } from '../utils';
|
|
1
2
|
var IMPRESSIONS_TTL_REFRESH = 3600; // 1 hr
|
|
2
3
|
var ImpressionsCacheInRedis = /** @class */ (function () {
|
|
3
4
|
function ImpressionsCacheInRedis(log, key, redis, metadata) {
|
|
@@ -8,31 +9,13 @@ var ImpressionsCacheInRedis = /** @class */ (function () {
|
|
|
8
9
|
}
|
|
9
10
|
ImpressionsCacheInRedis.prototype.track = function (impressions) {
|
|
10
11
|
var _this = this;
|
|
11
|
-
return this.redis.rpush(this.key, this.
|
|
12
|
+
return this.redis.rpush(this.key, impressionsToJSON(impressions, this.metadata)).then(function (queuedCount) {
|
|
12
13
|
// If this is the creation of the key on Redis, set the expiration for it in 1hr.
|
|
13
14
|
if (queuedCount === impressions.length) {
|
|
14
15
|
return _this.redis.expire(_this.key, IMPRESSIONS_TTL_REFRESH);
|
|
15
16
|
}
|
|
16
17
|
});
|
|
17
18
|
};
|
|
18
|
-
ImpressionsCacheInRedis.prototype._toJSON = function (impressions) {
|
|
19
|
-
var _this = this;
|
|
20
|
-
return impressions.map(function (impression) {
|
|
21
|
-
var keyName = impression.keyName, bucketingKey = impression.bucketingKey, feature = impression.feature, treatment = impression.treatment, label = impression.label, time = impression.time, changeNumber = impression.changeNumber;
|
|
22
|
-
return JSON.stringify({
|
|
23
|
-
m: _this.metadata,
|
|
24
|
-
i: {
|
|
25
|
-
k: keyName,
|
|
26
|
-
b: bucketingKey,
|
|
27
|
-
f: feature,
|
|
28
|
-
t: treatment,
|
|
29
|
-
r: label,
|
|
30
|
-
c: changeNumber,
|
|
31
|
-
m: time
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
19
|
ImpressionsCacheInRedis.prototype.count = function () {
|
|
37
20
|
return this.redis.llen(this.key).catch(function () { return 0; });
|
|
38
21
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { parseExceptionField, parseLatencyField, parseMetadata } from '../KeyBuilderSS';
|
|
2
1
|
import { findLatencyIndex } from '../findLatencyIndex';
|
|
3
2
|
import { getTelemetryConfigStats } from '../../sync/submitters/telemetrySubmitter';
|
|
4
3
|
import { CONSUMER_MODE, STORAGE_REDIS } from '../../utils/constants';
|
|
5
4
|
import { isNaNNumber, isString } from '../../utils/lang';
|
|
6
5
|
import { _Map } from '../../utils/lang/maps';
|
|
7
6
|
import { MAX_LATENCY_BUCKET_COUNT, newBuckets } from '../inMemory/TelemetryCacheInMemory';
|
|
7
|
+
import { parseLatencyField, parseExceptionField, parseMetadata } from '../utils';
|
|
8
8
|
var TelemetryCacheInRedis = /** @class */ (function () {
|
|
9
9
|
/**
|
|
10
10
|
* Create a Telemetry cache that uses Redis as storage.
|