@splitsoftware/splitio-commons 2.4.2-rc.2 → 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/AbstractMySegmentsCacheSync.js +23 -31
- package/cjs/storages/AbstractSplitsCacheSync.js +2 -3
- package/cjs/storages/dataLoader.js +102 -43
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +23 -20
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +37 -33
- package/cjs/storages/inLocalStorage/index.js +13 -28
- package/cjs/storages/inLocalStorage/validateCache.js +23 -25
- 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/syncManagerOnline.js +24 -28
- package/cjs/utils/env/isLocalStorageAvailable.js +5 -28
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/esm/storages/AbstractMySegmentsCacheSync.js +23 -31
- package/esm/storages/AbstractSplitsCacheSync.js +2 -3
- package/esm/storages/dataLoader.js +99 -41
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +16 -16
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +23 -20
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +37 -33
- package/esm/storages/inLocalStorage/index.js +14 -29
- package/esm/storages/inLocalStorage/validateCache.js +23 -25
- 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/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/AbstractMySegmentsCacheSync.ts +20 -26
- package/src/storages/AbstractSplitsCacheSync.ts +2 -3
- package/src/storages/dataLoader.ts +107 -49
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +17 -18
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +24 -22
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +37 -34
- package/src/storages/inLocalStorage/index.ts +16 -33
- package/src/storages/inLocalStorage/validateCache.ts +23 -26
- package/src/storages/inMemory/InMemoryStorageCS.ts +37 -14
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +4 -0
- package/src/storages/types.ts +6 -20
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +2 -1
- 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 -27
- package/cjs/storages/inLocalStorage/storageAdapter.js +0 -48
- package/esm/storages/inLocalStorage/storageAdapter.js +0 -44
- package/src/storages/inLocalStorage/storageAdapter.ts +0 -50
|
@@ -6,22 +6,25 @@ var AbstractSplitsCacheSync_1 = require("../AbstractSplitsCacheSync");
|
|
|
6
6
|
var lang_1 = require("../../utils/lang");
|
|
7
7
|
var constants_1 = require("./constants");
|
|
8
8
|
var sets_1 = require("../../utils/lang/sets");
|
|
9
|
+
/**
|
|
10
|
+
* ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
|
|
11
|
+
*/
|
|
9
12
|
var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
10
13
|
(0, tslib_1.__extends)(SplitsCacheInLocal, _super);
|
|
11
|
-
function SplitsCacheInLocal(settings, keys
|
|
14
|
+
function SplitsCacheInLocal(settings, keys) {
|
|
12
15
|
var _this = _super.call(this) || this;
|
|
13
16
|
_this.keys = keys;
|
|
14
17
|
_this.log = settings.log;
|
|
15
18
|
_this.flagSetsFilter = settings.sync.__splitFiltersValidation.groupedFilters.bySet;
|
|
16
|
-
_this.storage = storage;
|
|
17
19
|
return _this;
|
|
18
20
|
}
|
|
19
21
|
SplitsCacheInLocal.prototype._decrementCount = function (key) {
|
|
20
|
-
var count = (0, lang_1.toNumber)(
|
|
22
|
+
var count = (0, lang_1.toNumber)(localStorage.getItem(key)) - 1;
|
|
23
|
+
// @ts-expect-error
|
|
21
24
|
if (count > 0)
|
|
22
|
-
|
|
25
|
+
localStorage.setItem(key, count);
|
|
23
26
|
else
|
|
24
|
-
|
|
27
|
+
localStorage.removeItem(key);
|
|
25
28
|
};
|
|
26
29
|
SplitsCacheInLocal.prototype._decrementCounts = function (split) {
|
|
27
30
|
try {
|
|
@@ -39,10 +42,12 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
39
42
|
SplitsCacheInLocal.prototype._incrementCounts = function (split) {
|
|
40
43
|
try {
|
|
41
44
|
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
42
|
-
|
|
45
|
+
// @ts-expect-error
|
|
46
|
+
localStorage.setItem(ttKey, (0, lang_1.toNumber)(localStorage.getItem(ttKey)) + 1);
|
|
43
47
|
if ((0, AbstractSplitsCacheSync_1.usesSegments)(split)) {
|
|
44
48
|
var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
45
|
-
|
|
49
|
+
// @ts-expect-error
|
|
50
|
+
localStorage.setItem(segmentsCountKey, (0, lang_1.toNumber)(localStorage.getItem(segmentsCountKey)) + 1);
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
catch (e) {
|
|
@@ -54,18 +59,17 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
54
59
|
* We cannot simply call `localStorage.clear()` since that implies removing user items from the storage.
|
|
55
60
|
*/
|
|
56
61
|
SplitsCacheInLocal.prototype.clear = function () {
|
|
57
|
-
var _this = this;
|
|
58
62
|
// collect item keys
|
|
59
|
-
var len =
|
|
63
|
+
var len = localStorage.length;
|
|
60
64
|
var accum = [];
|
|
61
65
|
for (var cur = 0; cur < len; cur++) {
|
|
62
|
-
var key =
|
|
66
|
+
var key = localStorage.key(cur);
|
|
63
67
|
if (key != null && this.keys.isSplitsCacheKey(key))
|
|
64
68
|
accum.push(key);
|
|
65
69
|
}
|
|
66
70
|
// remove items
|
|
67
71
|
accum.forEach(function (key) {
|
|
68
|
-
|
|
72
|
+
localStorage.removeItem(key);
|
|
69
73
|
});
|
|
70
74
|
this.hasSync = false;
|
|
71
75
|
};
|
|
@@ -73,13 +77,13 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
73
77
|
try {
|
|
74
78
|
var name_1 = split.name;
|
|
75
79
|
var splitKey = this.keys.buildSplitKey(name_1);
|
|
76
|
-
var
|
|
77
|
-
var previousSplit =
|
|
80
|
+
var splitFromLocalStorage = localStorage.getItem(splitKey);
|
|
81
|
+
var previousSplit = splitFromLocalStorage ? JSON.parse(splitFromLocalStorage) : null;
|
|
78
82
|
if (previousSplit) {
|
|
79
83
|
this._decrementCounts(previousSplit);
|
|
80
84
|
this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
|
|
81
85
|
}
|
|
82
|
-
|
|
86
|
+
localStorage.setItem(splitKey, JSON.stringify(split));
|
|
83
87
|
this._incrementCounts(split);
|
|
84
88
|
this.addToFlagSets(split);
|
|
85
89
|
return true;
|
|
@@ -94,7 +98,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
94
98
|
var split = this.getSplit(name);
|
|
95
99
|
if (!split)
|
|
96
100
|
return false;
|
|
97
|
-
|
|
101
|
+
localStorage.removeItem(this.keys.buildSplitKey(name));
|
|
98
102
|
this._decrementCounts(split);
|
|
99
103
|
this.removeFromFlagSets(split.name, split.sets);
|
|
100
104
|
return true;
|
|
@@ -105,14 +109,14 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
105
109
|
}
|
|
106
110
|
};
|
|
107
111
|
SplitsCacheInLocal.prototype.getSplit = function (name) {
|
|
108
|
-
var item =
|
|
112
|
+
var item = localStorage.getItem(this.keys.buildSplitKey(name));
|
|
109
113
|
return item && JSON.parse(item);
|
|
110
114
|
};
|
|
111
115
|
SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
|
|
112
116
|
try {
|
|
113
|
-
|
|
117
|
+
localStorage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
|
|
114
118
|
// update "last updated" timestamp with current time
|
|
115
|
-
|
|
119
|
+
localStorage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
|
|
116
120
|
this.hasSync = true;
|
|
117
121
|
return true;
|
|
118
122
|
}
|
|
@@ -123,7 +127,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
123
127
|
};
|
|
124
128
|
SplitsCacheInLocal.prototype.getChangeNumber = function () {
|
|
125
129
|
var n = -1;
|
|
126
|
-
var value =
|
|
130
|
+
var value = localStorage.getItem(this.keys.buildSplitsTillKey());
|
|
127
131
|
if (value !== null) {
|
|
128
132
|
value = parseInt(value, 10);
|
|
129
133
|
return (0, lang_1.isNaNNumber)(value) ? n : value;
|
|
@@ -131,11 +135,11 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
131
135
|
return n;
|
|
132
136
|
};
|
|
133
137
|
SplitsCacheInLocal.prototype.getSplitNames = function () {
|
|
134
|
-
var len =
|
|
138
|
+
var len = localStorage.length;
|
|
135
139
|
var accum = [];
|
|
136
140
|
var cur = 0;
|
|
137
141
|
while (cur < len) {
|
|
138
|
-
var key =
|
|
142
|
+
var key = localStorage.key(cur);
|
|
139
143
|
if (key != null && this.keys.isSplitKey(key))
|
|
140
144
|
accum.push(this.keys.extractKey(key));
|
|
141
145
|
cur++;
|
|
@@ -143,14 +147,14 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
143
147
|
return accum;
|
|
144
148
|
};
|
|
145
149
|
SplitsCacheInLocal.prototype.trafficTypeExists = function (trafficType) {
|
|
146
|
-
var ttCount = (0, lang_1.toNumber)(
|
|
150
|
+
var ttCount = (0, lang_1.toNumber)(localStorage.getItem(this.keys.buildTrafficTypeKey(trafficType)));
|
|
147
151
|
return (0, lang_1.isFiniteNumber)(ttCount) && ttCount > 0;
|
|
148
152
|
};
|
|
149
153
|
SplitsCacheInLocal.prototype.usesSegments = function () {
|
|
150
154
|
// If cache hasn't been synchronized with the cloud, assume we need them.
|
|
151
155
|
if (!this.hasSync)
|
|
152
156
|
return true;
|
|
153
|
-
var storedCount =
|
|
157
|
+
var storedCount = localStorage.getItem(this.keys.buildSplitsWithSegmentCountKey());
|
|
154
158
|
var splitsWithSegmentsCount = storedCount === null ? 0 : (0, lang_1.toNumber)(storedCount);
|
|
155
159
|
return (0, lang_1.isFiniteNumber)(splitsWithSegmentsCount) ?
|
|
156
160
|
splitsWithSegmentsCount > 0 :
|
|
@@ -160,8 +164,8 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
160
164
|
var _this = this;
|
|
161
165
|
return flagSets.map(function (flagSet) {
|
|
162
166
|
var flagSetKey = _this.keys.buildFlagSetKey(flagSet);
|
|
163
|
-
var
|
|
164
|
-
return new Set(
|
|
167
|
+
var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
|
|
168
|
+
return new Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
|
|
165
169
|
});
|
|
166
170
|
};
|
|
167
171
|
SplitsCacheInLocal.prototype.addToFlagSets = function (featureFlag) {
|
|
@@ -172,10 +176,10 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
172
176
|
if (_this.flagSetsFilter.length > 0 && !_this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === featureFlagSet; }))
|
|
173
177
|
return;
|
|
174
178
|
var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
|
|
175
|
-
var
|
|
176
|
-
var flagSetCache = new Set(
|
|
179
|
+
var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
|
|
180
|
+
var flagSetCache = new Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
|
|
177
181
|
flagSetCache.add(featureFlag.name);
|
|
178
|
-
|
|
182
|
+
localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
|
|
179
183
|
});
|
|
180
184
|
};
|
|
181
185
|
SplitsCacheInLocal.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
|
|
@@ -188,16 +192,16 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
188
192
|
};
|
|
189
193
|
SplitsCacheInLocal.prototype.removeNames = function (flagSetName, featureFlagName) {
|
|
190
194
|
var flagSetKey = this.keys.buildFlagSetKey(flagSetName);
|
|
191
|
-
var
|
|
192
|
-
if (!
|
|
195
|
+
var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
|
|
196
|
+
if (!flagSetFromLocalStorage)
|
|
193
197
|
return;
|
|
194
|
-
var flagSetCache = new Set(JSON.parse(
|
|
198
|
+
var flagSetCache = new Set(JSON.parse(flagSetFromLocalStorage));
|
|
195
199
|
flagSetCache.delete(featureFlagName);
|
|
196
200
|
if (flagSetCache.size === 0) {
|
|
197
|
-
|
|
201
|
+
localStorage.removeItem(flagSetKey);
|
|
198
202
|
return;
|
|
199
203
|
}
|
|
200
|
-
|
|
204
|
+
localStorage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
|
|
201
205
|
};
|
|
202
206
|
return SplitsCacheInLocal;
|
|
203
207
|
}(AbstractSplitsCacheSync_1.AbstractSplitsCacheSync));
|
|
@@ -17,20 +17,6 @@ var TelemetryCacheInMemory_1 = require("../inMemory/TelemetryCacheInMemory");
|
|
|
17
17
|
var UniqueKeysCacheInMemoryCS_1 = require("../inMemory/UniqueKeysCacheInMemoryCS");
|
|
18
18
|
var key_1 = require("../../utils/key");
|
|
19
19
|
var validateCache_1 = require("./validateCache");
|
|
20
|
-
var storageAdapter_1 = require("./storageAdapter");
|
|
21
|
-
function validateStorage(log, prefix, wrapper) {
|
|
22
|
-
if (wrapper) {
|
|
23
|
-
if ((0, isLocalStorageAvailable_1.isValidStorageWrapper)(wrapper)) {
|
|
24
|
-
return (0, isLocalStorageAvailable_1.isWebStorage)(wrapper) ?
|
|
25
|
-
wrapper : // localStorage and sessionStorage don't need adapter
|
|
26
|
-
(0, storageAdapter_1.storageAdapter)(log, prefix, wrapper);
|
|
27
|
-
}
|
|
28
|
-
log.warn(constants_1.LOG_PREFIX + 'Invalid storage provided. Falling back to LocalStorage API');
|
|
29
|
-
}
|
|
30
|
-
if ((0, isLocalStorageAvailable_1.isLocalStorageAvailable)())
|
|
31
|
-
return localStorage;
|
|
32
|
-
log.warn(constants_1.LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
|
|
33
|
-
}
|
|
34
20
|
/**
|
|
35
21
|
* InLocal storage factory for standalone client-side SplitFactory
|
|
36
22
|
*/
|
|
@@ -38,17 +24,18 @@ function InLocalStorage(options) {
|
|
|
38
24
|
if (options === void 0) { options = {}; }
|
|
39
25
|
var prefix = (0, KeyBuilder_1.validatePrefix)(options.prefix);
|
|
40
26
|
function InLocalStorageCSFactory(params) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
27
|
+
// Fallback to InMemoryStorage if LocalStorage API is not available
|
|
28
|
+
if (!(0, isLocalStorageAvailable_1.isLocalStorageAvailable)()) {
|
|
29
|
+
params.settings.log.warn(constants_1.LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
|
|
44
30
|
return (0, InMemoryStorageCS_1.InMemoryStorageCSFactory)(params);
|
|
31
|
+
}
|
|
32
|
+
var settings = params.settings, _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize;
|
|
45
33
|
var matchingKey = (0, key_1.getMatching)(settings.core.key);
|
|
46
34
|
var keys = new KeyBuilderCS_1.KeyBuilderCS(prefix, matchingKey);
|
|
47
|
-
var splits = new SplitsCacheInLocal_1.SplitsCacheInLocal(settings, keys
|
|
48
|
-
var rbSegments = new RBSegmentsCacheInLocal_1.RBSegmentsCacheInLocal(settings, keys
|
|
49
|
-
var segments = new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, keys
|
|
50
|
-
var largeSegments = new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, (0, KeyBuilderCS_1.myLargeSegmentsKeyBuilder)(prefix, matchingKey)
|
|
51
|
-
var validateCachePromise;
|
|
35
|
+
var splits = new SplitsCacheInLocal_1.SplitsCacheInLocal(settings, keys);
|
|
36
|
+
var rbSegments = new RBSegmentsCacheInLocal_1.RBSegmentsCacheInLocal(settings, keys);
|
|
37
|
+
var segments = new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, keys);
|
|
38
|
+
var largeSegments = new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, (0, KeyBuilderCS_1.myLargeSegmentsKeyBuilder)(prefix, matchingKey));
|
|
52
39
|
return {
|
|
53
40
|
splits: splits,
|
|
54
41
|
rbSegments: rbSegments,
|
|
@@ -60,18 +47,16 @@ function InLocalStorage(options) {
|
|
|
60
47
|
telemetry: (0, TelemetryCacheInMemory_1.shouldRecordTelemetry)(params) ? new TelemetryCacheInMemory_1.TelemetryCacheInMemory(splits, segments) : undefined,
|
|
61
48
|
uniqueKeys: new UniqueKeysCacheInMemoryCS_1.UniqueKeysCacheInMemoryCS(),
|
|
62
49
|
validateCache: function () {
|
|
63
|
-
return
|
|
64
|
-
},
|
|
65
|
-
destroy: function () {
|
|
66
|
-
return storage.save && storage.save();
|
|
50
|
+
return (0, validateCache_1.validateCache)(options, settings, keys, splits, rbSegments, segments, largeSegments);
|
|
67
51
|
},
|
|
52
|
+
destroy: function () { },
|
|
68
53
|
// When using shared instantiation with MEMORY we reuse everything but segments (they are customer per key).
|
|
69
54
|
shared: function (matchingKey) {
|
|
70
55
|
return {
|
|
71
56
|
splits: this.splits,
|
|
72
57
|
rbSegments: this.rbSegments,
|
|
73
|
-
segments: new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, new KeyBuilderCS_1.KeyBuilderCS(prefix, matchingKey)
|
|
74
|
-
largeSegments: new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, (0, KeyBuilderCS_1.myLargeSegmentsKeyBuilder)(prefix, matchingKey)
|
|
58
|
+
segments: new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, new KeyBuilderCS_1.KeyBuilderCS(prefix, matchingKey)),
|
|
59
|
+
largeSegments: new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, (0, KeyBuilderCS_1.myLargeSegmentsKeyBuilder)(prefix, matchingKey)),
|
|
75
60
|
impressions: this.impressions,
|
|
76
61
|
impressionCounts: this.impressionCounts,
|
|
77
62
|
events: this.events,
|
|
@@ -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,26 +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
|
-
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);
|
|
77
74
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
// Check if ready from cache
|
|
78
|
+
return isThereCache;
|
|
81
79
|
}
|
|
82
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);
|
|
@@ -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;
|
|
@@ -20,45 +20,37 @@ var AbstractMySegmentsCacheSync = /** @class */ (function () {
|
|
|
20
20
|
*/
|
|
21
21
|
AbstractMySegmentsCacheSync.prototype.resetSegments = function (segmentsData) {
|
|
22
22
|
var _this = this;
|
|
23
|
+
this.setChangeNumber(segmentsData.cn);
|
|
23
24
|
var _a = segmentsData, added = _a.added, removed = _a.removed;
|
|
24
|
-
var isDiff = false;
|
|
25
25
|
if (added && removed) {
|
|
26
|
+
var isDiff_1 = false;
|
|
26
27
|
added.forEach(function (segment) {
|
|
27
|
-
|
|
28
|
+
isDiff_1 = _this.addSegment(segment) || isDiff_1;
|
|
28
29
|
});
|
|
29
30
|
removed.forEach(function (segment) {
|
|
30
|
-
|
|
31
|
+
isDiff_1 = _this.removeSegment(segment) || isDiff_1;
|
|
31
32
|
});
|
|
33
|
+
return isDiff_1;
|
|
32
34
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
// Slowest path => add and/or remove segments
|
|
50
|
-
for (var removeIndex = index; removeIndex < storedSegmentKeys.length; removeIndex++) {
|
|
51
|
-
this.removeSegment(storedSegmentKeys[removeIndex]);
|
|
52
|
-
}
|
|
53
|
-
for (var addIndex = index; addIndex < names.length; addIndex++) {
|
|
54
|
-
this.addSegment(names[addIndex]);
|
|
55
|
-
}
|
|
56
|
-
isDiff = true;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
35
|
+
var names = (segmentsData.k || []).map(function (s) { return s.n; }).sort();
|
|
36
|
+
var storedSegmentKeys = this.getRegisteredSegments().sort();
|
|
37
|
+
// Extreme fast => everything is empty
|
|
38
|
+
if (!names.length && !storedSegmentKeys.length)
|
|
39
|
+
return false;
|
|
40
|
+
var index = 0;
|
|
41
|
+
while (index < names.length && index < storedSegmentKeys.length && names[index] === storedSegmentKeys[index])
|
|
42
|
+
index++;
|
|
43
|
+
// Quick path => no changes
|
|
44
|
+
if (index === names.length && index === storedSegmentKeys.length)
|
|
45
|
+
return false;
|
|
46
|
+
// Slowest path => add and/or remove segments
|
|
47
|
+
for (var removeIndex = index; removeIndex < storedSegmentKeys.length; removeIndex++) {
|
|
48
|
+
this.removeSegment(storedSegmentKeys[removeIndex]);
|
|
59
49
|
}
|
|
60
|
-
|
|
61
|
-
|
|
50
|
+
for (var addIndex = index; addIndex < names.length; addIndex++) {
|
|
51
|
+
this.addSegment(names[addIndex]);
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
62
54
|
};
|
|
63
55
|
return AbstractMySegmentsCacheSync;
|
|
64
56
|
}());
|