@splitsoftware/splitio-commons 2.1.0-rc.1 → 2.1.0-rc.2
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 +5 -1
- package/LICENSE +1 -1
- package/cjs/evaluator/index.js +2 -0
- package/cjs/listeners/browser.js +4 -6
- package/cjs/sdkClient/client.js +14 -11
- package/cjs/sdkClient/sdkClient.js +1 -1
- package/cjs/sdkFactory/index.js +9 -14
- package/cjs/sdkManager/index.js +2 -1
- package/cjs/storages/inLocalStorage/index.js +4 -3
- package/cjs/storages/inMemory/InMemoryStorage.js +5 -7
- package/cjs/storages/inMemory/InMemoryStorageCS.js +6 -7
- package/cjs/storages/inRedis/index.js +9 -13
- package/cjs/storages/pluggable/index.js +15 -19
- package/cjs/sync/submitters/impressionCountsSubmitter.js +2 -4
- package/cjs/sync/submitters/submitterManager.js +3 -6
- package/cjs/trackers/impressionsTracker.js +17 -18
- package/cjs/trackers/strategy/strategyDebug.js +4 -11
- package/cjs/trackers/strategy/strategyNone.js +11 -16
- package/cjs/trackers/strategy/strategyOptimized.js +11 -21
- package/esm/evaluator/index.js +2 -0
- package/esm/listeners/browser.js +1 -3
- package/esm/sdkClient/client.js +14 -11
- package/esm/sdkClient/sdkClient.js +1 -1
- package/esm/sdkFactory/index.js +10 -15
- package/esm/sdkManager/index.js +2 -1
- package/esm/storages/inLocalStorage/index.js +5 -4
- package/esm/storages/inMemory/InMemoryStorage.js +6 -8
- package/esm/storages/inMemory/InMemoryStorageCS.js +7 -8
- package/esm/storages/inRedis/index.js +10 -14
- package/esm/storages/pluggable/index.js +16 -20
- package/esm/sync/submitters/impressionCountsSubmitter.js +2 -4
- package/esm/sync/submitters/submitterManager.js +3 -6
- package/esm/trackers/impressionsTracker.js +17 -18
- package/esm/trackers/strategy/strategyDebug.js +4 -11
- package/esm/trackers/strategy/strategyNone.js +11 -16
- package/esm/trackers/strategy/strategyOptimized.js +11 -21
- package/package.json +1 -1
- package/src/dtos/types.ts +2 -1
- package/src/evaluator/index.ts +2 -0
- package/src/evaluator/types.ts +1 -1
- package/src/listeners/browser.ts +1 -3
- package/src/sdkClient/client.ts +19 -15
- package/src/sdkClient/sdkClient.ts +1 -1
- package/src/sdkFactory/index.ts +11 -16
- package/src/sdkFactory/types.ts +1 -1
- package/src/sdkManager/index.ts +2 -1
- package/src/storages/inLocalStorage/index.ts +5 -4
- package/src/storages/inMemory/InMemoryStorage.ts +6 -6
- package/src/storages/inMemory/InMemoryStorageCS.ts +7 -6
- package/src/storages/inRedis/index.ts +10 -10
- package/src/storages/pluggable/index.ts +16 -20
- package/src/storages/types.ts +2 -2
- package/src/sync/submitters/impressionCountsSubmitter.ts +2 -4
- package/src/sync/submitters/submitterManager.ts +3 -4
- package/src/sync/submitters/uniqueKeysSubmitter.ts +2 -3
- package/src/trackers/impressionsTracker.ts +18 -19
- package/src/trackers/strategy/strategyDebug.ts +4 -11
- package/src/trackers/strategy/strategyNone.ts +11 -17
- package/src/trackers/strategy/strategyOptimized.ts +10 -20
- package/src/trackers/types.ts +13 -8
- package/types/splitio.d.ts +4 -0
|
@@ -6,29 +6,19 @@ var time_1 = require("../../utils/time");
|
|
|
6
6
|
* Optimized strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
7
7
|
*
|
|
8
8
|
* @param impressionsObserver - impression observer. previous time (pt property) is included in impression instances
|
|
9
|
-
* @param
|
|
10
|
-
* @returns
|
|
9
|
+
* @param impressionCounts - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
10
|
+
* @returns Optimized strategy
|
|
11
11
|
*/
|
|
12
|
-
function strategyOptimizedFactory(impressionsObserver,
|
|
12
|
+
function strategyOptimizedFactory(impressionsObserver, impressionCounts) {
|
|
13
13
|
return {
|
|
14
|
-
process: function (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// Checks if the impression should be added in queue to be sent
|
|
23
|
-
if (!impression.pt || impression.pt < (0, time_1.truncateTimeFrame)(now)) {
|
|
24
|
-
impressionsToStore.push(impression);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
return {
|
|
28
|
-
impressionsToStore: impressionsToStore,
|
|
29
|
-
impressionsToListener: impressions,
|
|
30
|
-
deduped: impressions.length - impressionsToStore.length
|
|
31
|
-
};
|
|
14
|
+
process: function (impression) {
|
|
15
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
16
|
+
var now = Date.now();
|
|
17
|
+
// Increments impression counter per featureName
|
|
18
|
+
if (impression.pt)
|
|
19
|
+
impressionCounts.track(impression.feature, now, 1);
|
|
20
|
+
// Checks if the impression should be added in queue to be sent
|
|
21
|
+
return (!impression.pt || impression.pt < (0, time_1.truncateTimeFrame)(now)) ? true : false;
|
|
32
22
|
}
|
|
33
23
|
};
|
|
34
24
|
}
|
package/esm/evaluator/index.js
CHANGED
|
@@ -98,12 +98,14 @@ function getEvaluation(log, splitJSON, key, attributes, storage) {
|
|
|
98
98
|
return evaluation.then(function (result) {
|
|
99
99
|
result.changeNumber = split_1.getChangeNumber();
|
|
100
100
|
result.config = splitJSON.configurations && splitJSON.configurations[result.treatment] || null;
|
|
101
|
+
result.impressionsDisabled = splitJSON.impressionsDisabled;
|
|
101
102
|
return result;
|
|
102
103
|
});
|
|
103
104
|
}
|
|
104
105
|
else {
|
|
105
106
|
evaluation.changeNumber = split_1.getChangeNumber(); // Always sync and optional
|
|
106
107
|
evaluation.config = splitJSON.configurations && splitJSON.configurations[evaluation.treatment] || null;
|
|
108
|
+
evaluation.impressionsDisabled = splitJSON.impressionsDisabled;
|
|
107
109
|
}
|
|
108
110
|
}
|
|
109
111
|
return evaluation;
|
package/esm/listeners/browser.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { fromImpressionsCollector } from '../sync/submitters/impressionsSubmitter';
|
|
2
2
|
import { fromImpressionCountsCollector } from '../sync/submitters/impressionCountsSubmitter';
|
|
3
|
-
import { OPTIMIZED, DEBUG, NONE } from '../utils/constants';
|
|
4
3
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
5
4
|
import { CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants';
|
|
6
5
|
import { isConsentGranted } from '../consent';
|
|
@@ -60,10 +59,9 @@ var BrowserSignalListener = /** @class */ (function () {
|
|
|
60
59
|
var _a = this.settings.urls, events = _a.events, telemetry = _a.telemetry;
|
|
61
60
|
// Flush impressions & events data if there is user consent
|
|
62
61
|
if (isConsentGranted(this.settings)) {
|
|
63
|
-
var sim = this.settings.sync.impressionsMode;
|
|
64
62
|
var extraMetadata = {
|
|
65
63
|
// sim stands for Sync/Split Impressions Mode
|
|
66
|
-
sim:
|
|
64
|
+
sim: this.settings.sync.impressionsMode
|
|
67
65
|
};
|
|
68
66
|
this._flushData(events + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
|
|
69
67
|
this._flushData(events + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
|
package/esm/sdkClient/client.js
CHANGED
|
@@ -30,7 +30,7 @@ export function clientFactory(params) {
|
|
|
30
30
|
var queue = [];
|
|
31
31
|
var treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig, methodName, queue);
|
|
32
32
|
impressionsTracker.track(queue, attributes);
|
|
33
|
-
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
33
|
+
stopTelemetryTracker(queue[0] && queue[0].imp.label);
|
|
34
34
|
return treatment;
|
|
35
35
|
};
|
|
36
36
|
var evaluation = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
|
|
@@ -54,7 +54,7 @@ export function clientFactory(params) {
|
|
|
54
54
|
treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
|
|
55
55
|
});
|
|
56
56
|
impressionsTracker.track(queue, attributes);
|
|
57
|
-
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
57
|
+
stopTelemetryTracker(queue[0] && queue[0].imp.label);
|
|
58
58
|
return treatments;
|
|
59
59
|
};
|
|
60
60
|
var evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
|
|
@@ -80,7 +80,7 @@ export function clientFactory(params) {
|
|
|
80
80
|
treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
|
|
81
81
|
});
|
|
82
82
|
impressionsTracker.track(queue, attributes);
|
|
83
|
-
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
83
|
+
stopTelemetryTracker(queue[0] && queue[0].imp.label);
|
|
84
84
|
return treatments;
|
|
85
85
|
};
|
|
86
86
|
var evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
|
|
@@ -103,18 +103,21 @@ export function clientFactory(params) {
|
|
|
103
103
|
function processEvaluation(evaluation, featureFlagName, key, attributes, withConfig, invokingMethodName, queue) {
|
|
104
104
|
var matchingKey = getMatching(key);
|
|
105
105
|
var bucketingKey = getBucketing(key);
|
|
106
|
-
var treatment = evaluation.treatment, label = evaluation.label, changeNumber = evaluation.changeNumber, _a = evaluation.config, config = _a === void 0 ? null : _a;
|
|
106
|
+
var treatment = evaluation.treatment, label = evaluation.label, changeNumber = evaluation.changeNumber, _a = evaluation.config, config = _a === void 0 ? null : _a, impressionsDisabled = evaluation.impressionsDisabled;
|
|
107
107
|
log.info(IMPRESSION, [featureFlagName, matchingKey, treatment, label]);
|
|
108
108
|
if (validateSplitExistence(log, readinessManager, featureFlagName, label, invokingMethodName)) {
|
|
109
109
|
log.info(IMPRESSION_QUEUEING);
|
|
110
110
|
queue.push({
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
imp: {
|
|
112
|
+
feature: featureFlagName,
|
|
113
|
+
keyName: matchingKey,
|
|
114
|
+
treatment: treatment,
|
|
115
|
+
time: Date.now(),
|
|
116
|
+
bucketingKey: bucketingKey,
|
|
117
|
+
label: label,
|
|
118
|
+
changeNumber: changeNumber,
|
|
119
|
+
},
|
|
120
|
+
disabled: impressionsDisabled
|
|
118
121
|
});
|
|
119
122
|
}
|
|
120
123
|
if (withConfig) {
|
|
@@ -47,7 +47,7 @@ export function sdkClientFactory(params, isSharedClient) {
|
|
|
47
47
|
releaseApiKey(settings.core.authorizationKey);
|
|
48
48
|
telemetryTracker.sessionLength();
|
|
49
49
|
signalListener && signalListener.stop();
|
|
50
|
-
uniqueKeysTracker
|
|
50
|
+
uniqueKeysTracker.stop();
|
|
51
51
|
}
|
|
52
52
|
// Stop background jobs
|
|
53
53
|
syncManager && syncManager.stop();
|
package/esm/sdkFactory/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { strategyDebugFactory } from '../trackers/strategy/strategyDebug';
|
|
|
11
11
|
import { strategyOptimizedFactory } from '../trackers/strategy/strategyOptimized';
|
|
12
12
|
import { strategyNoneFactory } from '../trackers/strategy/strategyNone';
|
|
13
13
|
import { uniqueKeysTrackerFactory } from '../trackers/uniqueKeysTracker';
|
|
14
|
-
import {
|
|
14
|
+
import { DEBUG, OPTIMIZED } from '../utils/constants';
|
|
15
15
|
/**
|
|
16
16
|
* Modular SDK factory
|
|
17
17
|
*/
|
|
@@ -48,19 +48,14 @@ export function sdkFactory(params) {
|
|
|
48
48
|
var telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
|
|
49
49
|
var integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings: settings, storage: storage, telemetryTracker: telemetryTracker });
|
|
50
50
|
var observer = impressionsObserverFactory();
|
|
51
|
-
var uniqueKeysTracker =
|
|
52
|
-
var
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
break;
|
|
60
|
-
default:
|
|
61
|
-
strategy = strategyDebugFactory(observer);
|
|
62
|
-
}
|
|
63
|
-
var impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, strategy, whenInit, integrationsManager, storage.telemetry);
|
|
51
|
+
var uniqueKeysTracker = uniqueKeysTrackerFactory(log, storage.uniqueKeys, filterAdapterFactory && filterAdapterFactory());
|
|
52
|
+
var noneStrategy = strategyNoneFactory(storage.impressionCounts, uniqueKeysTracker);
|
|
53
|
+
var strategy = impressionsMode === OPTIMIZED ?
|
|
54
|
+
strategyOptimizedFactory(observer, storage.impressionCounts) :
|
|
55
|
+
impressionsMode === DEBUG ?
|
|
56
|
+
strategyDebugFactory(observer) :
|
|
57
|
+
noneStrategy;
|
|
58
|
+
var impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, noneStrategy, strategy, whenInit, integrationsManager, storage.telemetry);
|
|
64
59
|
var eventTracker = eventTrackerFactory(settings, storage.events, whenInit, integrationsManager, storage.telemetry);
|
|
65
60
|
// splitApi is used by SyncManager and Browser signal listener
|
|
66
61
|
var splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
|
|
@@ -79,7 +74,7 @@ export function sdkFactory(params) {
|
|
|
79
74
|
// We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
|
|
80
75
|
validateAndTrackApiKey(log, settings.core.authorizationKey);
|
|
81
76
|
readiness.init();
|
|
82
|
-
uniqueKeysTracker
|
|
77
|
+
uniqueKeysTracker.start();
|
|
83
78
|
syncManager && syncManager.start();
|
|
84
79
|
signalListener && signalListener.start();
|
|
85
80
|
initCallbacks.forEach(function (cb) { return cb(); });
|
package/esm/sdkManager/index.js
CHANGED
|
@@ -25,7 +25,8 @@ function objectToView(splitObject) {
|
|
|
25
25
|
treatments: collectTreatments(splitObject),
|
|
26
26
|
configs: splitObject.configurations || {},
|
|
27
27
|
sets: splitObject.sets || [],
|
|
28
|
-
defaultTreatment: splitObject.defaultTreatment
|
|
28
|
+
defaultTreatment: splitObject.defaultTreatment,
|
|
29
|
+
impressionsDisabled: splitObject.impressionsDisabled === true
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
32
|
function objectsToViews(splitObjects) {
|
|
@@ -8,7 +8,7 @@ import { SplitsCacheInLocal } from './SplitsCacheInLocal';
|
|
|
8
8
|
import { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
|
|
9
9
|
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
|
|
10
10
|
import { LOG_PREFIX } from './constants';
|
|
11
|
-
import {
|
|
11
|
+
import { STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
12
12
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
|
|
13
13
|
import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
|
|
14
14
|
import { getMatching } from '../../utils/key';
|
|
@@ -25,7 +25,7 @@ export function InLocalStorage(options) {
|
|
|
25
25
|
params.settings.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
|
|
26
26
|
return InMemoryStorageCSFactory(params);
|
|
27
27
|
}
|
|
28
|
-
var settings = params.settings, _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize
|
|
28
|
+
var settings = params.settings, _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize;
|
|
29
29
|
var matchingKey = getMatching(settings.core.key);
|
|
30
30
|
var keys = new KeyBuilderCS(prefix, matchingKey);
|
|
31
31
|
var splits = new SplitsCacheInLocal(settings, keys);
|
|
@@ -36,10 +36,10 @@ export function InLocalStorage(options) {
|
|
|
36
36
|
segments: segments,
|
|
37
37
|
largeSegments: largeSegments,
|
|
38
38
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
39
|
-
impressionCounts:
|
|
39
|
+
impressionCounts: new ImpressionCountsCacheInMemory(),
|
|
40
40
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
41
41
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
42
|
-
uniqueKeys:
|
|
42
|
+
uniqueKeys: new UniqueKeysCacheInMemoryCS(),
|
|
43
43
|
validateCache: function () {
|
|
44
44
|
return validateCache(options, settings, keys, splits, segments, largeSegments);
|
|
45
45
|
},
|
|
@@ -54,6 +54,7 @@ export function InLocalStorage(options) {
|
|
|
54
54
|
impressionCounts: this.impressionCounts,
|
|
55
55
|
events: this.events,
|
|
56
56
|
telemetry: this.telemetry,
|
|
57
|
+
uniqueKeys: this.uniqueKeys,
|
|
57
58
|
destroy: function () { }
|
|
58
59
|
};
|
|
59
60
|
},
|
|
@@ -3,7 +3,7 @@ import { SegmentsCacheInMemory } from './SegmentsCacheInMemory';
|
|
|
3
3
|
import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
6
|
-
import {
|
|
6
|
+
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
7
7
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
8
8
|
import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
|
|
9
9
|
/**
|
|
@@ -12,17 +12,17 @@ import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
|
|
|
12
12
|
* @param params - parameters required by EventsCacheSync
|
|
13
13
|
*/
|
|
14
14
|
export function InMemoryStorageFactory(params) {
|
|
15
|
-
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize,
|
|
15
|
+
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation;
|
|
16
16
|
var splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
17
17
|
var segments = new SegmentsCacheInMemory();
|
|
18
18
|
var storage = {
|
|
19
19
|
splits: splits,
|
|
20
20
|
segments: segments,
|
|
21
21
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
22
|
-
impressionCounts:
|
|
22
|
+
impressionCounts: new ImpressionCountsCacheInMemory(),
|
|
23
23
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
24
24
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
25
|
-
uniqueKeys:
|
|
25
|
+
uniqueKeys: new UniqueKeysCacheInMemory(),
|
|
26
26
|
destroy: function () { }
|
|
27
27
|
};
|
|
28
28
|
// @TODO revisit storage logic in localhost mode
|
|
@@ -31,10 +31,8 @@ export function InMemoryStorageFactory(params) {
|
|
|
31
31
|
var noopTrack = function () { return true; };
|
|
32
32
|
storage.impressions.track = noopTrack;
|
|
33
33
|
storage.events.track = noopTrack;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (storage.uniqueKeys)
|
|
37
|
-
storage.uniqueKeys.track = noopTrack;
|
|
34
|
+
storage.impressionCounts.track = noopTrack;
|
|
35
|
+
storage.uniqueKeys.track = noopTrack;
|
|
38
36
|
}
|
|
39
37
|
return storage;
|
|
40
38
|
}
|
|
@@ -3,7 +3,7 @@ import { MySegmentsCacheInMemory } from './MySegmentsCacheInMemory';
|
|
|
3
3
|
import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
6
|
-
import {
|
|
6
|
+
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
7
7
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
8
8
|
import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
9
9
|
/**
|
|
@@ -12,7 +12,7 @@ import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
|
12
12
|
* @param params - parameters required by EventsCacheSync
|
|
13
13
|
*/
|
|
14
14
|
export function InMemoryStorageCSFactory(params) {
|
|
15
|
-
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize,
|
|
15
|
+
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation;
|
|
16
16
|
var splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
17
17
|
var segments = new MySegmentsCacheInMemory();
|
|
18
18
|
var largeSegments = new MySegmentsCacheInMemory();
|
|
@@ -21,10 +21,10 @@ export function InMemoryStorageCSFactory(params) {
|
|
|
21
21
|
segments: segments,
|
|
22
22
|
largeSegments: largeSegments,
|
|
23
23
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
24
|
-
impressionCounts:
|
|
24
|
+
impressionCounts: new ImpressionCountsCacheInMemory(),
|
|
25
25
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
26
26
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
27
|
-
uniqueKeys:
|
|
27
|
+
uniqueKeys: new UniqueKeysCacheInMemoryCS(),
|
|
28
28
|
destroy: function () { },
|
|
29
29
|
// When using shared instantiation with MEMORY we reuse everything but segments (they are unique per key)
|
|
30
30
|
shared: function () {
|
|
@@ -36,6 +36,7 @@ export function InMemoryStorageCSFactory(params) {
|
|
|
36
36
|
impressionCounts: this.impressionCounts,
|
|
37
37
|
events: this.events,
|
|
38
38
|
telemetry: this.telemetry,
|
|
39
|
+
uniqueKeys: this.uniqueKeys,
|
|
39
40
|
destroy: function () { }
|
|
40
41
|
};
|
|
41
42
|
},
|
|
@@ -46,10 +47,8 @@ export function InMemoryStorageCSFactory(params) {
|
|
|
46
47
|
var noopTrack = function () { return true; };
|
|
47
48
|
storage.impressions.track = noopTrack;
|
|
48
49
|
storage.events.track = noopTrack;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (storage.uniqueKeys)
|
|
52
|
-
storage.uniqueKeys.track = noopTrack;
|
|
50
|
+
storage.impressionCounts.track = noopTrack;
|
|
51
|
+
storage.uniqueKeys.track = noopTrack;
|
|
53
52
|
}
|
|
54
53
|
return storage;
|
|
55
54
|
}
|
|
@@ -4,7 +4,7 @@ import { SplitsCacheInRedis } from './SplitsCacheInRedis';
|
|
|
4
4
|
import { SegmentsCacheInRedis } from './SegmentsCacheInRedis';
|
|
5
5
|
import { ImpressionsCacheInRedis } from './ImpressionsCacheInRedis';
|
|
6
6
|
import { EventsCacheInRedis } from './EventsCacheInRedis';
|
|
7
|
-
import {
|
|
7
|
+
import { STORAGE_REDIS } from '../../utils/constants';
|
|
8
8
|
import { TelemetryCacheInRedis } from './TelemetryCacheInRedis';
|
|
9
9
|
import { UniqueKeysCacheInRedis } from './UniqueKeysCacheInRedis';
|
|
10
10
|
import { ImpressionCountsCacheInRedis } from './ImpressionCountsCacheInRedis';
|
|
@@ -20,20 +20,18 @@ export function InRedisStorage(options) {
|
|
|
20
20
|
var RD = require('./RedisAdapter').RedisAdapter;
|
|
21
21
|
var prefix = validatePrefix(options.prefix);
|
|
22
22
|
function InRedisStorageFactory(params) {
|
|
23
|
-
var onReadyCb = params.onReadyCb, settings = params.settings,
|
|
23
|
+
var onReadyCb = params.onReadyCb, settings = params.settings, log = params.settings.log;
|
|
24
24
|
var metadata = metadataBuilder(settings);
|
|
25
25
|
var keys = new KeyBuilderSS(prefix, metadata);
|
|
26
26
|
var redisClient = new RD(log, options.options || {});
|
|
27
27
|
var telemetry = new TelemetryCacheInRedis(log, keys, redisClient);
|
|
28
|
-
var impressionCountsCache =
|
|
29
|
-
var uniqueKeysCache =
|
|
28
|
+
var impressionCountsCache = new ImpressionCountsCacheInRedis(log, keys.buildImpressionsCountKey(), redisClient);
|
|
29
|
+
var uniqueKeysCache = new UniqueKeysCacheInRedis(log, keys.buildUniqueKeysKey(), redisClient);
|
|
30
30
|
// subscription to Redis connect event in order to emit SDK_READY event on consumer mode
|
|
31
31
|
redisClient.on('connect', function () {
|
|
32
32
|
onReadyCb();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (uniqueKeysCache)
|
|
36
|
-
uniqueKeysCache.start();
|
|
33
|
+
impressionCountsCache.start();
|
|
34
|
+
uniqueKeysCache.start();
|
|
37
35
|
// Synchronize config
|
|
38
36
|
telemetry.recordConfig();
|
|
39
37
|
});
|
|
@@ -48,12 +46,10 @@ export function InRedisStorage(options) {
|
|
|
48
46
|
// When using REDIS we should:
|
|
49
47
|
// 1- Disconnect from the storage
|
|
50
48
|
destroy: function () {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
promises.push(uniqueKeysCache.stop());
|
|
56
|
-
return Promise.all(promises).then(function () { redisClient.disconnect(); });
|
|
49
|
+
return Promise.all([
|
|
50
|
+
impressionCountsCache.stop(),
|
|
51
|
+
uniqueKeysCache.stop()
|
|
52
|
+
]).then(function () { redisClient.disconnect(); });
|
|
57
53
|
// @TODO check that caches works as expected when redisClient is disconnected
|
|
58
54
|
}
|
|
59
55
|
};
|
|
@@ -7,7 +7,7 @@ import { EventsCachePluggable } from './EventsCachePluggable';
|
|
|
7
7
|
import { wrapperAdapter, METHODS_TO_PROMISE_WRAP } from './wrapperAdapter';
|
|
8
8
|
import { isObject } from '../../utils/lang';
|
|
9
9
|
import { getStorageHash, validatePrefix } from '../KeyBuilder';
|
|
10
|
-
import { CONSUMER_PARTIAL_MODE,
|
|
10
|
+
import { CONSUMER_PARTIAL_MODE, STORAGE_PLUGGABLE } from '../../utils/constants';
|
|
11
11
|
import { ImpressionsCacheInMemory } from '../inMemory/ImpressionsCacheInMemory';
|
|
12
12
|
import { EventsCacheInMemory } from '../inMemory/EventsCacheInMemory';
|
|
13
13
|
import { ImpressionCountsCacheInMemory } from '../inMemory/ImpressionCountsCacheInMemory';
|
|
@@ -51,30 +51,26 @@ export function PluggableStorage(options) {
|
|
|
51
51
|
validatePluggableStorageOptions(options);
|
|
52
52
|
var prefix = validatePrefix(options.prefix);
|
|
53
53
|
function PluggableStorageFactory(params) {
|
|
54
|
-
var onReadyCb = params.onReadyCb, settings = params.settings, _a = params.settings, log = _a.log, mode = _a.mode,
|
|
54
|
+
var onReadyCb = params.onReadyCb, settings = params.settings, _a = params.settings, log = _a.log, mode = _a.mode, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize;
|
|
55
55
|
var metadata = metadataBuilder(settings);
|
|
56
56
|
var keys = new KeyBuilderSS(prefix, metadata);
|
|
57
57
|
var wrapper = wrapperAdapter(log, options.wrapper);
|
|
58
|
-
var
|
|
58
|
+
var isSynchronizer = mode === undefined; // If mode is not defined, the synchronizer is running
|
|
59
59
|
var isPartialConsumer = mode === CONSUMER_PARTIAL_MODE;
|
|
60
|
-
var telemetry = shouldRecordTelemetry(params) ||
|
|
60
|
+
var telemetry = shouldRecordTelemetry(params) || isSynchronizer ?
|
|
61
61
|
isPartialConsumer ?
|
|
62
62
|
new TelemetryCacheInMemory() :
|
|
63
63
|
new TelemetryCachePluggable(log, keys, wrapper) :
|
|
64
64
|
undefined;
|
|
65
|
-
var impressionCountsCache =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
undefined
|
|
70
|
-
|
|
71
|
-
isPartialConsumer ?
|
|
72
|
-
settings.core.key === undefined ? new UniqueKeysCacheInMemory() : new UniqueKeysCacheInMemoryCS() :
|
|
73
|
-
new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper) :
|
|
74
|
-
undefined;
|
|
65
|
+
var impressionCountsCache = isPartialConsumer ?
|
|
66
|
+
new ImpressionCountsCacheInMemory() :
|
|
67
|
+
new ImpressionCountsCachePluggable(log, keys.buildImpressionsCountKey(), wrapper);
|
|
68
|
+
var uniqueKeysCache = isPartialConsumer ?
|
|
69
|
+
settings.core.key === undefined ? new UniqueKeysCacheInMemory() : new UniqueKeysCacheInMemoryCS() :
|
|
70
|
+
new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper);
|
|
75
71
|
// Connects to wrapper and emits SDK_READY event on main client
|
|
76
72
|
var connectPromise = wrapper.connect().then(function () {
|
|
77
|
-
if (
|
|
73
|
+
if (isSynchronizer) {
|
|
78
74
|
// @TODO reuse InLocalStorage::validateCache logic
|
|
79
75
|
// In standalone or producer mode, clear storage if SDK key, flags filter criteria or flags spec version was modified
|
|
80
76
|
return wrapper.get(keys.buildHashKey()).then(function (hash) {
|
|
@@ -91,9 +87,9 @@ export function PluggableStorage(options) {
|
|
|
91
87
|
}
|
|
92
88
|
else {
|
|
93
89
|
// Start periodic flush of async storages if not running synchronizer (producer mode)
|
|
94
|
-
if (impressionCountsCache
|
|
90
|
+
if (impressionCountsCache.start)
|
|
95
91
|
impressionCountsCache.start();
|
|
96
|
-
if (uniqueKeysCache
|
|
92
|
+
if (uniqueKeysCache.start)
|
|
97
93
|
uniqueKeysCache.start();
|
|
98
94
|
if (telemetry && telemetry.recordConfig)
|
|
99
95
|
telemetry.recordConfig();
|
|
@@ -114,9 +110,9 @@ export function PluggableStorage(options) {
|
|
|
114
110
|
uniqueKeys: uniqueKeysCache,
|
|
115
111
|
// Stop periodic flush and disconnect the underlying storage
|
|
116
112
|
destroy: function () {
|
|
117
|
-
return Promise.all(
|
|
118
|
-
impressionCountsCache
|
|
119
|
-
uniqueKeysCache
|
|
113
|
+
return Promise.all(isSynchronizer ? [] : [
|
|
114
|
+
impressionCountsCache.stop && impressionCountsCache.stop(),
|
|
115
|
+
uniqueKeysCache.stop && uniqueKeysCache.stop(),
|
|
120
116
|
]).then(function () { return wrapper.disconnect(); });
|
|
121
117
|
},
|
|
122
118
|
// emits SDK_READY event on shared clients and returns a reference to the storage
|
|
@@ -26,8 +26,6 @@ var IMPRESSIONS_COUNT_RATE = 1800000; // 30 minutes
|
|
|
26
26
|
*/
|
|
27
27
|
export function impressionCountsSubmitterFactory(params) {
|
|
28
28
|
var log = params.settings.log, postTestImpressionsCount = params.splitApi.postTestImpressionsCount, impressionCounts = params.storage.impressionCounts;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return submitterFactory(log, postTestImpressionsCount, impressionCounts, IMPRESSIONS_COUNT_RATE, 'impression counts', fromImpressionCountsCollector, 1);
|
|
32
|
-
}
|
|
29
|
+
// retry impressions counts only once.
|
|
30
|
+
return submitterFactory(log, postTestImpressionsCount, impressionCounts, IMPRESSIONS_COUNT_RATE, 'impression counts', fromImpressionCountsCollector, 1);
|
|
33
31
|
}
|
|
@@ -6,14 +6,11 @@ import { uniqueKeysSubmitterFactory } from './uniqueKeysSubmitter';
|
|
|
6
6
|
export function submitterManagerFactory(params) {
|
|
7
7
|
var submitters = [
|
|
8
8
|
impressionsSubmitterFactory(params),
|
|
9
|
-
eventsSubmitterFactory(params)
|
|
9
|
+
eventsSubmitterFactory(params),
|
|
10
|
+
impressionCountsSubmitterFactory(params),
|
|
11
|
+
uniqueKeysSubmitterFactory(params)
|
|
10
12
|
];
|
|
11
|
-
var impressionCountsSubmitter = impressionCountsSubmitterFactory(params);
|
|
12
|
-
if (impressionCountsSubmitter)
|
|
13
|
-
submitters.push(impressionCountsSubmitter);
|
|
14
13
|
var telemetrySubmitter = telemetrySubmitterFactory(params);
|
|
15
|
-
if (params.storage.uniqueKeys)
|
|
16
|
-
submitters.push(uniqueKeysSubmitterFactory(params));
|
|
17
14
|
return {
|
|
18
15
|
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
19
16
|
start: function (onlyTelemetry) {
|
|
@@ -4,38 +4,37 @@ import { IMPRESSIONS_TRACKER_SUCCESS, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIO
|
|
|
4
4
|
import { CONSENT_DECLINED, DEDUPED, QUEUED } from '../utils/constants';
|
|
5
5
|
/**
|
|
6
6
|
* Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided.
|
|
7
|
-
*
|
|
8
|
-
* @param impressionsCache - cache to save impressions
|
|
9
|
-
* @param metadata - runtime metadata (ip, hostname and version)
|
|
10
|
-
* @param impressionListener - optional impression listener
|
|
11
|
-
* @param integrationsManager - optional integrations manager
|
|
12
|
-
* @param strategy - strategy for impressions tracking.
|
|
13
7
|
*/
|
|
14
|
-
export function impressionsTrackerFactory(settings, impressionsCache, strategy, whenInit, integrationsManager, telemetryCache) {
|
|
8
|
+
export function impressionsTrackerFactory(settings, impressionsCache, noneStrategy, strategy, whenInit, integrationsManager, telemetryCache) {
|
|
15
9
|
var log = settings.log, impressionListener = settings.impressionListener, _a = settings.runtime, ip = _a.ip, hostname = _a.hostname, version = settings.version;
|
|
16
10
|
return {
|
|
17
11
|
track: function (impressions, attributes) {
|
|
18
12
|
if (settings.userConsent === CONSENT_DECLINED)
|
|
19
13
|
return;
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
var impressionsToStore = impressions.filter(function (_a) {
|
|
15
|
+
var imp = _a.imp, disabled = _a.disabled;
|
|
16
|
+
return disabled ?
|
|
17
|
+
noneStrategy.process(imp) :
|
|
18
|
+
strategy.process(imp);
|
|
19
|
+
});
|
|
20
|
+
var impressionsLength = impressions.length;
|
|
21
|
+
var impressionsToStoreLength = impressionsToStore.length;
|
|
22
|
+
if (impressionsToStoreLength) {
|
|
23
|
+
var res = impressionsCache.track(impressionsToStore.map(function (item) { return item.imp; }));
|
|
25
24
|
// If we're on an async storage, handle error and log it.
|
|
26
25
|
if (thenable(res)) {
|
|
27
26
|
res.then(function () {
|
|
28
|
-
log.info(IMPRESSIONS_TRACKER_SUCCESS, [
|
|
27
|
+
log.info(IMPRESSIONS_TRACKER_SUCCESS, [impressionsLength]);
|
|
29
28
|
}).catch(function (err) {
|
|
30
|
-
log.error(ERROR_IMPRESSIONS_TRACKER, [
|
|
29
|
+
log.error(ERROR_IMPRESSIONS_TRACKER, [impressionsLength, err]);
|
|
31
30
|
});
|
|
32
31
|
}
|
|
33
32
|
else {
|
|
34
33
|
// Record when impressionsCache is sync only (standalone mode)
|
|
35
34
|
// @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
|
|
36
35
|
if (telemetryCache) {
|
|
37
|
-
telemetryCache.recordImpressionStats(QUEUED,
|
|
38
|
-
telemetryCache.recordImpressionStats(DEDUPED,
|
|
36
|
+
telemetryCache.recordImpressionStats(QUEUED, impressionsToStoreLength);
|
|
37
|
+
telemetryCache.recordImpressionStats(DEDUPED, impressionsLength - impressionsToStoreLength);
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
}
|
|
@@ -44,7 +43,7 @@ export function impressionsTrackerFactory(settings, impressionsCache, strategy,
|
|
|
44
43
|
var _loop_1 = function (i) {
|
|
45
44
|
var impressionData = {
|
|
46
45
|
// copy of impression, to avoid unexpected behavior if modified by integrations or impressionListener
|
|
47
|
-
impression: objectAssign({},
|
|
46
|
+
impression: objectAssign({}, impressions[i].imp),
|
|
48
47
|
attributes: attributes,
|
|
49
48
|
ip: ip,
|
|
50
49
|
hostname: hostname,
|
|
@@ -66,7 +65,7 @@ export function impressionsTrackerFactory(settings, impressionsCache, strategy,
|
|
|
66
65
|
});
|
|
67
66
|
});
|
|
68
67
|
};
|
|
69
|
-
for (var i = 0; i <
|
|
68
|
+
for (var i = 0; i < impressionsLength; i++) {
|
|
70
69
|
_loop_1(i);
|
|
71
70
|
}
|
|
72
71
|
}
|
|
@@ -2,20 +2,13 @@
|
|
|
2
2
|
* Debug strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
3
3
|
*
|
|
4
4
|
* @param impressionsObserver - impression observer. Previous time (pt property) is included in impression instances
|
|
5
|
-
* @returns
|
|
5
|
+
* @returns Debug strategy
|
|
6
6
|
*/
|
|
7
7
|
export function strategyDebugFactory(impressionsObserver) {
|
|
8
8
|
return {
|
|
9
|
-
process: function (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
impression.pt = impressionsObserver.testAndSet(impression);
|
|
13
|
-
});
|
|
14
|
-
return {
|
|
15
|
-
impressionsToStore: impressions,
|
|
16
|
-
impressionsToListener: impressions,
|
|
17
|
-
deduped: 0
|
|
18
|
-
};
|
|
9
|
+
process: function (impression) {
|
|
10
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
11
|
+
return true;
|
|
19
12
|
}
|
|
20
13
|
};
|
|
21
14
|
}
|