@splitsoftware/splitio-commons 2.8.1-rc.0 → 2.8.1-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 +2 -3
- package/cjs/evaluator/index.js +13 -13
- package/cjs/sdkClient/client.js +3 -3
- package/cjs/storages/AbstractMySegmentsCacheSync.js +23 -31
- package/cjs/storages/AbstractSplitsCacheSync.js +2 -3
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +28 -10
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +33 -22
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +29 -19
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +2 -3
- package/cjs/storages/inRedis/SegmentsCacheInRedis.js +1 -1
- package/cjs/sync/polling/syncTasks/segmentsSyncTask.js +1 -1
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +5 -16
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +3 -3
- package/cjs/utils/inputValidation/eventProperties.js +6 -1
- package/esm/evaluator/index.js +13 -13
- package/esm/sdkClient/client.js +3 -3
- package/esm/storages/AbstractMySegmentsCacheSync.js +23 -31
- package/esm/storages/AbstractSplitsCacheSync.js +2 -3
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +29 -11
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +33 -22
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +29 -19
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +2 -3
- package/esm/storages/inRedis/SegmentsCacheInRedis.js +1 -1
- package/esm/sync/polling/syncTasks/segmentsSyncTask.js +1 -1
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +5 -16
- package/esm/sync/polling/updaters/splitChangesUpdater.js +3 -3
- package/esm/utils/inputValidation/eventProperties.js +6 -1
- package/package.json +1 -1
- package/src/evaluator/index.ts +14 -6
- package/src/sdkClient/client.ts +3 -3
- package/src/storages/AbstractMySegmentsCacheSync.ts +20 -26
- package/src/storages/AbstractSplitsCacheSync.ts +2 -3
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +24 -9
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +27 -18
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +29 -22
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +2 -3
- package/src/storages/inRedis/SegmentsCacheInRedis.ts +1 -1
- package/src/sync/polling/syncTasks/segmentsSyncTask.ts +0 -2
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +3 -3
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +4 -17
- package/src/sync/polling/updaters/splitChangesUpdater.ts +7 -6
- package/src/utils/inputValidation/eventProperties.ts +6 -1
- package/types/splitio.d.ts +10 -0
package/esm/evaluator/index.js
CHANGED
|
@@ -16,7 +16,7 @@ function treatmentsException(splitNames) {
|
|
|
16
16
|
});
|
|
17
17
|
return evaluations;
|
|
18
18
|
}
|
|
19
|
-
export function evaluateFeature(log, key, splitName, attributes, storage) {
|
|
19
|
+
export function evaluateFeature(log, key, splitName, attributes, storage, options) {
|
|
20
20
|
var parsedSplit;
|
|
21
21
|
try {
|
|
22
22
|
parsedSplit = storage.splits.getSplit(splitName);
|
|
@@ -26,14 +26,14 @@ export function evaluateFeature(log, key, splitName, attributes, storage) {
|
|
|
26
26
|
return treatmentException;
|
|
27
27
|
}
|
|
28
28
|
if (thenable(parsedSplit)) {
|
|
29
|
-
return parsedSplit.then(function (split) { return getEvaluation(log, key, split, attributes, storage); }).catch(
|
|
29
|
+
return parsedSplit.then(function (split) { return getEvaluation(log, key, split, attributes, storage, options); }).catch(
|
|
30
30
|
// Exception on async `getSplit` storage. For example, when the storage is redis or
|
|
31
31
|
// pluggable and there is a connection issue and we can't retrieve the split to be evaluated
|
|
32
32
|
function () { return treatmentException; });
|
|
33
33
|
}
|
|
34
|
-
return getEvaluation(log, key, parsedSplit, attributes, storage);
|
|
34
|
+
return getEvaluation(log, key, parsedSplit, attributes, storage, options);
|
|
35
35
|
}
|
|
36
|
-
export function evaluateFeatures(log, key, splitNames, attributes, storage) {
|
|
36
|
+
export function evaluateFeatures(log, key, splitNames, attributes, storage, options) {
|
|
37
37
|
var parsedSplits;
|
|
38
38
|
try {
|
|
39
39
|
parsedSplits = storage.splits.getSplits(splitNames);
|
|
@@ -43,15 +43,15 @@ export function evaluateFeatures(log, key, splitNames, attributes, storage) {
|
|
|
43
43
|
return treatmentsException(splitNames);
|
|
44
44
|
}
|
|
45
45
|
return thenable(parsedSplits) ?
|
|
46
|
-
parsedSplits.then(function (splits) { return getEvaluations(log, key, splitNames, splits, attributes, storage); })
|
|
46
|
+
parsedSplits.then(function (splits) { return getEvaluations(log, key, splitNames, splits, attributes, storage, options); })
|
|
47
47
|
.catch(function () {
|
|
48
48
|
// Exception on async `getSplits` storage. For example, when the storage is redis or
|
|
49
49
|
// pluggable and there is a connection issue and we can't retrieve the split to be evaluated
|
|
50
50
|
return treatmentsException(splitNames);
|
|
51
51
|
}) :
|
|
52
|
-
getEvaluations(log, key, splitNames, parsedSplits, attributes, storage);
|
|
52
|
+
getEvaluations(log, key, splitNames, parsedSplits, attributes, storage, options);
|
|
53
53
|
}
|
|
54
|
-
export function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, storage, method) {
|
|
54
|
+
export function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, storage, method, options) {
|
|
55
55
|
var storedFlagNames;
|
|
56
56
|
function evaluate(featureFlagsByFlagSets) {
|
|
57
57
|
var featureFlags = new Set();
|
|
@@ -65,7 +65,7 @@ export function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, stora
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
return featureFlags.size ?
|
|
68
|
-
evaluateFeatures(log, key, setToArray(featureFlags), attributes, storage) :
|
|
68
|
+
evaluateFeatures(log, key, setToArray(featureFlags), attributes, storage, options) :
|
|
69
69
|
{};
|
|
70
70
|
}
|
|
71
71
|
// get features by flag sets
|
|
@@ -84,7 +84,7 @@ export function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, stora
|
|
|
84
84
|
}) :
|
|
85
85
|
evaluate(storedFlagNames);
|
|
86
86
|
}
|
|
87
|
-
function getEvaluation(log, key, splitJSON, attributes, storage) {
|
|
87
|
+
function getEvaluation(log, key, splitJSON, attributes, storage, options) {
|
|
88
88
|
var evaluation = {
|
|
89
89
|
treatment: CONTROL,
|
|
90
90
|
label: SPLIT_NOT_FOUND,
|
|
@@ -98,23 +98,23 @@ function getEvaluation(log, key, splitJSON, attributes, storage) {
|
|
|
98
98
|
return evaluation.then(function (result) {
|
|
99
99
|
result.changeNumber = splitJSON.changeNumber;
|
|
100
100
|
result.config = splitJSON.configurations && splitJSON.configurations[result.treatment] || null;
|
|
101
|
-
result.impressionsDisabled = splitJSON.impressionsDisabled;
|
|
101
|
+
result.impressionsDisabled = (options === null || options === void 0 ? void 0 : options.impressionsDisabled) || splitJSON.impressionsDisabled;
|
|
102
102
|
return result;
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
105
|
else {
|
|
106
106
|
evaluation.changeNumber = splitJSON.changeNumber;
|
|
107
107
|
evaluation.config = splitJSON.configurations && splitJSON.configurations[evaluation.treatment] || null;
|
|
108
|
-
evaluation.impressionsDisabled = splitJSON.impressionsDisabled;
|
|
108
|
+
evaluation.impressionsDisabled = (options === null || options === void 0 ? void 0 : options.impressionsDisabled) || splitJSON.impressionsDisabled;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
return evaluation;
|
|
112
112
|
}
|
|
113
|
-
function getEvaluations(log, key, splitNames, splits, attributes, storage) {
|
|
113
|
+
function getEvaluations(log, key, splitNames, splits, attributes, storage, options) {
|
|
114
114
|
var result = {};
|
|
115
115
|
var thenables = [];
|
|
116
116
|
splitNames.forEach(function (splitName) {
|
|
117
|
-
var evaluation = getEvaluation(log, key, splits[splitName], attributes, storage);
|
|
117
|
+
var evaluation = getEvaluation(log, key, splits[splitName], attributes, storage, options);
|
|
118
118
|
if (thenable(evaluation)) {
|
|
119
119
|
thenables.push(evaluation.then(function (res) {
|
|
120
120
|
result[splitName] = res;
|
package/esm/sdkClient/client.js
CHANGED
|
@@ -42,7 +42,7 @@ export function clientFactory(params) {
|
|
|
42
42
|
return treatment;
|
|
43
43
|
};
|
|
44
44
|
var evaluation = readinessManager.isReadyFromCache() ?
|
|
45
|
-
evaluateFeature(log, key, featureFlagName, attributes, storage) :
|
|
45
|
+
evaluateFeature(log, key, featureFlagName, attributes, storage, options) :
|
|
46
46
|
isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
|
|
47
47
|
Promise.resolve(treatmentNotReady) :
|
|
48
48
|
treatmentNotReady;
|
|
@@ -67,7 +67,7 @@ export function clientFactory(params) {
|
|
|
67
67
|
return treatments;
|
|
68
68
|
};
|
|
69
69
|
var evaluations = readinessManager.isReadyFromCache() ?
|
|
70
|
-
evaluateFeatures(log, key, featureFlagNames, attributes, storage) :
|
|
70
|
+
evaluateFeatures(log, key, featureFlagNames, attributes, storage, options) :
|
|
71
71
|
isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
|
|
72
72
|
Promise.resolve(treatmentsNotReady(featureFlagNames)) :
|
|
73
73
|
treatmentsNotReady(featureFlagNames);
|
|
@@ -93,7 +93,7 @@ export function clientFactory(params) {
|
|
|
93
93
|
return treatments;
|
|
94
94
|
};
|
|
95
95
|
var evaluations = readinessManager.isReadyFromCache() ?
|
|
96
|
-
evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage, methodName) :
|
|
96
|
+
evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage, methodName, options) :
|
|
97
97
|
isAsync ?
|
|
98
98
|
Promise.resolve({}) :
|
|
99
99
|
{};
|
|
@@ -20,45 +20,37 @@ var AbstractMySegmentsCacheSync = /** @class */ (function () {
|
|
|
20
20
|
*/
|
|
21
21
|
AbstractMySegmentsCacheSync.prototype.resetSegments = function (segmentsData) {
|
|
22
22
|
var _this = this;
|
|
23
|
-
|
|
23
|
+
this.setChangeNumber(segmentsData.cn);
|
|
24
24
|
var _a = segmentsData, added = _a.added, removed = _a.removed;
|
|
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
|
}());
|
|
@@ -9,10 +9,9 @@ var AbstractSplitsCacheSync = /** @class */ (function () {
|
|
|
9
9
|
}
|
|
10
10
|
AbstractSplitsCacheSync.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
11
11
|
var _this = this;
|
|
12
|
-
var updated = toAdd.map(function (addedFF) { return _this.addSplit(addedFF); }).some(function (result) { return result; });
|
|
13
|
-
updated = toRemove.map(function (removedFF) { return _this.removeSplit(removedFF.name); }).some(function (result) { return result; }) || updated;
|
|
14
12
|
this.setChangeNumber(changeNumber);
|
|
15
|
-
return
|
|
13
|
+
var updated = toAdd.map(function (addedFF) { return _this.addSplit(addedFF); }).some(function (result) { return result; });
|
|
14
|
+
return toRemove.map(function (removedFF) { return _this.removeSplit(removedFF.name); }).some(function (result) { return result; }) || updated;
|
|
16
15
|
};
|
|
17
16
|
AbstractSplitsCacheSync.prototype.getSplits = function (names) {
|
|
18
17
|
var _this = this;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __extends } from "tslib";
|
|
2
2
|
import { isNaNNumber } from '../../utils/lang';
|
|
3
3
|
import { AbstractMySegmentsCacheSync } from '../AbstractMySegmentsCacheSync';
|
|
4
|
-
import { DEFINED } from './constants';
|
|
4
|
+
import { LOG_PREFIX, DEFINED } from './constants';
|
|
5
5
|
var MySegmentsCacheInLocal = /** @class */ (function (_super) {
|
|
6
6
|
__extends(MySegmentsCacheInLocal, _super);
|
|
7
7
|
function MySegmentsCacheInLocal(log, keys, storage) {
|
|
@@ -10,20 +10,33 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
|
|
|
10
10
|
_this.keys = keys;
|
|
11
11
|
_this.storage = storage;
|
|
12
12
|
return _this;
|
|
13
|
+
// There is not need to flush segments cache like splits cache, since resetSegments receives the up-to-date list of active segments
|
|
13
14
|
}
|
|
14
15
|
MySegmentsCacheInLocal.prototype.addSegment = function (name) {
|
|
15
16
|
var segmentKey = this.keys.buildSegmentNameKey(name);
|
|
16
|
-
|
|
17
|
+
try {
|
|
18
|
+
if (this.storage.getItem(segmentKey) === DEFINED)
|
|
19
|
+
return false;
|
|
20
|
+
this.storage.setItem(segmentKey, DEFINED);
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
this.log.error(LOG_PREFIX + e);
|
|
17
25
|
return false;
|
|
18
|
-
|
|
19
|
-
return true;
|
|
26
|
+
}
|
|
20
27
|
};
|
|
21
28
|
MySegmentsCacheInLocal.prototype.removeSegment = function (name) {
|
|
22
29
|
var segmentKey = this.keys.buildSegmentNameKey(name);
|
|
23
|
-
|
|
30
|
+
try {
|
|
31
|
+
if (this.storage.getItem(segmentKey) !== DEFINED)
|
|
32
|
+
return false;
|
|
33
|
+
this.storage.removeItem(segmentKey);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
this.log.error(LOG_PREFIX + e);
|
|
24
38
|
return false;
|
|
25
|
-
|
|
26
|
-
return true;
|
|
39
|
+
}
|
|
27
40
|
};
|
|
28
41
|
MySegmentsCacheInLocal.prototype.isInSegment = function (name) {
|
|
29
42
|
return this.storage.getItem(this.keys.buildSegmentNameKey(name)) === DEFINED;
|
|
@@ -41,10 +54,15 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
|
|
|
41
54
|
return 1;
|
|
42
55
|
};
|
|
43
56
|
MySegmentsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
try {
|
|
58
|
+
if (changeNumber)
|
|
59
|
+
this.storage.setItem(this.keys.buildTillKey(), changeNumber + '');
|
|
60
|
+
else
|
|
61
|
+
this.storage.removeItem(this.keys.buildTillKey());
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
this.log.error(e);
|
|
65
|
+
}
|
|
48
66
|
};
|
|
49
67
|
MySegmentsCacheInLocal.prototype.getChangeNumber = function () {
|
|
50
68
|
var n = -1;
|
|
@@ -15,10 +15,9 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
|
|
|
15
15
|
};
|
|
16
16
|
RBSegmentsCacheInLocal.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
17
17
|
var _this = this;
|
|
18
|
-
var updated = toAdd.map(function (toAdd) { return _this.add(toAdd); }).some(function (result) { return result; });
|
|
19
|
-
updated = toRemove.map(function (toRemove) { return _this.remove(toRemove.name); }).some(function (result) { return result; }) || updated;
|
|
20
18
|
this.setChangeNumber(changeNumber);
|
|
21
|
-
return
|
|
19
|
+
var updated = toAdd.map(function (toAdd) { return _this.add(toAdd); }).some(function (result) { return result; });
|
|
20
|
+
return toRemove.map(function (toRemove) { return _this.remove(toRemove.name); }).some(function (result) { return result; }) || updated;
|
|
22
21
|
};
|
|
23
22
|
RBSegmentsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
|
|
24
23
|
try {
|
|
@@ -38,28 +37,40 @@ var RBSegmentsCacheInLocal = /** @class */ (function () {
|
|
|
38
37
|
this.storage.removeItem(segmentsCountKey);
|
|
39
38
|
};
|
|
40
39
|
RBSegmentsCacheInLocal.prototype.add = function (rbSegment) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
40
|
+
try {
|
|
41
|
+
var name_1 = rbSegment.name;
|
|
42
|
+
var rbSegmentKey = this.keys.buildRBSegmentKey(name_1);
|
|
43
|
+
var rbSegmentFromStorage = this.storage.getItem(rbSegmentKey);
|
|
44
|
+
var previous = rbSegmentFromStorage ? JSON.parse(rbSegmentFromStorage) : null;
|
|
45
|
+
this.storage.setItem(rbSegmentKey, JSON.stringify(rbSegment));
|
|
46
|
+
var usesSegmentsDiff = 0;
|
|
47
|
+
if (previous && usesSegments(previous))
|
|
48
|
+
usesSegmentsDiff--;
|
|
49
|
+
if (usesSegments(rbSegment))
|
|
50
|
+
usesSegmentsDiff++;
|
|
51
|
+
if (usesSegmentsDiff !== 0)
|
|
52
|
+
this.updateSegmentCount(usesSegmentsDiff);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
this.log.error(LOG_PREFIX + e);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
54
59
|
};
|
|
55
60
|
RBSegmentsCacheInLocal.prototype.remove = function (name) {
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
try {
|
|
62
|
+
var rbSegment = this.get(name);
|
|
63
|
+
if (!rbSegment)
|
|
64
|
+
return false;
|
|
65
|
+
this.storage.removeItem(this.keys.buildRBSegmentKey(name));
|
|
66
|
+
if (usesSegments(rbSegment))
|
|
67
|
+
this.updateSegmentCount(-1);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
this.log.error(LOG_PREFIX + e);
|
|
58
72
|
return false;
|
|
59
|
-
|
|
60
|
-
if (usesSegments(rbSegment))
|
|
61
|
-
this.updateSegmentCount(-1);
|
|
62
|
-
return true;
|
|
73
|
+
}
|
|
63
74
|
};
|
|
64
75
|
RBSegmentsCacheInLocal.prototype.getNames = function () {
|
|
65
76
|
var len = this.storage.length;
|
|
@@ -67,27 +67,39 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
67
67
|
this.hasSync = false;
|
|
68
68
|
};
|
|
69
69
|
SplitsCacheInLocal.prototype.addSplit = function (split) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
70
|
+
try {
|
|
71
|
+
var name_1 = split.name;
|
|
72
|
+
var splitKey = this.keys.buildSplitKey(name_1);
|
|
73
|
+
var splitFromStorage = this.storage.getItem(splitKey);
|
|
74
|
+
var previousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : null;
|
|
75
|
+
if (previousSplit) {
|
|
76
|
+
this._decrementCounts(previousSplit);
|
|
77
|
+
this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
|
|
78
|
+
}
|
|
79
|
+
this.storage.setItem(splitKey, JSON.stringify(split));
|
|
80
|
+
this._incrementCounts(split);
|
|
81
|
+
this.addToFlagSets(split);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
this.log.error(LOG_PREFIX + e);
|
|
86
|
+
return false;
|
|
77
87
|
}
|
|
78
|
-
this.storage.setItem(splitKey, JSON.stringify(split));
|
|
79
|
-
this._incrementCounts(split);
|
|
80
|
-
this.addToFlagSets(split);
|
|
81
|
-
return true;
|
|
82
88
|
};
|
|
83
89
|
SplitsCacheInLocal.prototype.removeSplit = function (name) {
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
try {
|
|
91
|
+
var split = this.getSplit(name);
|
|
92
|
+
if (!split)
|
|
93
|
+
return false;
|
|
94
|
+
this.storage.removeItem(this.keys.buildSplitKey(name));
|
|
95
|
+
this._decrementCounts(split);
|
|
96
|
+
this.removeFromFlagSets(split.name, split.sets);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
this.log.error(LOG_PREFIX + e);
|
|
86
101
|
return false;
|
|
87
|
-
|
|
88
|
-
this._decrementCounts(split);
|
|
89
|
-
this.removeFromFlagSets(split.name, split.sets);
|
|
90
|
-
return true;
|
|
102
|
+
}
|
|
91
103
|
};
|
|
92
104
|
SplitsCacheInLocal.prototype.getSplit = function (name) {
|
|
93
105
|
var item = this.storage.getItem(this.keys.buildSplitKey(name));
|
|
@@ -159,8 +171,6 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
159
171
|
var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
|
|
160
172
|
var flagSetFromStorage = _this.storage.getItem(flagSetKey);
|
|
161
173
|
var flagSetCache = new Set(flagSetFromStorage ? JSON.parse(flagSetFromStorage) : []);
|
|
162
|
-
if (flagSetCache.has(featureFlag.name))
|
|
163
|
-
return;
|
|
164
174
|
flagSetCache.add(featureFlag.name);
|
|
165
175
|
_this.storage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
|
|
166
176
|
});
|
|
@@ -13,10 +13,9 @@ var RBSegmentsCacheInMemory = /** @class */ (function () {
|
|
|
13
13
|
};
|
|
14
14
|
RBSegmentsCacheInMemory.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
15
15
|
var _this = this;
|
|
16
|
-
var updated = toAdd.map(function (toAdd) { return _this.add(toAdd); }).some(function (result) { return result; });
|
|
17
|
-
updated = toRemove.map(function (toRemove) { return _this.remove(toRemove.name); }).some(function (result) { return result; }) || updated;
|
|
18
16
|
this.changeNumber = changeNumber;
|
|
19
|
-
return
|
|
17
|
+
var updated = toAdd.map(function (toAdd) { return _this.add(toAdd); }).some(function (result) { return result; });
|
|
18
|
+
return toRemove.map(function (toRemove) { return _this.remove(toRemove.name); }).some(function (result) { return result; }) || updated;
|
|
20
19
|
};
|
|
21
20
|
RBSegmentsCacheInMemory.prototype.add = function (rbSegment) {
|
|
22
21
|
var name = rbSegment.name;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isNaNNumber } from '../../utils/lang';
|
|
2
|
-
import { LOG_PREFIX } from '
|
|
2
|
+
import { LOG_PREFIX } from '../inLocalStorage/constants';
|
|
3
3
|
var SegmentsCacheInRedis = /** @class */ (function () {
|
|
4
4
|
function SegmentsCacheInRedis(log, keys, redis) {
|
|
5
5
|
this.log = log;
|
|
@@ -5,5 +5,5 @@ import { segmentChangesUpdaterFactory } from '../updaters/segmentChangesUpdater'
|
|
|
5
5
|
* Creates a sync task that periodically executes a `segmentChangesUpdater` task
|
|
6
6
|
*/
|
|
7
7
|
export function segmentsSyncTaskFactory(fetchSegmentChanges, storage, readiness, settings) {
|
|
8
|
-
return syncTaskFactory(settings.log, segmentChangesUpdaterFactory(settings.log, segmentChangesFetcherFactory(fetchSegmentChanges), storage.segments, readiness
|
|
8
|
+
return syncTaskFactory(settings.log, segmentChangesUpdaterFactory(settings.log, segmentChangesFetcherFactory(fetchSegmentChanges), storage.segments, readiness), settings.scheduler.segmentsRefreshRate, 'segmentChangesUpdater');
|
|
9
9
|
}
|
|
@@ -45,9 +45,9 @@ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmen
|
|
|
45
45
|
new Promise(function (res) { updateSegments(segmentsData); res(true); }) :
|
|
46
46
|
// If not provided, fetch mySegments
|
|
47
47
|
mySegmentsFetcher(matchingKey, noCache, till, _promiseDecorator).then(function (segments) {
|
|
48
|
-
|
|
49
|
-
// Only when we have downloaded and stored segments completely, we should not keep retrying anymore
|
|
48
|
+
// Only when we have downloaded segments completely, we should not keep retrying anymore
|
|
50
49
|
startingUp = false;
|
|
50
|
+
updateSegments(segments);
|
|
51
51
|
return true;
|
|
52
52
|
});
|
|
53
53
|
return updaterPromise.catch(function (error) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
|
|
2
2
|
import { LOG_PREFIX_INSTANTIATION, LOG_PREFIX_SYNC_SEGMENTS } from '../../../logger/constants';
|
|
3
|
-
import { timeout } from '../../../utils/promise/timeout';
|
|
4
3
|
/**
|
|
5
4
|
* Factory of SegmentChanges updater, a task that:
|
|
6
5
|
* - fetches segment changes using `segmentChangesFetcher`
|
|
@@ -12,33 +11,22 @@ import { timeout } from '../../../utils/promise/timeout';
|
|
|
12
11
|
* @param segments - segments storage, with sync or async methods
|
|
13
12
|
* @param readiness - optional readiness manager. Not required for synchronizer or producer mode.
|
|
14
13
|
*/
|
|
15
|
-
export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segments, readiness
|
|
14
|
+
export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segments, readiness) {
|
|
16
15
|
var readyOnAlreadyExistentState = true;
|
|
17
|
-
function
|
|
18
|
-
if (readyOnAlreadyExistentState && requestTimeoutBeforeReady)
|
|
19
|
-
promise = timeout(requestTimeoutBeforeReady, promise);
|
|
20
|
-
return promise;
|
|
21
|
-
}
|
|
22
|
-
function updateSegment(segmentName, noCache, till, fetchOnlyNew, retries) {
|
|
16
|
+
function updateSegment(segmentName, noCache, till, fetchOnlyNew) {
|
|
23
17
|
log.debug(LOG_PREFIX_SYNC_SEGMENTS + "Processing segment " + segmentName);
|
|
24
18
|
var sincePromise = Promise.resolve(segments.getChangeNumber(segmentName));
|
|
25
19
|
return sincePromise.then(function (since) {
|
|
26
20
|
// if fetchOnlyNew flag, avoid processing already fetched segments
|
|
27
21
|
return fetchOnlyNew && since !== undefined ?
|
|
28
22
|
false :
|
|
29
|
-
segmentChangesFetcher(since || -1, segmentName, noCache, till
|
|
23
|
+
segmentChangesFetcher(since || -1, segmentName, noCache, till).then(function (changes) {
|
|
30
24
|
return Promise.all(changes.map(function (x) {
|
|
31
25
|
log.debug(LOG_PREFIX_SYNC_SEGMENTS + "Processing " + segmentName + " with till = " + x.till + ". Added: " + x.added.length + ". Removed: " + x.removed.length);
|
|
32
26
|
return segments.update(segmentName, x.added, x.removed, x.till);
|
|
33
27
|
})).then(function (updates) {
|
|
34
28
|
return updates.some(function (update) { return update; });
|
|
35
29
|
});
|
|
36
|
-
}).catch(function (error) {
|
|
37
|
-
if (retries) {
|
|
38
|
-
log.warn(LOG_PREFIX_SYNC_SEGMENTS + "Retrying fetch of segment " + segmentName + " (attempt #" + retries + "). Reason: " + error);
|
|
39
|
-
return updateSegment(segmentName, noCache, till, fetchOnlyNew, retries - 1);
|
|
40
|
-
}
|
|
41
|
-
throw error;
|
|
42
30
|
});
|
|
43
31
|
});
|
|
44
32
|
}
|
|
@@ -58,7 +46,8 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
|
|
|
58
46
|
// If not a segment name provided, read list of available segments names to be updated.
|
|
59
47
|
var segmentsPromise = Promise.resolve(segmentName ? [segmentName] : segments.getRegisteredSegments());
|
|
60
48
|
return segmentsPromise.then(function (segmentNames) {
|
|
61
|
-
|
|
49
|
+
// Async fetchers
|
|
50
|
+
var updaters = segmentNames.map(function (segmentName) { return updateSegment(segmentName, noCache, till, fetchOnlyNew); });
|
|
62
51
|
return Promise.all(updaters).then(function (shouldUpdateFlags) {
|
|
63
52
|
// if at least one segment fetch succeeded, mark segments ready
|
|
64
53
|
if (shouldUpdateFlags.some(function (update) { return update; }) || readyOnAlreadyExistentState) {
|
|
@@ -130,6 +130,7 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, sp
|
|
|
130
130
|
{ rbs: { d: [instantUpdate.payload], t: instantUpdate.changeNumber } } :
|
|
131
131
|
splitChangesFetcher(since, noCache, till, rbSince, _promiseDecorator))
|
|
132
132
|
.then(function (splitChanges) {
|
|
133
|
+
startingUp = false;
|
|
133
134
|
var usedSegments = new Set();
|
|
134
135
|
var ffUpdate = false;
|
|
135
136
|
if (splitChanges.ff) {
|
|
@@ -150,7 +151,6 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, sp
|
|
|
150
151
|
var ffChanged = _a[0], rbsChanged = _a[1];
|
|
151
152
|
if (storage.save)
|
|
152
153
|
storage.save();
|
|
153
|
-
startingUp = false;
|
|
154
154
|
if (splitsEventEmitter) {
|
|
155
155
|
// To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
|
|
156
156
|
return Promise.resolve(!splitsEventEmitter.splitsArrived || ((ffChanged || rbsChanged) && (isClientSide || checkAllSegmentsExist(segments))))
|
|
@@ -166,14 +166,14 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, sp
|
|
|
166
166
|
});
|
|
167
167
|
})
|
|
168
168
|
.catch(function (error) {
|
|
169
|
+
log.warn(SYNC_SPLITS_FETCH_FAILS, [error]);
|
|
169
170
|
if (startingUp && retriesOnFailureBeforeReady > retry) {
|
|
170
171
|
retry += 1;
|
|
171
|
-
log.
|
|
172
|
+
log.info(SYNC_SPLITS_FETCH_RETRY, [retry, error]);
|
|
172
173
|
return _splitChangesUpdater(sinces, retry);
|
|
173
174
|
}
|
|
174
175
|
else {
|
|
175
176
|
startingUp = false;
|
|
176
|
-
log.warn(SYNC_SPLITS_FETCH_FAILS, [error]);
|
|
177
177
|
}
|
|
178
178
|
return false;
|
|
179
179
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { __assign } from "tslib";
|
|
1
2
|
import { isObject, isString, isFiniteNumber, isBoolean } from '../lang';
|
|
2
3
|
import { objectAssign } from '../lang/objectAssign';
|
|
3
4
|
import { ERROR_NOT_PLAIN_OBJECT, ERROR_SIZE_EXCEEDED, WARN_SETTING_NULL, WARN_TRIMMING_PROPERTIES } from '../../logger/constants';
|
|
@@ -60,7 +61,11 @@ export function validateEventProperties(log, maybeProperties, method) {
|
|
|
60
61
|
export function validateEvaluationOptions(log, maybeOptions, method) {
|
|
61
62
|
if (isObject(maybeOptions)) {
|
|
62
63
|
var properties = validateEventProperties(log, maybeOptions.properties, method).properties;
|
|
63
|
-
|
|
64
|
+
var options = properties && Object.keys(properties).length > 0 ? { properties: properties } : undefined;
|
|
65
|
+
var impressionsDisabled = maybeOptions.impressionsDisabled;
|
|
66
|
+
if (!impressionsDisabled)
|
|
67
|
+
return options;
|
|
68
|
+
return options ? __assign(__assign({}, options), { impressionsDisabled: impressionsDisabled }) : { impressionsDisabled: impressionsDisabled };
|
|
64
69
|
}
|
|
65
70
|
else if (maybeOptions) {
|
|
66
71
|
log.error(ERROR_NOT_PLAIN_OBJECT, [method, 'evaluation options']);
|