@splitsoftware/splitio-commons 2.0.3-rc.0 → 2.1.0-rc.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 +5 -2
- package/README.md +2 -2
- package/cjs/evaluator/index.js +0 -2
- package/cjs/evaluator/matchers/large_segment.js +0 -6
- package/cjs/evaluator/matchers/segment.js +0 -6
- package/cjs/listeners/browser.js +6 -4
- package/cjs/listeners/node.js +2 -2
- package/cjs/readiness/readinessManager.js +6 -0
- package/cjs/sdkClient/client.js +13 -13
- package/cjs/sdkClient/sdkClient.js +1 -1
- package/cjs/sdkFactory/index.js +14 -9
- package/cjs/sdkManager/index.js +1 -2
- package/cjs/storages/AbstractSplitsCacheAsync.js +0 -7
- package/cjs/storages/AbstractSplitsCacheSync.js +0 -7
- package/cjs/storages/KeyBuilderCS.js +3 -0
- package/cjs/storages/dataLoader.js +3 -2
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +1 -57
- package/cjs/storages/inLocalStorage/index.js +8 -7
- package/cjs/storages/inLocalStorage/validateCache.js +79 -0
- package/cjs/storages/inMemory/InMemoryStorage.js +3 -3
- package/cjs/storages/inMemory/InMemoryStorageCS.js +3 -4
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/index.js +13 -9
- package/cjs/storages/pluggable/index.js +21 -16
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +1 -10
- package/cjs/sync/streaming/pushManager.js +8 -6
- package/cjs/sync/submitters/impressionCountsSubmitter.js +4 -2
- package/cjs/sync/submitters/submitterManager.js +6 -3
- package/cjs/sync/syncManagerOnline.js +10 -4
- package/cjs/trackers/eventTracker.js +1 -1
- package/cjs/trackers/impressionsTracker.js +19 -18
- package/cjs/trackers/strategy/strategyDebug.js +11 -4
- package/cjs/trackers/strategy/strategyNone.js +16 -11
- package/cjs/trackers/strategy/strategyOptimized.js +21 -11
- package/cjs/utils/settingsValidation/index.js +1 -1
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/esm/evaluator/index.js +0 -2
- package/esm/evaluator/matchers/large_segment.js +0 -6
- package/esm/evaluator/matchers/segment.js +0 -6
- package/esm/listeners/browser.js +3 -1
- package/esm/listeners/node.js +2 -2
- package/esm/readiness/readinessManager.js +6 -0
- package/esm/sdkClient/client.js +13 -13
- package/esm/sdkClient/sdkClient.js +1 -1
- package/esm/sdkFactory/index.js +15 -10
- package/esm/sdkManager/index.js +1 -2
- package/esm/storages/AbstractSplitsCacheAsync.js +0 -7
- package/esm/storages/AbstractSplitsCacheSync.js +0 -7
- package/esm/storages/KeyBuilderCS.js +3 -0
- package/esm/storages/dataLoader.js +2 -1
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +1 -57
- package/esm/storages/inLocalStorage/index.js +9 -8
- package/esm/storages/inLocalStorage/validateCache.js +75 -0
- package/esm/storages/inMemory/InMemoryStorage.js +4 -4
- package/esm/storages/inMemory/InMemoryStorageCS.js +4 -5
- package/esm/storages/inRedis/SplitsCacheInRedis.js +1 -1
- package/esm/storages/inRedis/index.js +14 -10
- package/esm/storages/pluggable/index.js +22 -17
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
- package/esm/sync/polling/updaters/splitChangesUpdater.js +2 -11
- package/esm/sync/streaming/pushManager.js +8 -6
- package/esm/sync/submitters/impressionCountsSubmitter.js +4 -2
- package/esm/sync/submitters/submitterManager.js +6 -3
- package/esm/sync/syncManagerOnline.js +10 -4
- package/esm/trackers/eventTracker.js +1 -1
- package/esm/trackers/impressionsTracker.js +19 -18
- package/esm/trackers/strategy/strategyDebug.js +11 -4
- package/esm/trackers/strategy/strategyNone.js +16 -11
- package/esm/trackers/strategy/strategyOptimized.js +21 -11
- package/esm/utils/settingsValidation/index.js +1 -1
- package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
- package/package.json +1 -1
- package/src/dtos/types.ts +1 -2
- package/src/evaluator/index.ts +0 -2
- package/src/evaluator/matchers/large_segment.ts +0 -7
- package/src/evaluator/matchers/segment.ts +0 -7
- package/src/evaluator/types.ts +1 -1
- package/src/listeners/browser.ts +3 -1
- package/src/listeners/node.ts +2 -2
- package/src/readiness/readinessManager.ts +5 -0
- package/src/sdkClient/client.ts +11 -11
- package/src/sdkClient/sdkClient.ts +1 -1
- package/src/sdkFactory/index.ts +16 -11
- package/src/sdkFactory/types.ts +1 -1
- package/src/sdkManager/index.ts +1 -2
- package/src/storages/AbstractSplitsCacheAsync.ts +0 -8
- package/src/storages/AbstractSplitsCacheSync.ts +0 -8
- package/src/storages/KeyBuilderCS.ts +4 -0
- package/src/storages/dataLoader.ts +3 -1
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +1 -66
- package/src/storages/inLocalStorage/index.ts +12 -13
- package/src/storages/inLocalStorage/validateCache.ts +91 -0
- package/src/storages/inMemory/InMemoryStorage.ts +4 -4
- package/src/storages/inMemory/InMemoryStorageCS.ts +4 -5
- package/src/storages/inRedis/SplitsCacheInRedis.ts +1 -1
- package/src/storages/inRedis/index.ts +10 -10
- package/src/storages/pluggable/index.ts +22 -17
- package/src/storages/types.ts +3 -6
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +6 -5
- package/src/sync/polling/updaters/splitChangesUpdater.ts +2 -11
- package/src/sync/streaming/pushManager.ts +8 -6
- package/src/sync/submitters/impressionCountsSubmitter.ts +4 -2
- package/src/sync/submitters/submitterManager.ts +4 -3
- package/src/sync/submitters/uniqueKeysSubmitter.ts +3 -2
- package/src/sync/syncManagerOnline.ts +11 -5
- package/src/trackers/eventTracker.ts +1 -1
- package/src/trackers/impressionsTracker.ts +19 -18
- package/src/trackers/strategy/strategyDebug.ts +11 -4
- package/src/trackers/strategy/strategyNone.ts +17 -11
- package/src/trackers/strategy/strategyOptimized.ts +20 -10
- package/src/trackers/types.ts +8 -2
- package/src/utils/lang/index.ts +1 -1
- package/src/utils/settingsValidation/index.ts +1 -1
- package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
- package/types/index.d.ts +1 -1
- package/types/splitio.d.ts +26 -6
- package/cjs/utils/constants/browser.js +0 -5
- package/esm/utils/constants/browser.js +0 -2
- package/src/utils/constants/browser.ts +0 -2
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]
|
|
33
|
+
stopTelemetryTracker(queue[0] && queue[0].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]
|
|
57
|
+
stopTelemetryTracker(queue[0] && queue[0].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]
|
|
83
|
+
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
84
84
|
return treatments;
|
|
85
85
|
};
|
|
86
86
|
var evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
|
|
@@ -103,19 +103,19 @@ 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;
|
|
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
|
-
queue.push(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
queue.push({
|
|
111
|
+
feature: featureFlagName,
|
|
112
|
+
keyName: matchingKey,
|
|
113
|
+
treatment: treatment,
|
|
114
|
+
time: Date.now(),
|
|
115
|
+
bucketingKey: bucketingKey,
|
|
116
|
+
label: label,
|
|
117
|
+
changeNumber: changeNumber
|
|
118
|
+
});
|
|
119
119
|
}
|
|
120
120
|
if (withConfig) {
|
|
121
121
|
return {
|
|
@@ -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.stop();
|
|
50
|
+
uniqueKeysTracker && 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 { NONE, OPTIMIZED } from '../utils/constants';
|
|
15
15
|
/**
|
|
16
16
|
* Modular SDK factory
|
|
17
17
|
*/
|
|
@@ -48,14 +48,19 @@ 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 = uniqueKeysTrackerFactory(log, storage.uniqueKeys, filterAdapterFactory && filterAdapterFactory());
|
|
52
|
-
var
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
var uniqueKeysTracker = impressionsMode === NONE ? uniqueKeysTrackerFactory(log, storage.uniqueKeys, filterAdapterFactory && filterAdapterFactory()) : undefined;
|
|
52
|
+
var strategy;
|
|
53
|
+
switch (impressionsMode) {
|
|
54
|
+
case OPTIMIZED:
|
|
55
|
+
strategy = strategyOptimizedFactory(observer, storage.impressionCounts);
|
|
56
|
+
break;
|
|
57
|
+
case NONE:
|
|
58
|
+
strategy = strategyNoneFactory(storage.impressionCounts, uniqueKeysTracker);
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
strategy = strategyDebugFactory(observer);
|
|
62
|
+
}
|
|
63
|
+
var impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, strategy, whenInit, integrationsManager, storage.telemetry);
|
|
59
64
|
var eventTracker = eventTrackerFactory(settings, storage.events, whenInit, integrationsManager, storage.telemetry);
|
|
60
65
|
// splitApi is used by SyncManager and Browser signal listener
|
|
61
66
|
var splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
|
|
@@ -74,7 +79,7 @@ export function sdkFactory(params) {
|
|
|
74
79
|
// We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
|
|
75
80
|
validateAndTrackApiKey(log, settings.core.authorizationKey);
|
|
76
81
|
readiness.init();
|
|
77
|
-
uniqueKeysTracker.start();
|
|
82
|
+
uniqueKeysTracker && uniqueKeysTracker.start();
|
|
78
83
|
syncManager && syncManager.start();
|
|
79
84
|
signalListener && signalListener.start();
|
|
80
85
|
initCallbacks.forEach(function (cb) { return cb(); });
|
package/esm/sdkManager/index.js
CHANGED
|
@@ -25,8 +25,7 @@ function objectToView(splitObject) {
|
|
|
25
25
|
treatments: collectTreatments(splitObject),
|
|
26
26
|
configs: splitObject.configurations || {},
|
|
27
27
|
sets: splitObject.sets || [],
|
|
28
|
-
defaultTreatment: splitObject.defaultTreatment
|
|
29
|
-
trackImpressions: splitObject.trackImpressions !== false
|
|
28
|
+
defaultTreatment: splitObject.defaultTreatment
|
|
30
29
|
};
|
|
31
30
|
}
|
|
32
31
|
function objectsToViews(splitObjects) {
|
|
@@ -11,13 +11,6 @@ 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
|
-
};
|
|
21
14
|
/**
|
|
22
15
|
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
23
16
|
* Used for SPLIT_KILL push notifications.
|
|
@@ -27,13 +27,6 @@ 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
|
-
};
|
|
37
30
|
/**
|
|
38
31
|
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
39
32
|
* Used for SPLIT_KILL push notifications.
|
|
@@ -29,6 +29,9 @@ 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
|
+
};
|
|
32
35
|
return KeyBuilderCS;
|
|
33
36
|
}(KeyBuilder));
|
|
34
37
|
export { KeyBuilderCS };
|
|
@@ -2,21 +2,17 @@ import { __extends } from "tslib";
|
|
|
2
2
|
import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
|
|
3
3
|
import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
|
|
4
4
|
import { LOG_PREFIX } from './constants';
|
|
5
|
-
import { getStorageHash } from '../KeyBuilder';
|
|
6
5
|
import { setToArray } from '../../utils/lang/sets';
|
|
7
6
|
/**
|
|
8
7
|
* ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
|
|
9
8
|
*/
|
|
10
9
|
var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
11
10
|
__extends(SplitsCacheInLocal, _super);
|
|
12
|
-
function SplitsCacheInLocal(settings, keys
|
|
11
|
+
function SplitsCacheInLocal(settings, keys) {
|
|
13
12
|
var _this = _super.call(this) || this;
|
|
14
13
|
_this.keys = keys;
|
|
15
14
|
_this.log = settings.log;
|
|
16
|
-
_this.storageHash = getStorageHash(settings);
|
|
17
15
|
_this.flagSetsFilter = settings.sync.__splitFiltersValidation.groupedFilters.bySet;
|
|
18
|
-
_this._checkExpiration(expirationTimestamp);
|
|
19
|
-
_this._checkFilterQuery();
|
|
20
16
|
return _this;
|
|
21
17
|
}
|
|
22
18
|
SplitsCacheInLocal.prototype._decrementCount = function (key) {
|
|
@@ -64,7 +60,6 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
64
60
|
* We cannot simply call `localStorage.clear()` since that implies removing user items from the storage.
|
|
65
61
|
*/
|
|
66
62
|
SplitsCacheInLocal.prototype.clear = function () {
|
|
67
|
-
this.log.info(LOG_PREFIX + 'Flushing Splits data from localStorage');
|
|
68
63
|
// collect item keys
|
|
69
64
|
var len = localStorage.length;
|
|
70
65
|
var accum = [];
|
|
@@ -116,18 +111,6 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
116
111
|
return item && JSON.parse(item);
|
|
117
112
|
};
|
|
118
113
|
SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
|
|
119
|
-
// when using a new split query, we must update it at the store
|
|
120
|
-
if (this.updateNewFilter) {
|
|
121
|
-
this.log.info(LOG_PREFIX + 'SDK key, flags filter criteria or flags spec version was modified. Updating cache');
|
|
122
|
-
var storageHashKey = this.keys.buildHashKey();
|
|
123
|
-
try {
|
|
124
|
-
localStorage.setItem(storageHashKey, this.storageHash);
|
|
125
|
-
}
|
|
126
|
-
catch (e) {
|
|
127
|
-
this.log.error(LOG_PREFIX + e);
|
|
128
|
-
}
|
|
129
|
-
this.updateNewFilter = false;
|
|
130
|
-
}
|
|
131
114
|
try {
|
|
132
115
|
localStorage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
|
|
133
116
|
// update "last updated" timestamp with current time
|
|
@@ -178,45 +161,6 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
178
161
|
return true;
|
|
179
162
|
}
|
|
180
163
|
};
|
|
181
|
-
/**
|
|
182
|
-
* Check if the splits information is already stored in browser LocalStorage.
|
|
183
|
-
* In this function we could add more code to check if the data is valid.
|
|
184
|
-
* @override
|
|
185
|
-
*/
|
|
186
|
-
SplitsCacheInLocal.prototype.checkCache = function () {
|
|
187
|
-
return this.getChangeNumber() > -1;
|
|
188
|
-
};
|
|
189
|
-
/**
|
|
190
|
-
* Clean Splits cache if its `lastUpdated` timestamp is older than the given `expirationTimestamp`,
|
|
191
|
-
*
|
|
192
|
-
* @param expirationTimestamp - if the value is not a number, data will not be cleaned
|
|
193
|
-
*/
|
|
194
|
-
SplitsCacheInLocal.prototype._checkExpiration = function (expirationTimestamp) {
|
|
195
|
-
var value = localStorage.getItem(this.keys.buildLastUpdatedKey());
|
|
196
|
-
if (value !== null) {
|
|
197
|
-
value = parseInt(value, 10);
|
|
198
|
-
if (!isNaNNumber(value) && expirationTimestamp && value < expirationTimestamp)
|
|
199
|
-
this.clear();
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
// @TODO eventually remove `_checkFilterQuery`. Cache should be cleared at the storage level, reusing same logic than PluggableStorage
|
|
203
|
-
SplitsCacheInLocal.prototype._checkFilterQuery = function () {
|
|
204
|
-
var storageHashKey = this.keys.buildHashKey();
|
|
205
|
-
var storageHash = localStorage.getItem(storageHashKey);
|
|
206
|
-
if (storageHash !== this.storageHash) {
|
|
207
|
-
try {
|
|
208
|
-
// mark cache to update the new query filter on first successful splits fetch
|
|
209
|
-
this.updateNewFilter = true;
|
|
210
|
-
// if there is cache, clear it
|
|
211
|
-
if (this.checkCache())
|
|
212
|
-
this.clear();
|
|
213
|
-
}
|
|
214
|
-
catch (e) {
|
|
215
|
-
this.log.error(LOG_PREFIX + e);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// if the filter didn't change, nothing is done
|
|
219
|
-
};
|
|
220
164
|
SplitsCacheInLocal.prototype.getNamesByFlagSets = function (flagSets) {
|
|
221
165
|
var _this = this;
|
|
222
166
|
return flagSets.map(function (flagSet) {
|
|
@@ -6,13 +6,13 @@ import { KeyBuilderCS, myLargeSegmentsKeyBuilder } from '../KeyBuilderCS';
|
|
|
6
6
|
import { isLocalStorageAvailable } from '../../utils/env/isLocalStorageAvailable';
|
|
7
7
|
import { SplitsCacheInLocal } from './SplitsCacheInLocal';
|
|
8
8
|
import { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
|
|
9
|
-
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
|
|
10
9
|
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
|
|
11
10
|
import { LOG_PREFIX } from './constants';
|
|
12
|
-
import { STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
11
|
+
import { DEBUG, NONE, STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
13
12
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
|
|
14
13
|
import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
|
|
15
14
|
import { getMatching } from '../../utils/key';
|
|
15
|
+
import { validateCache } from './validateCache';
|
|
16
16
|
/**
|
|
17
17
|
* InLocal storage factory for standalone client-side SplitFactory
|
|
18
18
|
*/
|
|
@@ -25,11 +25,10 @@ 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, impressionsMode = _a.sync.impressionsMode;
|
|
29
29
|
var matchingKey = getMatching(settings.core.key);
|
|
30
30
|
var keys = new KeyBuilderCS(prefix, matchingKey);
|
|
31
|
-
var
|
|
32
|
-
var splits = new SplitsCacheInLocal(settings, keys, expirationTimestamp);
|
|
31
|
+
var splits = new SplitsCacheInLocal(settings, keys);
|
|
33
32
|
var segments = new MySegmentsCacheInLocal(log, keys);
|
|
34
33
|
var largeSegments = new MySegmentsCacheInLocal(log, myLargeSegmentsKeyBuilder(prefix, matchingKey));
|
|
35
34
|
return {
|
|
@@ -37,10 +36,13 @@ export function InLocalStorage(options) {
|
|
|
37
36
|
segments: segments,
|
|
38
37
|
largeSegments: largeSegments,
|
|
39
38
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
40
|
-
impressionCounts: new ImpressionCountsCacheInMemory(),
|
|
39
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
41
40
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
42
41
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
43
|
-
uniqueKeys: new UniqueKeysCacheInMemoryCS(),
|
|
42
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
|
|
43
|
+
validateCache: function () {
|
|
44
|
+
return validateCache(options, settings, keys, splits, segments, largeSegments);
|
|
45
|
+
},
|
|
44
46
|
destroy: function () { },
|
|
45
47
|
// When using shared instantiation with MEMORY we reuse everything but segments (they are customer per key).
|
|
46
48
|
shared: function (matchingKey) {
|
|
@@ -52,7 +54,6 @@ export function InLocalStorage(options) {
|
|
|
52
54
|
impressionCounts: this.impressionCounts,
|
|
53
55
|
events: this.events,
|
|
54
56
|
telemetry: this.telemetry,
|
|
55
|
-
uniqueKeys: this.uniqueKeys,
|
|
56
57
|
destroy: function () { }
|
|
57
58
|
};
|
|
58
59
|
},
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
|
|
2
|
+
import { getStorageHash } from '../KeyBuilder';
|
|
3
|
+
import { LOG_PREFIX } from './constants';
|
|
4
|
+
var DEFAULT_CACHE_EXPIRATION_IN_DAYS = 10;
|
|
5
|
+
var MILLIS_IN_A_DAY = 86400000;
|
|
6
|
+
/**
|
|
7
|
+
* Validates if cache should be cleared and sets the cache `hash` if needed.
|
|
8
|
+
*
|
|
9
|
+
* @returns `true` if cache should be cleared, `false` otherwise
|
|
10
|
+
*/
|
|
11
|
+
function validateExpiration(options, settings, keys, currentTimestamp, isThereCache) {
|
|
12
|
+
var log = settings.log;
|
|
13
|
+
// Check expiration
|
|
14
|
+
var lastUpdatedTimestamp = parseInt(localStorage.getItem(keys.buildLastUpdatedKey()), 10);
|
|
15
|
+
if (!isNaNNumber(lastUpdatedTimestamp)) {
|
|
16
|
+
var cacheExpirationInDays = isFiniteNumber(options.expirationDays) && options.expirationDays >= 1 ? options.expirationDays : DEFAULT_CACHE_EXPIRATION_IN_DAYS;
|
|
17
|
+
var expirationTimestamp = currentTimestamp - MILLIS_IN_A_DAY * cacheExpirationInDays;
|
|
18
|
+
if (lastUpdatedTimestamp < expirationTimestamp) {
|
|
19
|
+
log.info(LOG_PREFIX + 'Cache expired more than ' + cacheExpirationInDays + ' days ago. Cleaning up cache');
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Check hash
|
|
24
|
+
var storageHashKey = keys.buildHashKey();
|
|
25
|
+
var storageHash = localStorage.getItem(storageHashKey);
|
|
26
|
+
var currentStorageHash = getStorageHash(settings);
|
|
27
|
+
if (storageHash !== currentStorageHash) {
|
|
28
|
+
try {
|
|
29
|
+
localStorage.setItem(storageHashKey, currentStorageHash);
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
log.error(LOG_PREFIX + e);
|
|
33
|
+
}
|
|
34
|
+
if (isThereCache) {
|
|
35
|
+
log.info(LOG_PREFIX + 'SDK key, flags filter criteria, or flags spec version has changed. Cleaning up cache');
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false; // No cache to clear
|
|
39
|
+
}
|
|
40
|
+
// Clear on init
|
|
41
|
+
if (options.clearOnInit) {
|
|
42
|
+
var lastClearTimestamp = parseInt(localStorage.getItem(keys.buildLastClear()), 10);
|
|
43
|
+
if (isNaNNumber(lastClearTimestamp) || lastClearTimestamp < currentTimestamp - MILLIS_IN_A_DAY) {
|
|
44
|
+
log.info(LOG_PREFIX + 'clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Clean cache if:
|
|
51
|
+
* - it has expired, i.e., its `lastUpdated` timestamp is older than the given `expirationTimestamp`
|
|
52
|
+
* - its hash has changed, i.e., the SDK key, flags filter criteria or flags spec version was modified
|
|
53
|
+
* - `clearOnInit` was set and cache was not cleared in the last 24 hours
|
|
54
|
+
*
|
|
55
|
+
* @returns `true` if cache is ready to be used, `false` otherwise (cache was cleared or there is no cache)
|
|
56
|
+
*/
|
|
57
|
+
export function validateCache(options, settings, keys, splits, segments, largeSegments) {
|
|
58
|
+
var currentTimestamp = Date.now();
|
|
59
|
+
var isThereCache = splits.getChangeNumber() > -1;
|
|
60
|
+
if (validateExpiration(options, settings, keys, currentTimestamp, isThereCache)) {
|
|
61
|
+
splits.clear();
|
|
62
|
+
segments.clear();
|
|
63
|
+
largeSegments.clear();
|
|
64
|
+
// Update last clear timestamp
|
|
65
|
+
try {
|
|
66
|
+
localStorage.setItem(keys.buildLastClear(), currentTimestamp + '');
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
settings.log.error(LOG_PREFIX + e);
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
// Check if ready from cache
|
|
74
|
+
return isThereCache;
|
|
75
|
+
}
|
|
@@ -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 { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
6
|
+
import { DEBUG, LOCALHOST_MODE, NONE, 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, _c = _a.sync, impressionsMode = _c.impressionsMode, __splitFiltersValidation = _c.__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: new ImpressionCountsCacheInMemory(),
|
|
22
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
23
23
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
24
24
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
25
|
-
uniqueKeys: new UniqueKeysCacheInMemory(),
|
|
25
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemory() : undefined,
|
|
26
26
|
destroy: function () { }
|
|
27
27
|
};
|
|
28
28
|
// @TODO revisit storage logic in localhost mode
|
|
@@ -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 { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
6
|
+
import { DEBUG, LOCALHOST_MODE, NONE, 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, _c = _a.sync, impressionsMode = _c.impressionsMode, __splitFiltersValidation = _c.__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: new ImpressionCountsCacheInMemory(),
|
|
24
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
25
25
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
26
26
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
27
|
-
uniqueKeys: new UniqueKeysCacheInMemoryCS(),
|
|
27
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
|
|
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,7 +36,6 @@ export function InMemoryStorageCSFactory(params) {
|
|
|
36
36
|
impressionCounts: this.impressionCounts,
|
|
37
37
|
events: this.events,
|
|
38
38
|
telemetry: this.telemetry,
|
|
39
|
-
uniqueKeys: this.uniqueKeys,
|
|
40
39
|
destroy: function () { }
|
|
41
40
|
};
|
|
42
41
|
},
|
|
@@ -238,9 +238,9 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
|
|
|
238
238
|
this.log.error(LOG_PREFIX + this.redisError);
|
|
239
239
|
return Promise.reject(this.redisError);
|
|
240
240
|
}
|
|
241
|
-
var splits = {};
|
|
242
241
|
var keys = names.map(function (name) { return _this.keys.buildSplitKey(name); });
|
|
243
242
|
return (_a = this.redis).mget.apply(_a, keys).then(function (splitDefinitions) {
|
|
243
|
+
var splits = {};
|
|
244
244
|
names.forEach(function (name, idx) {
|
|
245
245
|
var split = splitDefinitions[idx];
|
|
246
246
|
splits[name] = split && JSON.parse(split);
|
|
@@ -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 { STORAGE_REDIS } from '../../utils/constants';
|
|
7
|
+
import { DEBUG, NONE, STORAGE_REDIS } from '../../utils/constants';
|
|
8
8
|
import { TelemetryCacheInRedis } from './TelemetryCacheInRedis';
|
|
9
9
|
import { UniqueKeysCacheInRedis } from './UniqueKeysCacheInRedis';
|
|
10
10
|
import { ImpressionCountsCacheInRedis } from './ImpressionCountsCacheInRedis';
|
|
@@ -20,18 +20,20 @@ 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, _a = params.settings, log = _a.log, impressionsMode = _a.sync.impressionsMode;
|
|
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 = new ImpressionCountsCacheInRedis(log, keys.buildImpressionsCountKey(), redisClient);
|
|
29
|
-
var uniqueKeysCache = new UniqueKeysCacheInRedis(log, keys.buildUniqueKeysKey(), redisClient);
|
|
28
|
+
var impressionCountsCache = impressionsMode !== DEBUG ? new ImpressionCountsCacheInRedis(log, keys.buildImpressionsCountKey(), redisClient) : undefined;
|
|
29
|
+
var uniqueKeysCache = impressionsMode === NONE ? new UniqueKeysCacheInRedis(log, keys.buildUniqueKeysKey(), redisClient) : undefined;
|
|
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
|
-
impressionCountsCache
|
|
34
|
-
|
|
33
|
+
if (impressionCountsCache)
|
|
34
|
+
impressionCountsCache.start();
|
|
35
|
+
if (uniqueKeysCache)
|
|
36
|
+
uniqueKeysCache.start();
|
|
35
37
|
// Synchronize config
|
|
36
38
|
telemetry.recordConfig();
|
|
37
39
|
});
|
|
@@ -46,10 +48,12 @@ export function InRedisStorage(options) {
|
|
|
46
48
|
// When using REDIS we should:
|
|
47
49
|
// 1- Disconnect from the storage
|
|
48
50
|
destroy: function () {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
var promises = [];
|
|
52
|
+
if (impressionCountsCache)
|
|
53
|
+
promises.push(impressionCountsCache.stop());
|
|
54
|
+
if (uniqueKeysCache)
|
|
55
|
+
promises.push(uniqueKeysCache.stop());
|
|
56
|
+
return Promise.all(promises).then(function () { redisClient.disconnect(); });
|
|
53
57
|
// @TODO check that caches works as expected when redisClient is disconnected
|
|
54
58
|
}
|
|
55
59
|
};
|
|
@@ -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, STORAGE_PLUGGABLE } from '../../utils/constants';
|
|
10
|
+
import { CONSUMER_PARTIAL_MODE, DEBUG, NONE, 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,27 +51,32 @@ 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, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize;
|
|
54
|
+
var onReadyCb = params.onReadyCb, settings = params.settings, _a = params.settings, log = _a.log, mode = _a.mode, impressionsMode = _a.sync.impressionsMode, _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 isSyncronizer = 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) || isSyncronizer ?
|
|
61
61
|
isPartialConsumer ?
|
|
62
62
|
new TelemetryCacheInMemory() :
|
|
63
63
|
new TelemetryCachePluggable(log, keys, wrapper) :
|
|
64
64
|
undefined;
|
|
65
|
-
var impressionCountsCache =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
var impressionCountsCache = impressionsMode !== DEBUG || isSyncronizer ?
|
|
66
|
+
isPartialConsumer ?
|
|
67
|
+
new ImpressionCountsCacheInMemory() :
|
|
68
|
+
new ImpressionCountsCachePluggable(log, keys.buildImpressionsCountKey(), wrapper) :
|
|
69
|
+
undefined;
|
|
70
|
+
var uniqueKeysCache = impressionsMode === NONE || isSyncronizer ?
|
|
71
|
+
isPartialConsumer ?
|
|
72
|
+
settings.core.key === undefined ? new UniqueKeysCacheInMemory() : new UniqueKeysCacheInMemoryCS() :
|
|
73
|
+
new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper) :
|
|
74
|
+
undefined;
|
|
71
75
|
// Connects to wrapper and emits SDK_READY event on main client
|
|
72
76
|
var connectPromise = wrapper.connect().then(function () {
|
|
73
|
-
if (
|
|
74
|
-
//
|
|
77
|
+
if (isSyncronizer) {
|
|
78
|
+
// @TODO reuse InLocalStorage::validateCache logic
|
|
79
|
+
// In standalone or producer mode, clear storage if SDK key, flags filter criteria or flags spec version was modified
|
|
75
80
|
return wrapper.get(keys.buildHashKey()).then(function (hash) {
|
|
76
81
|
var currentHash = getStorageHash(settings);
|
|
77
82
|
if (hash !== currentHash) {
|
|
@@ -86,9 +91,9 @@ export function PluggableStorage(options) {
|
|
|
86
91
|
}
|
|
87
92
|
else {
|
|
88
93
|
// Start periodic flush of async storages if not running synchronizer (producer mode)
|
|
89
|
-
if (impressionCountsCache.start)
|
|
94
|
+
if (impressionCountsCache && impressionCountsCache.start)
|
|
90
95
|
impressionCountsCache.start();
|
|
91
|
-
if (uniqueKeysCache.start)
|
|
96
|
+
if (uniqueKeysCache && uniqueKeysCache.start)
|
|
92
97
|
uniqueKeysCache.start();
|
|
93
98
|
if (telemetry && telemetry.recordConfig)
|
|
94
99
|
telemetry.recordConfig();
|
|
@@ -109,9 +114,9 @@ export function PluggableStorage(options) {
|
|
|
109
114
|
uniqueKeys: uniqueKeysCache,
|
|
110
115
|
// Stop periodic flush and disconnect the underlying storage
|
|
111
116
|
destroy: function () {
|
|
112
|
-
return Promise.all(
|
|
113
|
-
impressionCountsCache.stop && impressionCountsCache.stop(),
|
|
114
|
-
uniqueKeysCache.stop && uniqueKeysCache.stop(),
|
|
117
|
+
return Promise.all(isSyncronizer ? [] : [
|
|
118
|
+
impressionCountsCache && impressionCountsCache.stop && impressionCountsCache.stop(),
|
|
119
|
+
uniqueKeysCache && uniqueKeysCache.stop && uniqueKeysCache.stop(),
|
|
115
120
|
]).then(function () { return wrapper.disconnect(); });
|
|
116
121
|
},
|
|
117
122
|
// emits SDK_READY event on shared clients and returns a reference to the storage
|
|
@@ -43,9 +43,10 @@ export function fromObjectUpdaterFactory(splitsParser, storage, readiness, setti
|
|
|
43
43
|
readiness.splits.emit(SDK_SPLITS_ARRIVED);
|
|
44
44
|
if (startingUp) {
|
|
45
45
|
startingUp = false;
|
|
46
|
-
|
|
46
|
+
var isCacheLoaded_1 = storage.validateCache ? storage.validateCache() : false;
|
|
47
|
+
Promise.resolve().then(function () {
|
|
47
48
|
// Emits SDK_READY_FROM_CACHE
|
|
48
|
-
if (
|
|
49
|
+
if (isCacheLoaded_1)
|
|
49
50
|
readiness.splits.emit(SDK_SPLITS_CACHE_LOADED);
|
|
50
51
|
// Emits SDK_READY
|
|
51
52
|
readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|