@splitsoftware/splitio-commons 2.1.0-rc.1 → 2.1.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 +4 -5
- package/LICENSE +1 -1
- package/cjs/evaluator/index.js +2 -0
- package/cjs/listeners/browser.js +4 -6
- package/cjs/readiness/readinessManager.js +0 -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/AbstractSplitsCacheAsync.js +7 -0
- package/cjs/storages/AbstractSplitsCacheSync.js +7 -0
- package/cjs/storages/KeyBuilderCS.js +0 -3
- package/cjs/storages/dataLoader.js +2 -3
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +57 -1
- package/cjs/storages/inLocalStorage/index.js +7 -8
- package/cjs/storages/inMemory/InMemoryStorage.js +5 -7
- package/cjs/storages/inMemory/InMemoryStorageCS.js +6 -7
- package/cjs/storages/inRedis/constants.js +1 -1
- package/cjs/storages/inRedis/index.js +9 -13
- package/cjs/storages/pluggable/index.js +16 -21
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +10 -1
- package/cjs/sync/submitters/impressionCountsSubmitter.js +2 -4
- package/cjs/sync/submitters/submitterManager.js +3 -6
- package/cjs/sync/syncManagerOnline.js +3 -8
- 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/cjs/trackers/uniqueKeysTracker.js +1 -1
- package/cjs/utils/constants/browser.js +5 -0
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/esm/evaluator/index.js +2 -0
- package/esm/listeners/browser.js +1 -3
- package/esm/readiness/readinessManager.js +0 -6
- 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/AbstractSplitsCacheAsync.js +7 -0
- package/esm/storages/AbstractSplitsCacheSync.js +7 -0
- package/esm/storages/KeyBuilderCS.js +0 -3
- package/esm/storages/dataLoader.js +1 -2
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +57 -1
- package/esm/storages/inLocalStorage/index.js +8 -9
- package/esm/storages/inMemory/InMemoryStorage.js +6 -8
- package/esm/storages/inMemory/InMemoryStorageCS.js +7 -8
- package/esm/storages/inRedis/constants.js +1 -1
- package/esm/storages/inRedis/index.js +10 -14
- package/esm/storages/pluggable/index.js +17 -22
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
- package/esm/sync/polling/updaters/splitChangesUpdater.js +11 -2
- package/esm/sync/submitters/impressionCountsSubmitter.js +2 -4
- package/esm/sync/submitters/submitterManager.js +3 -6
- package/esm/sync/syncManagerOnline.js +3 -8
- 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/esm/trackers/uniqueKeysTracker.js +1 -1
- package/esm/utils/constants/browser.js +2 -0
- package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
- 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/readiness/readinessManager.ts +0 -5
- 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/AbstractSplitsCacheAsync.ts +8 -0
- package/src/storages/AbstractSplitsCacheSync.ts +8 -0
- package/src/storages/KeyBuilderCS.ts +0 -4
- package/src/storages/dataLoader.ts +1 -3
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +66 -1
- package/src/storages/inLocalStorage/index.ts +13 -12
- package/src/storages/inMemory/InMemoryStorage.ts +6 -6
- package/src/storages/inMemory/InMemoryStorageCS.ts +7 -6
- package/src/storages/inRedis/constants.ts +1 -1
- package/src/storages/inRedis/index.ts +10 -10
- package/src/storages/pluggable/index.ts +17 -22
- package/src/storages/types.ts +6 -3
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +5 -6
- package/src/sync/polling/updaters/splitChangesUpdater.ts +11 -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/sync/syncManagerOnline.ts +3 -9
- 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/src/trackers/uniqueKeysTracker.ts +1 -1
- package/src/utils/constants/browser.ts +2 -0
- package/src/utils/lang/index.ts +1 -1
- package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
- package/types/splitio.d.ts +5 -25
- package/cjs/storages/inLocalStorage/validateCache.js +0 -79
- package/esm/storages/inLocalStorage/validateCache.js +0 -75
- package/src/storages/inLocalStorage/validateCache.ts +0 -91
|
@@ -46,10 +46,9 @@ function fromObjectUpdaterFactory(splitsParser, storage, readiness, settings) {
|
|
|
46
46
|
readiness.splits.emit(constants_2.SDK_SPLITS_ARRIVED);
|
|
47
47
|
if (startingUp) {
|
|
48
48
|
startingUp = false;
|
|
49
|
-
|
|
50
|
-
Promise.resolve().then(function () {
|
|
49
|
+
Promise.resolve(splitsCache.checkCache()).then(function (cacheReady) {
|
|
51
50
|
// Emits SDK_READY_FROM_CACHE
|
|
52
|
-
if (
|
|
51
|
+
if (cacheReady)
|
|
53
52
|
readiness.splits.emit(constants_2.SDK_SPLITS_CACHE_LOADED);
|
|
54
53
|
// Emits SDK_READY
|
|
55
54
|
readiness.segments.emit(constants_2.SDK_SEGMENTS_ARRIVED);
|
|
@@ -126,7 +126,7 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments,
|
|
|
126
126
|
function _splitChangesUpdater(since, retry) {
|
|
127
127
|
if (retry === void 0) { retry = 0; }
|
|
128
128
|
log.debug(constants_2.SYNC_SPLITS_FETCH, [since]);
|
|
129
|
-
|
|
129
|
+
var fetcherPromise = Promise.resolve(splitUpdateNotification ?
|
|
130
130
|
{ splits: [splitUpdateNotification.payload], till: splitUpdateNotification.changeNumber } :
|
|
131
131
|
splitChangesFetcher(since, noCache, till, _promiseDecorator))
|
|
132
132
|
.then(function (splitChanges) {
|
|
@@ -170,6 +170,15 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments,
|
|
|
170
170
|
}
|
|
171
171
|
return false;
|
|
172
172
|
});
|
|
173
|
+
// After triggering the requests, if we have cached splits information let's notify that to emit SDK_READY_FROM_CACHE.
|
|
174
|
+
// Wrapping in a promise since checkCache can be async.
|
|
175
|
+
if (splitsEventEmitter && startingUp) {
|
|
176
|
+
Promise.resolve(splits.checkCache()).then(function (isCacheReady) {
|
|
177
|
+
if (isCacheReady)
|
|
178
|
+
splitsEventEmitter.emit(constants_1.SDK_SPLITS_CACHE_LOADED);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return fetcherPromise;
|
|
173
182
|
}
|
|
174
183
|
var sincePromise = Promise.resolve(splits.getChangeNumber()); // `getChangeNumber` never rejects or throws error
|
|
175
184
|
return sincePromise.then(_splitChangesUpdater);
|
|
@@ -30,9 +30,7 @@ var IMPRESSIONS_COUNT_RATE = 1800000; // 30 minutes
|
|
|
30
30
|
*/
|
|
31
31
|
function impressionCountsSubmitterFactory(params) {
|
|
32
32
|
var log = params.settings.log, postTestImpressionsCount = params.splitApi.postTestImpressionsCount, impressionCounts = params.storage.impressionCounts;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return (0, submitter_1.submitterFactory)(log, postTestImpressionsCount, impressionCounts, IMPRESSIONS_COUNT_RATE, 'impression counts', fromImpressionCountsCollector, 1);
|
|
36
|
-
}
|
|
33
|
+
// retry impressions counts only once.
|
|
34
|
+
return (0, submitter_1.submitterFactory)(log, postTestImpressionsCount, impressionCounts, IMPRESSIONS_COUNT_RATE, 'impression counts', fromImpressionCountsCollector, 1);
|
|
37
35
|
}
|
|
38
36
|
exports.impressionCountsSubmitterFactory = impressionCountsSubmitterFactory;
|
|
@@ -9,14 +9,11 @@ var uniqueKeysSubmitter_1 = require("./uniqueKeysSubmitter");
|
|
|
9
9
|
function submitterManagerFactory(params) {
|
|
10
10
|
var submitters = [
|
|
11
11
|
(0, impressionsSubmitter_1.impressionsSubmitterFactory)(params),
|
|
12
|
-
(0, eventsSubmitter_1.eventsSubmitterFactory)(params)
|
|
12
|
+
(0, eventsSubmitter_1.eventsSubmitterFactory)(params),
|
|
13
|
+
(0, impressionCountsSubmitter_1.impressionCountsSubmitterFactory)(params),
|
|
14
|
+
(0, uniqueKeysSubmitter_1.uniqueKeysSubmitterFactory)(params)
|
|
13
15
|
];
|
|
14
|
-
var impressionCountsSubmitter = (0, impressionCountsSubmitter_1.impressionCountsSubmitterFactory)(params);
|
|
15
|
-
if (impressionCountsSubmitter)
|
|
16
|
-
submitters.push(impressionCountsSubmitter);
|
|
17
16
|
var telemetrySubmitter = (0, telemetrySubmitter_1.telemetrySubmitterFactory)(params);
|
|
18
|
-
if (params.storage.uniqueKeys)
|
|
19
|
-
submitters.push((0, uniqueKeysSubmitter_1.uniqueKeysSubmitterFactory)(params));
|
|
20
17
|
return {
|
|
21
18
|
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
22
19
|
start: function (onlyTelemetry) {
|
|
@@ -6,7 +6,6 @@ var constants_1 = require("./streaming/constants");
|
|
|
6
6
|
var constants_2 = require("../logger/constants");
|
|
7
7
|
var consent_1 = require("../consent");
|
|
8
8
|
var constants_3 = require("../utils/constants");
|
|
9
|
-
var constants_4 = require("../readiness/constants");
|
|
10
9
|
/**
|
|
11
10
|
* Online SyncManager factory.
|
|
12
11
|
* Can be used for server-side API, and client-side API with or without multiple clients.
|
|
@@ -20,7 +19,7 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
20
19
|
* SyncManager factory for modular SDK
|
|
21
20
|
*/
|
|
22
21
|
return function (params) {
|
|
23
|
-
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker
|
|
22
|
+
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker;
|
|
24
23
|
/** Polling Manager */
|
|
25
24
|
var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
26
25
|
/** Push Manager */
|
|
@@ -68,11 +67,6 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
68
67
|
*/
|
|
69
68
|
start: function () {
|
|
70
69
|
running = true;
|
|
71
|
-
if (startFirstTime) {
|
|
72
|
-
var isCacheLoaded = storage.validateCache ? storage.validateCache() : false;
|
|
73
|
-
if (isCacheLoaded)
|
|
74
|
-
Promise.resolve().then(function () { readiness.splits.emit(constants_4.SDK_SPLITS_CACHE_LOADED); });
|
|
75
|
-
}
|
|
76
70
|
// start syncing splits and segments
|
|
77
71
|
if (pollingManager) {
|
|
78
72
|
// If synchronization is disabled pushManager and pollingManager should not start
|
|
@@ -81,6 +75,7 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
81
75
|
// Doesn't call `syncAll` when the syncManager is resuming
|
|
82
76
|
if (startFirstTime) {
|
|
83
77
|
pollingManager.syncAll();
|
|
78
|
+
startFirstTime = false;
|
|
84
79
|
}
|
|
85
80
|
pushManager.start();
|
|
86
81
|
}
|
|
@@ -91,12 +86,12 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
91
86
|
else {
|
|
92
87
|
if (startFirstTime) {
|
|
93
88
|
pollingManager.syncAll();
|
|
89
|
+
startFirstTime = false;
|
|
94
90
|
}
|
|
95
91
|
}
|
|
96
92
|
}
|
|
97
93
|
// start periodic data recording (events, impressions, telemetry).
|
|
98
94
|
submitterManager.start(!(0, consent_1.isConsentGranted)(settings));
|
|
99
|
-
startFirstTime = false;
|
|
100
95
|
},
|
|
101
96
|
/**
|
|
102
97
|
* Method used to stop/pause the syncManager.
|
|
@@ -7,38 +7,37 @@ var constants_1 = require("../logger/constants");
|
|
|
7
7
|
var constants_2 = require("../utils/constants");
|
|
8
8
|
/**
|
|
9
9
|
* Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided.
|
|
10
|
-
*
|
|
11
|
-
* @param impressionsCache - cache to save impressions
|
|
12
|
-
* @param metadata - runtime metadata (ip, hostname and version)
|
|
13
|
-
* @param impressionListener - optional impression listener
|
|
14
|
-
* @param integrationsManager - optional integrations manager
|
|
15
|
-
* @param strategy - strategy for impressions tracking.
|
|
16
10
|
*/
|
|
17
|
-
function impressionsTrackerFactory(settings, impressionsCache, strategy, whenInit, integrationsManager, telemetryCache) {
|
|
11
|
+
function impressionsTrackerFactory(settings, impressionsCache, noneStrategy, strategy, whenInit, integrationsManager, telemetryCache) {
|
|
18
12
|
var log = settings.log, impressionListener = settings.impressionListener, _a = settings.runtime, ip = _a.ip, hostname = _a.hostname, version = settings.version;
|
|
19
13
|
return {
|
|
20
14
|
track: function (impressions, attributes) {
|
|
21
15
|
if (settings.userConsent === constants_2.CONSENT_DECLINED)
|
|
22
16
|
return;
|
|
23
|
-
var
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
var impressionsToStore = impressions.filter(function (_a) {
|
|
18
|
+
var imp = _a.imp, disabled = _a.disabled;
|
|
19
|
+
return disabled ?
|
|
20
|
+
noneStrategy.process(imp) :
|
|
21
|
+
strategy.process(imp);
|
|
22
|
+
});
|
|
23
|
+
var impressionsLength = impressions.length;
|
|
24
|
+
var impressionsToStoreLength = impressionsToStore.length;
|
|
25
|
+
if (impressionsToStoreLength) {
|
|
26
|
+
var res = impressionsCache.track(impressionsToStore.map(function (item) { return item.imp; }));
|
|
28
27
|
// If we're on an async storage, handle error and log it.
|
|
29
28
|
if ((0, thenable_1.thenable)(res)) {
|
|
30
29
|
res.then(function () {
|
|
31
|
-
log.info(constants_1.IMPRESSIONS_TRACKER_SUCCESS, [
|
|
30
|
+
log.info(constants_1.IMPRESSIONS_TRACKER_SUCCESS, [impressionsLength]);
|
|
32
31
|
}).catch(function (err) {
|
|
33
|
-
log.error(constants_1.ERROR_IMPRESSIONS_TRACKER, [
|
|
32
|
+
log.error(constants_1.ERROR_IMPRESSIONS_TRACKER, [impressionsLength, err]);
|
|
34
33
|
});
|
|
35
34
|
}
|
|
36
35
|
else {
|
|
37
36
|
// Record when impressionsCache is sync only (standalone mode)
|
|
38
37
|
// @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
|
|
39
38
|
if (telemetryCache) {
|
|
40
|
-
telemetryCache.recordImpressionStats(constants_2.QUEUED,
|
|
41
|
-
telemetryCache.recordImpressionStats(constants_2.DEDUPED,
|
|
39
|
+
telemetryCache.recordImpressionStats(constants_2.QUEUED, impressionsToStoreLength);
|
|
40
|
+
telemetryCache.recordImpressionStats(constants_2.DEDUPED, impressionsLength - impressionsToStoreLength);
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
43
|
}
|
|
@@ -47,7 +46,7 @@ function impressionsTrackerFactory(settings, impressionsCache, strategy, whenIni
|
|
|
47
46
|
var _loop_1 = function (i) {
|
|
48
47
|
var impressionData = {
|
|
49
48
|
// copy of impression, to avoid unexpected behavior if modified by integrations or impressionListener
|
|
50
|
-
impression: (0, objectAssign_1.objectAssign)({},
|
|
49
|
+
impression: (0, objectAssign_1.objectAssign)({}, impressions[i].imp),
|
|
51
50
|
attributes: attributes,
|
|
52
51
|
ip: ip,
|
|
53
52
|
hostname: hostname,
|
|
@@ -69,7 +68,7 @@ function impressionsTrackerFactory(settings, impressionsCache, strategy, whenIni
|
|
|
69
68
|
});
|
|
70
69
|
});
|
|
71
70
|
};
|
|
72
|
-
for (var i = 0; i <
|
|
71
|
+
for (var i = 0; i < impressionsLength; i++) {
|
|
73
72
|
_loop_1(i);
|
|
74
73
|
}
|
|
75
74
|
}
|
|
@@ -5,20 +5,13 @@ exports.strategyDebugFactory = void 0;
|
|
|
5
5
|
* Debug strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
6
6
|
*
|
|
7
7
|
* @param impressionsObserver - impression observer. Previous time (pt property) is included in impression instances
|
|
8
|
-
* @returns
|
|
8
|
+
* @returns Debug strategy
|
|
9
9
|
*/
|
|
10
10
|
function strategyDebugFactory(impressionsObserver) {
|
|
11
11
|
return {
|
|
12
|
-
process: function (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
impression.pt = impressionsObserver.testAndSet(impression);
|
|
16
|
-
});
|
|
17
|
-
return {
|
|
18
|
-
impressionsToStore: impressions,
|
|
19
|
-
impressionsToListener: impressions,
|
|
20
|
-
deduped: 0
|
|
21
|
-
};
|
|
12
|
+
process: function (impression) {
|
|
13
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
14
|
+
return true;
|
|
22
15
|
}
|
|
23
16
|
};
|
|
24
17
|
}
|
|
@@ -4,25 +4,20 @@ exports.strategyNoneFactory = void 0;
|
|
|
4
4
|
/**
|
|
5
5
|
* None strategy for impressions tracker.
|
|
6
6
|
*
|
|
7
|
-
* @param
|
|
7
|
+
* @param impressionCounts - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
8
8
|
* @param uniqueKeysTracker - unique keys tracker in charge of tracking the unique keys per split.
|
|
9
|
-
* @returns
|
|
9
|
+
* @returns None strategy
|
|
10
10
|
*/
|
|
11
|
-
function strategyNoneFactory(
|
|
11
|
+
function strategyNoneFactory(impressionCounts, uniqueKeysTracker) {
|
|
12
12
|
return {
|
|
13
|
-
process: function (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
impressionsToStore: [],
|
|
23
|
-
impressionsToListener: impressions,
|
|
24
|
-
deduped: 0
|
|
25
|
-
};
|
|
13
|
+
process: function (impression) {
|
|
14
|
+
var now = Date.now();
|
|
15
|
+
// Increments impression counter per featureName
|
|
16
|
+
impressionCounts.track(impression.feature, now, 1);
|
|
17
|
+
// Keep track by unique key
|
|
18
|
+
uniqueKeysTracker.track(impression.keyName, impression.feature);
|
|
19
|
+
// Do not store impressions
|
|
20
|
+
return false;
|
|
26
21
|
}
|
|
27
22
|
};
|
|
28
23
|
}
|
|
@@ -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
|
}
|
|
@@ -8,7 +8,7 @@ var noopFilterAdapter = {
|
|
|
8
8
|
clear: function () { }
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Tracks uniques keys
|
|
12
12
|
* Unique Keys Tracker will be in charge of checking if the MTK was already sent to the BE in the last period
|
|
13
13
|
* or schedule to be sent; if not it will be added in an internal cache and sent in the next post.
|
|
14
14
|
*
|
|
@@ -6,7 +6,7 @@ var constants_1 = require("../../../logger/constants");
|
|
|
6
6
|
var constants_2 = require("../../../utils/constants");
|
|
7
7
|
function __InLocalStorageMockFactory(params) {
|
|
8
8
|
var result = (0, InMemoryStorageCS_1.InMemoryStorageCSFactory)(params);
|
|
9
|
-
result.
|
|
9
|
+
result.splits.checkCache = function () { return true; }; // to emit SDK_READY_FROM_CACHE
|
|
10
10
|
return result;
|
|
11
11
|
}
|
|
12
12
|
exports.__InLocalStorageMockFactory = __InLocalStorageMockFactory;
|
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);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED, SDK_SEGMENTS_ARRIVED, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE, SDK_READY } from './constants';
|
|
3
|
-
import { STORAGE_LOCALSTORAGE } from '../utils/constants';
|
|
4
3
|
function splitsEventEmitterFactory(EventEmitter) {
|
|
5
4
|
var splitsEventEmitter = objectAssign(new EventEmitter(), {
|
|
6
5
|
splitsArrived: false,
|
|
@@ -81,7 +80,6 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
82
|
function checkIsReadyOrUpdate(diff) {
|
|
84
|
-
var _a;
|
|
85
83
|
if (isDestroyed)
|
|
86
84
|
return;
|
|
87
85
|
if (isReady) {
|
|
@@ -100,10 +98,6 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
100
98
|
isReady = true;
|
|
101
99
|
try {
|
|
102
100
|
syncLastUpdate();
|
|
103
|
-
if (!isReadyFromCache && ((_a = settings.storage) === null || _a === void 0 ? void 0 : _a.type) === STORAGE_LOCALSTORAGE) {
|
|
104
|
-
isReadyFromCache = true;
|
|
105
|
-
gate.emit(SDK_READY_FROM_CACHE);
|
|
106
|
-
}
|
|
107
101
|
gate.emit(SDK_READY);
|
|
108
102
|
}
|
|
109
103
|
catch (e) {
|
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) {
|
|
@@ -11,6 +11,13 @@ var AbstractSplitsCacheAsync = /** @class */ (function () {
|
|
|
11
11
|
AbstractSplitsCacheAsync.prototype.usesSegments = function () {
|
|
12
12
|
return Promise.resolve(true);
|
|
13
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* Check if the splits information is already stored in cache.
|
|
16
|
+
* Noop, just keeping the interface. This is used by client-side implementations only.
|
|
17
|
+
*/
|
|
18
|
+
AbstractSplitsCacheAsync.prototype.checkCache = function () {
|
|
19
|
+
return Promise.resolve(false);
|
|
20
|
+
};
|
|
14
21
|
/**
|
|
15
22
|
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
16
23
|
* Used for SPLIT_KILL push notifications.
|
|
@@ -27,6 +27,13 @@ var AbstractSplitsCacheSync = /** @class */ (function () {
|
|
|
27
27
|
var _this = this;
|
|
28
28
|
return this.getSplitNames().map(function (key) { return _this.getSplit(key); });
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Check if the splits information is already stored in cache. This data can be preloaded.
|
|
32
|
+
* It is used as condition to emit SDK_SPLITS_CACHE_LOADED, and then SDK_READY_FROM_CACHE.
|
|
33
|
+
*/
|
|
34
|
+
AbstractSplitsCacheSync.prototype.checkCache = function () {
|
|
35
|
+
return false;
|
|
36
|
+
};
|
|
30
37
|
/**
|
|
31
38
|
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
32
39
|
* Used for SPLIT_KILL push notifications.
|
|
@@ -29,9 +29,6 @@ var KeyBuilderCS = /** @class */ (function (_super) {
|
|
|
29
29
|
KeyBuilderCS.prototype.buildTillKey = function () {
|
|
30
30
|
return this.prefix + "." + this.matchingKey + ".segments.till";
|
|
31
31
|
};
|
|
32
|
-
KeyBuilderCS.prototype.buildLastClear = function () {
|
|
33
|
-
return this.prefix + ".lastClear";
|
|
34
|
-
};
|
|
35
32
|
return KeyBuilderCS;
|
|
36
33
|
}(KeyBuilder));
|
|
37
34
|
export { KeyBuilderCS };
|