@splitsoftware/splitio-commons 2.4.2-rc.3 → 2.5.0-rc.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 +2 -10
- package/cjs/storages/dataLoader.js +102 -43
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +21 -17
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +37 -33
- package/cjs/storages/inLocalStorage/index.js +13 -31
- package/cjs/storages/inLocalStorage/validateCache.js +23 -28
- package/cjs/storages/inMemory/InMemoryStorageCS.js +32 -14
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +4 -0
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +0 -2
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +0 -2
- package/cjs/sync/syncManagerOnline.js +24 -28
- package/cjs/utils/env/isLocalStorageAvailable.js +5 -28
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/esm/storages/dataLoader.js +99 -41
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +21 -17
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +37 -33
- package/esm/storages/inLocalStorage/index.js +14 -32
- package/esm/storages/inLocalStorage/validateCache.js +23 -28
- package/esm/storages/inMemory/InMemoryStorageCS.js +32 -14
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +4 -0
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +0 -2
- package/esm/sync/polling/updaters/splitChangesUpdater.js +0 -2
- package/esm/sync/syncManagerOnline.js +24 -28
- package/esm/utils/env/isLocalStorageAvailable.js +3 -24
- package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
- package/package.json +1 -1
- package/src/sdkFactory/index.ts +3 -2
- package/src/storages/dataLoader.ts +107 -49
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +17 -18
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +22 -19
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +37 -34
- package/src/storages/inLocalStorage/index.ts +16 -37
- package/src/storages/inLocalStorage/validateCache.ts +23 -29
- package/src/storages/inMemory/InMemoryStorageCS.ts +37 -14
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +4 -0
- package/src/storages/types.ts +6 -22
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +2 -1
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +0 -2
- package/src/sync/polling/updaters/splitChangesUpdater.ts +1 -3
- package/src/sync/syncManagerOnline.ts +22 -27
- package/src/types.ts +0 -35
- package/src/utils/env/isLocalStorageAvailable.ts +3 -24
- package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
- package/types/splitio.d.ts +46 -42
- package/cjs/storages/inLocalStorage/storageAdapter.js +0 -54
- package/esm/storages/inLocalStorage/storageAdapter.js +0 -50
- package/src/storages/inLocalStorage/storageAdapter.ts +0 -62
|
@@ -11,10 +11,10 @@ var MILLIS_IN_A_DAY = 86400000;
|
|
|
11
11
|
*
|
|
12
12
|
* @returns `true` if cache should be cleared, `false` otherwise
|
|
13
13
|
*/
|
|
14
|
-
function validateExpiration(options,
|
|
14
|
+
function validateExpiration(options, settings, keys, currentTimestamp, isThereCache) {
|
|
15
15
|
var log = settings.log;
|
|
16
16
|
// Check expiration
|
|
17
|
-
var lastUpdatedTimestamp = parseInt(
|
|
17
|
+
var lastUpdatedTimestamp = parseInt(localStorage.getItem(keys.buildLastUpdatedKey()), 10);
|
|
18
18
|
if (!(0, lang_1.isNaNNumber)(lastUpdatedTimestamp)) {
|
|
19
19
|
var cacheExpirationInDays = (0, lang_1.isFiniteNumber)(options.expirationDays) && options.expirationDays >= 1 ? options.expirationDays : DEFAULT_CACHE_EXPIRATION_IN_DAYS;
|
|
20
20
|
var expirationTimestamp = currentTimestamp - MILLIS_IN_A_DAY * cacheExpirationInDays;
|
|
@@ -25,11 +25,11 @@ function validateExpiration(options, storage, settings, keys, currentTimestamp,
|
|
|
25
25
|
}
|
|
26
26
|
// Check hash
|
|
27
27
|
var storageHashKey = keys.buildHashKey();
|
|
28
|
-
var storageHash =
|
|
28
|
+
var storageHash = localStorage.getItem(storageHashKey);
|
|
29
29
|
var currentStorageHash = (0, KeyBuilder_1.getStorageHash)(settings);
|
|
30
30
|
if (storageHash !== currentStorageHash) {
|
|
31
31
|
try {
|
|
32
|
-
|
|
32
|
+
localStorage.setItem(storageHashKey, currentStorageHash);
|
|
33
33
|
}
|
|
34
34
|
catch (e) {
|
|
35
35
|
log.error(constants_1.LOG_PREFIX + e);
|
|
@@ -42,7 +42,7 @@ function validateExpiration(options, storage, settings, keys, currentTimestamp,
|
|
|
42
42
|
}
|
|
43
43
|
// Clear on init
|
|
44
44
|
if (options.clearOnInit) {
|
|
45
|
-
var lastClearTimestamp = parseInt(
|
|
45
|
+
var lastClearTimestamp = parseInt(localStorage.getItem(keys.buildLastClear()), 10);
|
|
46
46
|
if ((0, lang_1.isNaNNumber)(lastClearTimestamp) || lastClearTimestamp < currentTimestamp - MILLIS_IN_A_DAY) {
|
|
47
47
|
log.info(constants_1.LOG_PREFIX + 'clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
|
|
48
48
|
return true;
|
|
@@ -57,29 +57,24 @@ function validateExpiration(options, storage, settings, keys, currentTimestamp,
|
|
|
57
57
|
*
|
|
58
58
|
* @returns `true` if cache is ready to be used, `false` otherwise (cache was cleared or there is no cache)
|
|
59
59
|
*/
|
|
60
|
-
function validateCache(options,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
settings.log.error(constants_1.LOG_PREFIX + e);
|
|
75
|
-
}
|
|
76
|
-
// Persist clear
|
|
77
|
-
if (storage.save)
|
|
78
|
-
storage.save();
|
|
79
|
-
return false;
|
|
60
|
+
function validateCache(options, settings, keys, splits, rbSegments, segments, largeSegments) {
|
|
61
|
+
var currentTimestamp = Date.now();
|
|
62
|
+
var isThereCache = splits.getChangeNumber() > -1;
|
|
63
|
+
if (validateExpiration(options, settings, keys, currentTimestamp, isThereCache)) {
|
|
64
|
+
splits.clear();
|
|
65
|
+
rbSegments.clear();
|
|
66
|
+
segments.clear();
|
|
67
|
+
largeSegments.clear();
|
|
68
|
+
// Update last clear timestamp
|
|
69
|
+
try {
|
|
70
|
+
localStorage.setItem(keys.buildLastClear(), currentTimestamp + '');
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
settings.log.error(constants_1.LOG_PREFIX + e);
|
|
80
74
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
// Check if ready from cache
|
|
78
|
+
return isThereCache;
|
|
84
79
|
}
|
|
85
80
|
exports.validateCache = validateCache;
|
|
@@ -9,6 +9,8 @@ var ImpressionCountsCacheInMemory_1 = require("./ImpressionCountsCacheInMemory")
|
|
|
9
9
|
var constants_1 = require("../../utils/constants");
|
|
10
10
|
var TelemetryCacheInMemory_1 = require("./TelemetryCacheInMemory");
|
|
11
11
|
var UniqueKeysCacheInMemoryCS_1 = require("./UniqueKeysCacheInMemoryCS");
|
|
12
|
+
var key_1 = require("../../utils/key");
|
|
13
|
+
var dataLoader_1 = require("../dataLoader");
|
|
12
14
|
var RBSegmentsCacheInMemory_1 = require("./RBSegmentsCacheInMemory");
|
|
13
15
|
/**
|
|
14
16
|
* InMemory storage factory for standalone client-side SplitFactory
|
|
@@ -16,7 +18,8 @@ var RBSegmentsCacheInMemory_1 = require("./RBSegmentsCacheInMemory");
|
|
|
16
18
|
* @param params - parameters required by EventsCacheSync
|
|
17
19
|
*/
|
|
18
20
|
function InMemoryStorageCSFactory(params) {
|
|
19
|
-
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation;
|
|
21
|
+
var _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation, preloadedData = _a.preloadedData, onReadyFromCacheCb = params.onReadyFromCacheCb;
|
|
22
|
+
var storages = {};
|
|
20
23
|
var splits = new SplitsCacheInMemory_1.SplitsCacheInMemory(__splitFiltersValidation);
|
|
21
24
|
var rbSegments = new RBSegmentsCacheInMemory_1.RBSegmentsCacheInMemory();
|
|
22
25
|
var segments = new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory();
|
|
@@ -33,19 +36,27 @@ function InMemoryStorageCSFactory(params) {
|
|
|
33
36
|
uniqueKeys: new UniqueKeysCacheInMemoryCS_1.UniqueKeysCacheInMemoryCS(),
|
|
34
37
|
destroy: function () { },
|
|
35
38
|
// When using shared instantiation with MEMORY we reuse everything but segments (they are unique per key)
|
|
36
|
-
shared: function () {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
shared: function (matchingKey) {
|
|
40
|
+
if (!storages[matchingKey]) {
|
|
41
|
+
var segments_1 = new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory();
|
|
42
|
+
var largeSegments_1 = new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory();
|
|
43
|
+
if (preloadedData) {
|
|
44
|
+
(0, dataLoader_1.setCache)(log, preloadedData, { segments: segments_1, largeSegments: largeSegments_1 }, matchingKey);
|
|
45
|
+
}
|
|
46
|
+
storages[matchingKey] = {
|
|
47
|
+
splits: this.splits,
|
|
48
|
+
rbSegments: this.rbSegments,
|
|
49
|
+
segments: segments_1,
|
|
50
|
+
largeSegments: largeSegments_1,
|
|
51
|
+
impressions: this.impressions,
|
|
52
|
+
impressionCounts: this.impressionCounts,
|
|
53
|
+
events: this.events,
|
|
54
|
+
telemetry: this.telemetry,
|
|
55
|
+
uniqueKeys: this.uniqueKeys,
|
|
56
|
+
destroy: function () { }
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return storages[matchingKey];
|
|
49
60
|
},
|
|
50
61
|
};
|
|
51
62
|
// @TODO revisit storage logic in localhost mode
|
|
@@ -57,6 +68,13 @@ function InMemoryStorageCSFactory(params) {
|
|
|
57
68
|
storage.impressionCounts.track = noopTrack;
|
|
58
69
|
storage.uniqueKeys.track = noopTrack;
|
|
59
70
|
}
|
|
71
|
+
var matchingKey = (0, key_1.getMatching)(params.settings.core.key);
|
|
72
|
+
storages[matchingKey] = storage;
|
|
73
|
+
if (preloadedData) {
|
|
74
|
+
(0, dataLoader_1.setCache)(log, preloadedData, storage, matchingKey);
|
|
75
|
+
if (splits.getChangeNumber() > -1)
|
|
76
|
+
onReadyFromCacheCb();
|
|
77
|
+
}
|
|
60
78
|
return storage;
|
|
61
79
|
}
|
|
62
80
|
exports.InMemoryStorageCSFactory = InMemoryStorageCSFactory;
|
|
@@ -45,6 +45,10 @@ var RBSegmentsCacheInMemory = /** @class */ (function () {
|
|
|
45
45
|
RBSegmentsCacheInMemory.prototype.get = function (name) {
|
|
46
46
|
return this.cache[name] || null;
|
|
47
47
|
};
|
|
48
|
+
RBSegmentsCacheInMemory.prototype.getAll = function () {
|
|
49
|
+
var _this = this;
|
|
50
|
+
return this.getNames().map(function (key) { return _this.get(key); });
|
|
51
|
+
};
|
|
48
52
|
RBSegmentsCacheInMemory.prototype.contains = function (names) {
|
|
49
53
|
var namesArray = (0, sets_1.setToArray)(names);
|
|
50
54
|
var namesInStorage = this.getNames();
|
|
@@ -45,9 +45,10 @@ function fromObjectUpdaterFactory(splitsParser, storage, readiness, settings) {
|
|
|
45
45
|
readiness.splits.emit(constants_2.SDK_SPLITS_ARRIVED);
|
|
46
46
|
if (startingUp) {
|
|
47
47
|
startingUp = false;
|
|
48
|
-
|
|
48
|
+
var isCacheLoaded_1 = storage.validateCache ? storage.validateCache() : false;
|
|
49
|
+
Promise.resolve().then(function () {
|
|
49
50
|
// Emits SDK_READY_FROM_CACHE
|
|
50
|
-
if (
|
|
51
|
+
if (isCacheLoaded_1)
|
|
51
52
|
readiness.splits.emit(constants_2.SDK_SPLITS_CACHE_LOADED);
|
|
52
53
|
// Emits SDK_READY
|
|
53
54
|
readiness.segments.emit(constants_2.SDK_SEGMENTS_ARRIVED);
|
|
@@ -34,8 +34,6 @@ function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmentsEvent
|
|
|
34
34
|
shouldNotifyUpdate = segments.resetSegments(segmentsData.ms || {});
|
|
35
35
|
shouldNotifyUpdate = largeSegments.resetSegments(segmentsData.ls || {}) || shouldNotifyUpdate;
|
|
36
36
|
}
|
|
37
|
-
if (storage.save)
|
|
38
|
-
storage.save();
|
|
39
37
|
// Notify update if required
|
|
40
38
|
if ((0, AbstractSplitsCacheSync_1.usesSegmentsSync)(storage) && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
|
|
41
39
|
readyOnAlreadyExistentState = false;
|
|
@@ -154,8 +154,6 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, splitFilt
|
|
|
154
154
|
segments.registerSegments((0, sets_1.setToArray)(usedSegments))
|
|
155
155
|
]).then(function (_a) {
|
|
156
156
|
var ffChanged = _a[0], rbsChanged = _a[1];
|
|
157
|
-
if (storage.save)
|
|
158
|
-
storage.save();
|
|
159
157
|
if (splitsEventEmitter) {
|
|
160
158
|
// To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
|
|
161
159
|
return Promise.resolve(!splitsEventEmitter.splitsArrived || ((ffChanged || rbsChanged) && (isClientSide || checkAllSegmentsExist(segments))))
|
|
@@ -69,39 +69,35 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
|
69
69
|
*/
|
|
70
70
|
start: function () {
|
|
71
71
|
running = true;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (pollingManager) {
|
|
84
|
-
// If synchronization is disabled pushManager and pollingManager should not start
|
|
85
|
-
if (syncEnabled) {
|
|
86
|
-
if (pushManager) {
|
|
87
|
-
// Doesn't call `syncAll` when the syncManager is resuming
|
|
88
|
-
if (startFirstTime) {
|
|
89
|
-
pollingManager.syncAll();
|
|
90
|
-
}
|
|
91
|
-
pushManager.start();
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
pollingManager.start();
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
72
|
+
if (startFirstTime) {
|
|
73
|
+
var isCacheLoaded = storage.validateCache ? storage.validateCache() : false;
|
|
74
|
+
if (isCacheLoaded)
|
|
75
|
+
Promise.resolve().then(function () { readiness.splits.emit(constants_4.SDK_SPLITS_CACHE_LOADED); });
|
|
76
|
+
}
|
|
77
|
+
// start syncing splits and segments
|
|
78
|
+
if (pollingManager) {
|
|
79
|
+
// If synchronization is disabled pushManager and pollingManager should not start
|
|
80
|
+
if (syncEnabled) {
|
|
81
|
+
if (pushManager) {
|
|
82
|
+
// Doesn't call `syncAll` when the syncManager is resuming
|
|
98
83
|
if (startFirstTime) {
|
|
99
84
|
pollingManager.syncAll();
|
|
100
85
|
}
|
|
86
|
+
pushManager.start();
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
pollingManager.start();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
if (startFirstTime) {
|
|
94
|
+
pollingManager.syncAll();
|
|
101
95
|
}
|
|
102
96
|
}
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
}
|
|
98
|
+
// start periodic data recording (events, impressions, telemetry).
|
|
99
|
+
submitterManager.start(!(0, consent_1.isConsentGranted)(settings));
|
|
100
|
+
startFirstTime = false;
|
|
105
101
|
},
|
|
106
102
|
/**
|
|
107
103
|
* Method used to stop/pause the syncManager.
|
|
@@ -1,39 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.isLocalStorageAvailable = void 0;
|
|
4
|
+
/* eslint-disable no-undef */
|
|
4
5
|
function isLocalStorageAvailable() {
|
|
5
|
-
try {
|
|
6
|
-
// eslint-disable-next-line no-undef
|
|
7
|
-
return isValidStorageWrapper(localStorage);
|
|
8
|
-
}
|
|
9
|
-
catch (e) {
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
exports.isLocalStorageAvailable = isLocalStorageAvailable;
|
|
14
|
-
function isValidStorageWrapper(wrapper) {
|
|
15
6
|
var mod = '__SPLITSOFTWARE__';
|
|
16
7
|
try {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
wrapper.removeItem(mod);
|
|
8
|
+
localStorage.setItem(mod, mod);
|
|
9
|
+
localStorage.removeItem(mod);
|
|
20
10
|
return true;
|
|
21
11
|
}
|
|
22
12
|
catch (e) {
|
|
23
13
|
return false;
|
|
24
14
|
}
|
|
25
15
|
}
|
|
26
|
-
exports.
|
|
27
|
-
function isWebStorage(wrapper) {
|
|
28
|
-
if (typeof wrapper.length === 'number') {
|
|
29
|
-
try {
|
|
30
|
-
wrapper.key(0);
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
33
|
-
catch (e) {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
exports.isWebStorage = isWebStorage;
|
|
16
|
+
exports.isLocalStorageAvailable = isLocalStorageAvailable;
|
|
@@ -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.validateCache = function () { return
|
|
9
|
+
result.validateCache = function () { return true; }; // to emit SDK_READY_FROM_CACHE
|
|
10
10
|
return result;
|
|
11
11
|
}
|
|
12
12
|
exports.__InLocalStorageMockFactory = __InLocalStorageMockFactory;
|
|
@@ -1,46 +1,104 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { setToArray } from '../utils/lang/sets';
|
|
2
|
+
import { getMatching } from '../utils/key';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* and extended with a `mySegmentsData` property.
|
|
8
|
-
* @returns function to preload the storage
|
|
4
|
+
* Sets the given synchronous storage with the provided preloaded data snapshot.
|
|
5
|
+
* If `matchingKey` is provided, the storage is handled as a client-side storage (segments and largeSegments are instances of MySegmentsCache).
|
|
6
|
+
* Otherwise, the storage is handled as a server-side storage (segments is an instance of SegmentsCache).
|
|
9
7
|
*/
|
|
10
|
-
export function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
var
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
var mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[userId];
|
|
37
|
-
if (!mySegmentsData) {
|
|
38
|
-
// segmentsData in an object where the property is the segment name and the pertaining value is a stringified object that contains the `added` array of userIds
|
|
39
|
-
mySegmentsData = Object.keys(segmentsData).filter(function (segmentName) {
|
|
40
|
-
var userIds = JSON.parse(segmentsData[segmentName]).added;
|
|
41
|
-
return Array.isArray(userIds) && userIds.indexOf(userId) > -1;
|
|
42
|
-
});
|
|
8
|
+
export function setCache(log, preloadedData, storage, matchingKey) {
|
|
9
|
+
// Do not load data if current preloadedData is empty
|
|
10
|
+
if (Object.keys(preloadedData).length === 0)
|
|
11
|
+
return;
|
|
12
|
+
var splits = storage.splits, rbSegments = storage.rbSegments, segments = storage.segments, largeSegments = storage.largeSegments;
|
|
13
|
+
log.debug("set cache" + (matchingKey ? " for key " + matchingKey : ''));
|
|
14
|
+
if (splits) {
|
|
15
|
+
splits.clear();
|
|
16
|
+
splits.update(preloadedData.flags || [], [], preloadedData.since || -1);
|
|
17
|
+
}
|
|
18
|
+
if (rbSegments) {
|
|
19
|
+
rbSegments.clear();
|
|
20
|
+
rbSegments.update(preloadedData.rbSegments || [], [], preloadedData.rbSince || -1);
|
|
21
|
+
}
|
|
22
|
+
var segmentsData = preloadedData.segments || {};
|
|
23
|
+
if (matchingKey) { // add memberships data (client-side)
|
|
24
|
+
var memberships = preloadedData.memberships && preloadedData.memberships[matchingKey];
|
|
25
|
+
if (!memberships && segmentsData) {
|
|
26
|
+
memberships = {
|
|
27
|
+
ms: {
|
|
28
|
+
k: Object.keys(segmentsData).filter(function (segmentName) {
|
|
29
|
+
var segmentKeys = segmentsData[segmentName];
|
|
30
|
+
return segmentKeys.indexOf(matchingKey) > -1;
|
|
31
|
+
}).map(function (segmentName) { return ({ n: segmentName }); })
|
|
32
|
+
}
|
|
33
|
+
};
|
|
43
34
|
}
|
|
44
|
-
|
|
35
|
+
if (memberships) {
|
|
36
|
+
if (memberships.ms)
|
|
37
|
+
segments.resetSegments(memberships.ms);
|
|
38
|
+
if (memberships.ls && largeSegments)
|
|
39
|
+
largeSegments.resetSegments(memberships.ls);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else { // add segments data (server-side)
|
|
43
|
+
Object.keys(segmentsData).forEach(function (segmentName) {
|
|
44
|
+
var segmentKeys = segmentsData[segmentName];
|
|
45
|
+
segments.update(segmentName, segmentKeys, [], -1);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Gets the preloaded data snapshot from the given synchronous storage.
|
|
51
|
+
* If `keys` are provided, the memberships for those keys is returned, to protect segments data.
|
|
52
|
+
* Otherwise, the segments data is returned.
|
|
53
|
+
*/
|
|
54
|
+
export function getCache(log, storage, keys) {
|
|
55
|
+
log.debug("get cache" + (keys ? " for keys " + keys : ''));
|
|
56
|
+
return {
|
|
57
|
+
since: storage.splits.getChangeNumber(),
|
|
58
|
+
flags: storage.splits.getAll(),
|
|
59
|
+
rbSince: storage.rbSegments.getChangeNumber(),
|
|
60
|
+
rbSegments: storage.rbSegments.getAll(),
|
|
61
|
+
segments: keys ?
|
|
62
|
+
undefined : // @ts-ignore accessing private prop
|
|
63
|
+
Object.keys(storage.segments.segmentCache).reduce(function (prev, cur) {
|
|
64
|
+
prev[cur] = setToArray(storage.segments.segmentCache[cur]);
|
|
65
|
+
return prev;
|
|
66
|
+
}, {}),
|
|
67
|
+
memberships: keys ?
|
|
68
|
+
keys.reduce(function (prev, key) {
|
|
69
|
+
if (storage.shared) {
|
|
70
|
+
// Client-side segments
|
|
71
|
+
// @ts-ignore accessing private prop
|
|
72
|
+
var sharedStorage = storage.shared(key);
|
|
73
|
+
prev[getMatching(key)] = {
|
|
74
|
+
ms: {
|
|
75
|
+
// @ts-ignore accessing private prop
|
|
76
|
+
k: Object.keys(sharedStorage.segments.segmentCache).map(function (segmentName) { return ({ n: segmentName }); }),
|
|
77
|
+
},
|
|
78
|
+
ls: sharedStorage.largeSegments ? {
|
|
79
|
+
// @ts-ignore accessing private prop
|
|
80
|
+
k: Object.keys(sharedStorage.largeSegments.segmentCache).map(function (segmentName) { return ({ n: segmentName }); }),
|
|
81
|
+
} : undefined
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
prev[getMatching(key)] = {
|
|
86
|
+
ms: {
|
|
87
|
+
// Server-side segments
|
|
88
|
+
// @ts-ignore accessing private prop
|
|
89
|
+
k: Object.keys(storage.segments.segmentCache).reduce(function (prev, segmentName) {
|
|
90
|
+
return storage.segments.segmentCache[segmentName].has(key) ?
|
|
91
|
+
prev.concat({ n: segmentName }) :
|
|
92
|
+
prev;
|
|
93
|
+
}, [])
|
|
94
|
+
},
|
|
95
|
+
ls: {
|
|
96
|
+
k: []
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return prev;
|
|
101
|
+
}, {}) :
|
|
102
|
+
undefined
|
|
45
103
|
};
|
|
46
104
|
}
|
|
@@ -4,20 +4,19 @@ import { AbstractMySegmentsCacheSync } from '../AbstractMySegmentsCacheSync';
|
|
|
4
4
|
import { LOG_PREFIX, DEFINED } from './constants';
|
|
5
5
|
var MySegmentsCacheInLocal = /** @class */ (function (_super) {
|
|
6
6
|
__extends(MySegmentsCacheInLocal, _super);
|
|
7
|
-
function MySegmentsCacheInLocal(log, keys
|
|
7
|
+
function MySegmentsCacheInLocal(log, keys) {
|
|
8
8
|
var _this = _super.call(this) || this;
|
|
9
9
|
_this.log = log;
|
|
10
10
|
_this.keys = keys;
|
|
11
|
-
_this.storage = storage;
|
|
12
11
|
return _this;
|
|
13
12
|
// There is not need to flush segments cache like splits cache, since resetSegments receives the up-to-date list of active segments
|
|
14
13
|
}
|
|
15
14
|
MySegmentsCacheInLocal.prototype.addSegment = function (name) {
|
|
16
15
|
var segmentKey = this.keys.buildSegmentNameKey(name);
|
|
17
16
|
try {
|
|
18
|
-
if (
|
|
17
|
+
if (localStorage.getItem(segmentKey) === DEFINED)
|
|
19
18
|
return false;
|
|
20
|
-
|
|
19
|
+
localStorage.setItem(segmentKey, DEFINED);
|
|
21
20
|
return true;
|
|
22
21
|
}
|
|
23
22
|
catch (e) {
|
|
@@ -28,9 +27,9 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
|
|
|
28
27
|
MySegmentsCacheInLocal.prototype.removeSegment = function (name) {
|
|
29
28
|
var segmentKey = this.keys.buildSegmentNameKey(name);
|
|
30
29
|
try {
|
|
31
|
-
if (
|
|
30
|
+
if (localStorage.getItem(segmentKey) !== DEFINED)
|
|
32
31
|
return false;
|
|
33
|
-
|
|
32
|
+
localStorage.removeItem(segmentKey);
|
|
34
33
|
return true;
|
|
35
34
|
}
|
|
36
35
|
catch (e) {
|
|
@@ -39,16 +38,17 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
|
|
|
39
38
|
}
|
|
40
39
|
};
|
|
41
40
|
MySegmentsCacheInLocal.prototype.isInSegment = function (name) {
|
|
42
|
-
return
|
|
41
|
+
return localStorage.getItem(this.keys.buildSegmentNameKey(name)) === DEFINED;
|
|
43
42
|
};
|
|
44
43
|
MySegmentsCacheInLocal.prototype.getRegisteredSegments = function () {
|
|
45
|
-
var
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
var _this = this;
|
|
45
|
+
// Scan current values from localStorage
|
|
46
|
+
return Object.keys(localStorage).reduce(function (accum, key) {
|
|
47
|
+
var segmentName = _this.keys.extractSegmentName(key);
|
|
48
48
|
if (segmentName)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
accum.push(segmentName);
|
|
50
|
+
return accum;
|
|
51
|
+
}, []);
|
|
52
52
|
};
|
|
53
53
|
MySegmentsCacheInLocal.prototype.getKeysCount = function () {
|
|
54
54
|
return 1;
|
|
@@ -56,9 +56,9 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
|
|
|
56
56
|
MySegmentsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
|
|
57
57
|
try {
|
|
58
58
|
if (changeNumber)
|
|
59
|
-
|
|
59
|
+
localStorage.setItem(this.keys.buildTillKey(), changeNumber + '');
|
|
60
60
|
else
|
|
61
|
-
|
|
61
|
+
localStorage.removeItem(this.keys.buildTillKey());
|
|
62
62
|
}
|
|
63
63
|
catch (e) {
|
|
64
64
|
this.log.error(e);
|
|
@@ -66,7 +66,7 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
|
|
|
66
66
|
};
|
|
67
67
|
MySegmentsCacheInLocal.prototype.getChangeNumber = function () {
|
|
68
68
|
var n = -1;
|
|
69
|
-
var value =
|
|
69
|
+
var value = localStorage.getItem(this.keys.buildTillKey());
|
|
70
70
|
if (value !== null) {
|
|
71
71
|
value = parseInt(value, 10);
|
|
72
72
|
return isNaNNumber(value) ? n : value;
|