@splitsoftware/splitio-commons 2.1.0-rc.2 → 2.1.1-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 -7
- package/README.md +1 -0
- package/cjs/evaluator/combiners/and.js +2 -6
- package/cjs/evaluator/combiners/ifelseif.js +6 -6
- package/cjs/evaluator/condition/index.js +6 -5
- package/cjs/evaluator/index.js +7 -7
- package/cjs/evaluator/matchers/index.js +3 -1
- package/cjs/evaluator/matchers/matcherTypes.js +1 -0
- package/cjs/evaluator/matchers/rbsegment.js +43 -0
- package/cjs/evaluator/matchersTransform/index.js +4 -0
- package/cjs/evaluator/parser/index.js +2 -2
- package/cjs/evaluator/value/sanitize.js +1 -0
- package/cjs/logger/constants.js +5 -6
- package/cjs/logger/messages/debug.js +3 -4
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/readiness/readinessManager.js +0 -6
- package/cjs/services/splitApi.js +2 -2
- package/cjs/storages/AbstractSplitsCacheAsync.js +19 -1
- package/cjs/storages/AbstractSplitsCacheSync.js +17 -9
- package/cjs/storages/KeyBuilder.js +8 -15
- package/cjs/storages/KeyBuilderCS.js +11 -5
- package/cjs/storages/KeyBuilderSS.js +3 -0
- package/cjs/storages/dataLoader.js +3 -5
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +117 -0
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +69 -15
- package/cjs/storages/inLocalStorage/index.js +7 -5
- package/cjs/storages/inMemory/InMemoryStorage.js +3 -0
- package/cjs/storages/inMemory/InMemoryStorageCS.js +4 -0
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +61 -0
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +24 -31
- package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +64 -0
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +4 -21
- package/cjs/storages/inRedis/constants.js +1 -1
- package/cjs/storages/inRedis/index.js +2 -0
- package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +64 -0
- package/cjs/storages/pluggable/SplitsCachePluggable.js +2 -19
- package/cjs/storages/pluggable/index.js +3 -2
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +14 -16
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +2 -2
- package/cjs/sync/polling/pollingManagerCS.js +7 -7
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +1 -1
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +62 -51
- package/cjs/sync/streaming/SSEHandler/index.js +1 -0
- package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +106 -77
- package/cjs/sync/streaming/constants.js +2 -1
- package/cjs/sync/streaming/pushManager.js +3 -16
- package/cjs/sync/syncManagerOnline.js +5 -10
- package/cjs/trackers/uniqueKeysTracker.js +1 -1
- package/cjs/utils/constants/browser.js +5 -0
- package/cjs/utils/constants/index.js +3 -2
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/esm/evaluator/combiners/and.js +2 -6
- package/esm/evaluator/combiners/ifelseif.js +7 -7
- package/esm/evaluator/condition/index.js +6 -5
- package/esm/evaluator/index.js +7 -7
- package/esm/evaluator/matchers/index.js +3 -1
- package/esm/evaluator/matchers/matcherTypes.js +1 -0
- package/esm/evaluator/matchers/rbsegment.js +39 -0
- package/esm/evaluator/matchersTransform/index.js +4 -0
- package/esm/evaluator/parser/index.js +2 -2
- package/esm/evaluator/value/sanitize.js +1 -0
- package/esm/logger/constants.js +2 -3
- package/esm/logger/messages/debug.js +3 -4
- package/esm/logger/messages/warn.js +1 -1
- package/esm/readiness/readinessManager.js +0 -6
- package/esm/services/splitApi.js +2 -2
- package/esm/storages/AbstractSplitsCacheAsync.js +19 -1
- package/esm/storages/AbstractSplitsCacheSync.js +17 -9
- package/esm/storages/KeyBuilder.js +8 -15
- package/esm/storages/KeyBuilderCS.js +11 -5
- package/esm/storages/KeyBuilderSS.js +3 -0
- package/esm/storages/dataLoader.js +2 -4
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +114 -0
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +69 -15
- package/esm/storages/inLocalStorage/index.js +7 -5
- package/esm/storages/inMemory/InMemoryStorage.js +3 -0
- package/esm/storages/inMemory/InMemoryStorageCS.js +4 -0
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +58 -0
- package/esm/storages/inMemory/SplitsCacheInMemory.js +24 -31
- package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +61 -0
- package/esm/storages/inRedis/SplitsCacheInRedis.js +4 -21
- package/esm/storages/inRedis/constants.js +1 -1
- package/esm/storages/inRedis/index.js +2 -0
- package/esm/storages/pluggable/RBSegmentsCachePluggable.js +61 -0
- package/esm/storages/pluggable/SplitsCachePluggable.js +2 -19
- package/esm/storages/pluggable/index.js +3 -2
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +14 -16
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +2 -2
- package/esm/sync/polling/pollingManagerCS.js +7 -7
- package/esm/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +1 -1
- package/esm/sync/polling/updaters/splitChangesUpdater.js +63 -52
- package/esm/sync/streaming/SSEHandler/index.js +2 -1
- package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +102 -73
- package/esm/sync/streaming/constants.js +1 -0
- package/esm/sync/streaming/pushManager.js +6 -19
- package/esm/sync/syncManagerOnline.js +5 -10
- package/esm/trackers/uniqueKeysTracker.js +1 -1
- package/esm/utils/constants/browser.js +2 -0
- package/esm/utils/constants/index.js +2 -1
- package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
- package/package.json +1 -1
- package/src/dtos/types.ts +32 -8
- package/src/evaluator/Engine.ts +1 -1
- package/src/evaluator/combiners/and.ts +5 -4
- package/src/evaluator/combiners/ifelseif.ts +7 -9
- package/src/evaluator/condition/engineUtils.ts +1 -1
- package/src/evaluator/condition/index.ts +12 -12
- package/src/evaluator/index.ts +7 -7
- package/src/evaluator/matchers/index.ts +3 -1
- package/src/evaluator/matchers/matcherTypes.ts +1 -0
- package/src/evaluator/matchers/rbsegment.ts +61 -0
- package/src/evaluator/matchersTransform/index.ts +3 -0
- package/src/evaluator/parser/index.ts +3 -3
- package/src/evaluator/types.ts +2 -2
- package/src/evaluator/value/index.ts +2 -2
- package/src/evaluator/value/sanitize.ts +5 -4
- package/src/logger/constants.ts +2 -3
- package/src/logger/messages/debug.ts +3 -4
- package/src/logger/messages/warn.ts +1 -1
- package/src/readiness/readinessManager.ts +0 -5
- package/src/sdkManager/index.ts +1 -1
- package/src/services/splitApi.ts +2 -2
- package/src/services/types.ts +1 -1
- package/src/storages/AbstractSplitsCacheAsync.ts +23 -5
- package/src/storages/AbstractSplitsCacheSync.ts +22 -15
- package/src/storages/KeyBuilder.ts +9 -17
- package/src/storages/KeyBuilderCS.ts +13 -6
- package/src/storages/KeyBuilderSS.ts +4 -0
- package/src/storages/dataLoader.ts +2 -5
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +136 -0
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +80 -16
- package/src/storages/inLocalStorage/index.ts +12 -8
- package/src/storages/inMemory/InMemoryStorage.ts +3 -0
- package/src/storages/inMemory/InMemoryStorageCS.ts +4 -0
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +68 -0
- package/src/storages/inMemory/SplitsCacheInMemory.ts +22 -27
- package/src/storages/inRedis/RBSegmentsCacheInRedis.ts +79 -0
- package/src/storages/inRedis/SplitsCacheInRedis.ts +4 -21
- package/src/storages/inRedis/constants.ts +1 -1
- package/src/storages/inRedis/index.ts +2 -0
- package/src/storages/pluggable/RBSegmentsCachePluggable.ts +76 -0
- package/src/storages/pluggable/SplitsCachePluggable.ts +2 -19
- package/src/storages/pluggable/index.ts +3 -2
- package/src/storages/types.ts +47 -18
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +19 -21
- package/src/sync/polling/fetchers/splitChangesFetcher.ts +2 -1
- package/src/sync/polling/fetchers/types.ts +1 -0
- package/src/sync/polling/pollingManagerCS.ts +7 -7
- package/src/sync/polling/syncTasks/splitsSyncTask.ts +1 -2
- package/src/sync/polling/types.ts +2 -2
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +2 -2
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +1 -1
- package/src/sync/polling/updaters/splitChangesUpdater.ts +74 -63
- package/src/sync/streaming/SSEHandler/index.ts +2 -1
- package/src/sync/streaming/SSEHandler/types.ts +2 -2
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +98 -68
- package/src/sync/streaming/constants.ts +1 -0
- package/src/sync/streaming/parseUtils.ts +2 -2
- package/src/sync/streaming/pushManager.ts +6 -18
- package/src/sync/streaming/types.ts +3 -2
- package/src/sync/syncManagerOnline.ts +5 -11
- package/src/trackers/uniqueKeysTracker.ts +1 -1
- package/src/utils/constants/browser.ts +2 -0
- package/src/utils/constants/index.ts +2 -1
- package/src/utils/lang/index.ts +2 -2
- package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
- package/types/splitio.d.ts +1 -25
- package/cjs/storages/inLocalStorage/validateCache.js +0 -79
- package/esm/storages/inLocalStorage/validateCache.js +0 -75
- package/src/storages/inLocalStorage/validateCache.ts +0 -91
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RBSegmentsCachePluggable = void 0;
|
|
4
|
+
var lang_1 = require("../../utils/lang");
|
|
5
|
+
var constants_1 = require("./constants");
|
|
6
|
+
var sets_1 = require("../../utils/lang/sets");
|
|
7
|
+
var RBSegmentsCachePluggable = /** @class */ (function () {
|
|
8
|
+
function RBSegmentsCachePluggable(log, keys, wrapper) {
|
|
9
|
+
this.log = log;
|
|
10
|
+
this.keys = keys;
|
|
11
|
+
this.wrapper = wrapper;
|
|
12
|
+
}
|
|
13
|
+
RBSegmentsCachePluggable.prototype.get = function (name) {
|
|
14
|
+
return this.wrapper.get(this.keys.buildRBSegmentKey(name))
|
|
15
|
+
.then(function (maybeRBSegment) { return maybeRBSegment && JSON.parse(maybeRBSegment); });
|
|
16
|
+
};
|
|
17
|
+
RBSegmentsCachePluggable.prototype.getNames = function () {
|
|
18
|
+
var _this = this;
|
|
19
|
+
return this.wrapper.getKeysByPrefix(this.keys.buildRBSegmentKeyPrefix()).then(function (listOfKeys) { return listOfKeys.map(_this.keys.extractKey); });
|
|
20
|
+
};
|
|
21
|
+
RBSegmentsCachePluggable.prototype.contains = function (names) {
|
|
22
|
+
var namesArray = (0, sets_1.setToArray)(names);
|
|
23
|
+
return this.getNames().then(function (namesInStorage) {
|
|
24
|
+
return namesArray.every(function (name) { return namesInStorage.includes(name); });
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
RBSegmentsCachePluggable.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
28
|
+
var _this = this;
|
|
29
|
+
return Promise.all([
|
|
30
|
+
this.setChangeNumber(changeNumber),
|
|
31
|
+
Promise.all(toAdd.map(function (toAdd) {
|
|
32
|
+
var key = _this.keys.buildRBSegmentKey(toAdd.name);
|
|
33
|
+
var stringifiedNewRBSegment = JSON.stringify(toAdd);
|
|
34
|
+
return _this.wrapper.set(key, stringifiedNewRBSegment).then(function () { return true; });
|
|
35
|
+
})),
|
|
36
|
+
Promise.all(toRemove.map(function (toRemove) {
|
|
37
|
+
var key = _this.keys.buildRBSegmentKey(toRemove.name);
|
|
38
|
+
return _this.wrapper.del(key);
|
|
39
|
+
}))
|
|
40
|
+
]).then(function (_a) {
|
|
41
|
+
var added = _a[1], removed = _a[2];
|
|
42
|
+
return added.some(function (result) { return result; }) || removed.some(function (result) { return result; });
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
RBSegmentsCachePluggable.prototype.setChangeNumber = function (changeNumber) {
|
|
46
|
+
return this.wrapper.set(this.keys.buildRBSegmentsTillKey(), changeNumber + '');
|
|
47
|
+
};
|
|
48
|
+
RBSegmentsCachePluggable.prototype.getChangeNumber = function () {
|
|
49
|
+
var _this = this;
|
|
50
|
+
return this.wrapper.get(this.keys.buildRBSegmentsTillKey()).then(function (value) {
|
|
51
|
+
var i = parseInt(value, 10);
|
|
52
|
+
return (0, lang_1.isNaNNumber)(i) ? -1 : i;
|
|
53
|
+
}).catch(function (e) {
|
|
54
|
+
_this.log.error(constants_1.LOG_PREFIX + 'Could not retrieve changeNumber from storage. Error: ' + e);
|
|
55
|
+
return -1;
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
// @TODO implement if required by DataLoader or producer mode
|
|
59
|
+
RBSegmentsCachePluggable.prototype.clear = function () {
|
|
60
|
+
return Promise.resolve();
|
|
61
|
+
};
|
|
62
|
+
return RBSegmentsCachePluggable;
|
|
63
|
+
}());
|
|
64
|
+
exports.RBSegmentsCachePluggable = RBSegmentsCachePluggable;
|
|
@@ -54,8 +54,9 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
54
54
|
* The returned promise is resolved when the operation success
|
|
55
55
|
* or rejected if it fails (e.g., wrapper operation fails)
|
|
56
56
|
*/
|
|
57
|
-
SplitsCachePluggable.prototype.addSplit = function (
|
|
57
|
+
SplitsCachePluggable.prototype.addSplit = function (split) {
|
|
58
58
|
var _this = this;
|
|
59
|
+
var name = split.name;
|
|
59
60
|
var splitKey = this.keys.buildSplitKey(name);
|
|
60
61
|
return this.wrapper.get(splitKey).then(function (splitFromStorage) {
|
|
61
62
|
// handling parsing error
|
|
@@ -79,15 +80,6 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
79
80
|
}).then(function () { return _this._updateFlagSets(name, parsedPreviousSplit && parsedPreviousSplit.sets, split.sets); });
|
|
80
81
|
}).then(function () { return true; });
|
|
81
82
|
};
|
|
82
|
-
/**
|
|
83
|
-
* Add a list of splits.
|
|
84
|
-
* The returned promise is resolved when the operation success
|
|
85
|
-
* or rejected if it fails (e.g., wrapper operation fails)
|
|
86
|
-
*/
|
|
87
|
-
SplitsCachePluggable.prototype.addSplits = function (entries) {
|
|
88
|
-
var _this = this;
|
|
89
|
-
return Promise.all(entries.map(function (keyValuePair) { return _this.addSplit(keyValuePair[0], keyValuePair[1]); }));
|
|
90
|
-
};
|
|
91
83
|
/**
|
|
92
84
|
* Remove a given split.
|
|
93
85
|
* The returned promise is resolved when the operation success, with a boolean indicating if the split existed or not.
|
|
@@ -103,15 +95,6 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
|
103
95
|
return _this.wrapper.del(_this.keys.buildSplitKey(name));
|
|
104
96
|
});
|
|
105
97
|
};
|
|
106
|
-
/**
|
|
107
|
-
* Remove a list of splits.
|
|
108
|
-
* The returned promise is resolved when the operation success, with a boolean array indicating if the splits existed or not.
|
|
109
|
-
* or rejected if it fails (e.g., wrapper operation fails).
|
|
110
|
-
*/
|
|
111
|
-
SplitsCachePluggable.prototype.removeSplits = function (names) {
|
|
112
|
-
var _this = this;
|
|
113
|
-
return Promise.all(names.map(function (name) { return _this.removeSplit(name); }));
|
|
114
|
-
};
|
|
115
98
|
/**
|
|
116
99
|
* Get split.
|
|
117
100
|
* The returned promise is resolved with the split definition or null if it's not defined,
|
|
@@ -22,6 +22,7 @@ var UniqueKeysCacheInMemory_1 = require("../inMemory/UniqueKeysCacheInMemory");
|
|
|
22
22
|
var UniqueKeysCacheInMemoryCS_1 = require("../inMemory/UniqueKeysCacheInMemoryCS");
|
|
23
23
|
var utils_1 = require("../utils");
|
|
24
24
|
var constants_2 = require("../pluggable/constants");
|
|
25
|
+
var RBSegmentsCachePluggable_1 = require("./RBSegmentsCachePluggable");
|
|
25
26
|
var NO_VALID_WRAPPER = 'Expecting pluggable storage `wrapper` in options, but no valid wrapper instance was provided.';
|
|
26
27
|
var NO_VALID_WRAPPER_INTERFACE = 'The provided wrapper instance doesn’t follow the expected interface. Check our docs.';
|
|
27
28
|
/**
|
|
@@ -74,8 +75,7 @@ function PluggableStorage(options) {
|
|
|
74
75
|
// Connects to wrapper and emits SDK_READY event on main client
|
|
75
76
|
var connectPromise = wrapper.connect().then(function () {
|
|
76
77
|
if (isSynchronizer) {
|
|
77
|
-
//
|
|
78
|
-
// In standalone or producer mode, clear storage if SDK key, flags filter criteria or flags spec version was modified
|
|
78
|
+
// In standalone or producer mode, clear storage if SDK key or feature flag filter has changed
|
|
79
79
|
return wrapper.get(keys.buildHashKey()).then(function (hash) {
|
|
80
80
|
var currentHash = (0, KeyBuilder_1.getStorageHash)(settings);
|
|
81
81
|
if (hash !== currentHash) {
|
|
@@ -105,6 +105,7 @@ function PluggableStorage(options) {
|
|
|
105
105
|
});
|
|
106
106
|
return {
|
|
107
107
|
splits: new SplitsCachePluggable_1.SplitsCachePluggable(log, keys, wrapper, settings.sync.__splitFiltersValidation),
|
|
108
|
+
rbSegments: new RBSegmentsCachePluggable_1.RBSegmentsCachePluggable(log, keys, wrapper),
|
|
108
109
|
segments: new SegmentsCachePluggable_1.SegmentsCachePluggable(log, keys, wrapper),
|
|
109
110
|
impressions: isPartialConsumer ? new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable_1.ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
110
111
|
impressionCounts: impressionCountsCache,
|
|
@@ -26,30 +26,28 @@ function fromObjectUpdaterFactory(splitsParser, storage, readiness, settings) {
|
|
|
26
26
|
if (!loadError && splitsMock) {
|
|
27
27
|
log.debug(constants_3.SYNC_OFFLINE_DATA, [JSON.stringify(splitsMock)]);
|
|
28
28
|
(0, lang_1.forOwn)(splitsMock, function (val, name) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
]);
|
|
29
|
+
// @ts-ignore Split changeNumber and seed is undefined in localhost mode
|
|
30
|
+
splits.push({
|
|
31
|
+
name: name,
|
|
32
|
+
status: 'ACTIVE',
|
|
33
|
+
killed: false,
|
|
34
|
+
trafficAllocation: 100,
|
|
35
|
+
defaultTreatment: constants_1.CONTROL,
|
|
36
|
+
conditions: val.conditions || [],
|
|
37
|
+
configurations: val.configurations,
|
|
38
|
+
trafficTypeName: val.trafficTypeName
|
|
39
|
+
});
|
|
41
40
|
});
|
|
42
41
|
return Promise.all([
|
|
43
42
|
splitsCache.clear(),
|
|
44
|
-
splitsCache.
|
|
43
|
+
splitsCache.update(splits, [], Date.now())
|
|
45
44
|
]).then(function () {
|
|
46
45
|
readiness.splits.emit(constants_2.SDK_SPLITS_ARRIVED);
|
|
47
46
|
if (startingUp) {
|
|
48
47
|
startingUp = false;
|
|
49
|
-
|
|
50
|
-
Promise.resolve().then(function () {
|
|
48
|
+
Promise.resolve(splitsCache.checkCache()).then(function (cacheReady) {
|
|
51
49
|
// Emits SDK_READY_FROM_CACHE
|
|
52
|
-
if (
|
|
50
|
+
if (cacheReady)
|
|
53
51
|
readiness.splits.emit(constants_2.SDK_SPLITS_CACHE_LOADED);
|
|
54
52
|
// Emits SDK_READY
|
|
55
53
|
readiness.segments.emit(constants_2.SDK_SEGMENTS_ARRIVED);
|
|
@@ -6,10 +6,10 @@ exports.splitChangesFetcherFactory = void 0;
|
|
|
6
6
|
* SplitChanges fetcher is a wrapper around `splitChanges` API service that parses the response and handle errors.
|
|
7
7
|
*/
|
|
8
8
|
function splitChangesFetcherFactory(fetchSplitChanges) {
|
|
9
|
-
return function splitChangesFetcher(since, noCache, till,
|
|
9
|
+
return function splitChangesFetcher(since, noCache, till, rbSince,
|
|
10
10
|
// Optional decorator for `fetchSplitChanges` promise, such as timeout or time tracker
|
|
11
11
|
decorator) {
|
|
12
|
-
var splitsPromise = fetchSplitChanges(since, noCache, till);
|
|
12
|
+
var splitsPromise = fetchSplitChanges(since, noCache, till, rbSince);
|
|
13
13
|
if (decorator)
|
|
14
14
|
splitsPromise = decorator(splitsPromise);
|
|
15
15
|
return splitsPromise.then(function (resp) { return resp.json(); });
|
|
@@ -34,10 +34,10 @@ function pollingManagerCSFactory(params) {
|
|
|
34
34
|
readiness.splits.on(constants_1.SDK_SPLITS_ARRIVED, function () {
|
|
35
35
|
if (!splitsSyncTask.isRunning())
|
|
36
36
|
return; // noop if not doing polling
|
|
37
|
-
var
|
|
38
|
-
if (
|
|
39
|
-
log.info(constants_2.POLLING_SMART_PAUSING, [
|
|
40
|
-
if (
|
|
37
|
+
var usingSegments = storage.splits.usesSegments() || storage.rbSegments.usesSegments();
|
|
38
|
+
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
39
|
+
log.info(constants_2.POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
40
|
+
if (usingSegments) {
|
|
41
41
|
startMySegmentsSyncTasks();
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
@@ -49,10 +49,10 @@ function pollingManagerCSFactory(params) {
|
|
|
49
49
|
var mySegmentsSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(splitApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
50
50
|
// smart ready
|
|
51
51
|
function smartReady() {
|
|
52
|
-
if (!readiness.isReady() && !storage.splits.usesSegments())
|
|
52
|
+
if (!readiness.isReady() && !storage.splits.usesSegments() && !storage.rbSegments.usesSegments())
|
|
53
53
|
readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED);
|
|
54
54
|
}
|
|
55
|
-
if (!storage.splits.usesSegments())
|
|
55
|
+
if (!storage.splits.usesSegments() && !storage.rbSegments.usesSegments())
|
|
56
56
|
setTimeout(smartReady, 0);
|
|
57
57
|
else
|
|
58
58
|
readiness.splits.once(constants_1.SDK_SPLITS_ARRIVED, smartReady);
|
|
@@ -66,7 +66,7 @@ function pollingManagerCSFactory(params) {
|
|
|
66
66
|
start: function () {
|
|
67
67
|
log.info(constants_2.POLLING_START);
|
|
68
68
|
splitsSyncTask.start();
|
|
69
|
-
if (storage.splits.usesSegments())
|
|
69
|
+
if (storage.splits.usesSegments() || storage.rbSegments.usesSegments())
|
|
70
70
|
startMySegmentsSyncTasks();
|
|
71
71
|
},
|
|
72
72
|
// Stop periodic fetching (polling)
|
|
@@ -8,6 +8,6 @@ var splitChangesUpdater_1 = require("../updaters/splitChangesUpdater");
|
|
|
8
8
|
* Creates a sync task that periodically executes a `splitChangesUpdater` task
|
|
9
9
|
*/
|
|
10
10
|
function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings, isClientSide) {
|
|
11
|
-
return (0, syncTask_1.syncTaskFactory)(settings.log, (0, splitChangesUpdater_1.splitChangesUpdaterFactory)(settings.log, (0, splitChangesFetcher_1.splitChangesFetcherFactory)(fetchSplitChanges), storage
|
|
11
|
+
return (0, syncTask_1.syncTaskFactory)(settings.log, (0, splitChangesUpdater_1.splitChangesUpdaterFactory)(settings.log, (0, splitChangesFetcher_1.splitChangesFetcherFactory)(fetchSplitChanges), storage, settings.sync.__splitFiltersValidation, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, isClientSide), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
|
|
12
12
|
}
|
|
13
13
|
exports.splitsSyncTaskFactory = splitsSyncTaskFactory;
|
|
@@ -12,7 +12,7 @@ var constants_3 = require("../../streaming/constants");
|
|
|
12
12
|
* - uses `segmentsEventEmitter` to emit events related to segments data updates
|
|
13
13
|
*/
|
|
14
14
|
function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmentsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, matchingKey) {
|
|
15
|
-
var splits = storage.splits, segments = storage.segments, largeSegments = storage.largeSegments;
|
|
15
|
+
var splits = storage.splits, rbSegments = storage.rbSegments, segments = storage.segments, largeSegments = storage.largeSegments;
|
|
16
16
|
var readyOnAlreadyExistentState = true;
|
|
17
17
|
var startingUp = true;
|
|
18
18
|
/** timeout and telemetry decorator for `splitChangesFetcher` promise */
|
|
@@ -34,7 +34,7 @@ function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmentsEvent
|
|
|
34
34
|
shouldNotifyUpdate = largeSegments.resetSegments(segmentsData.ls || {}) || shouldNotifyUpdate;
|
|
35
35
|
}
|
|
36
36
|
// Notify update if required
|
|
37
|
-
if (splits.usesSegments() && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
|
|
37
|
+
if ((splits.usesSegments() || rbSegments.usesSegments()) && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
|
|
38
38
|
readyOnAlreadyExistentState = false;
|
|
39
39
|
segmentsEventEmitter.emit(constants_1.SDK_SEGMENTS_ARRIVED);
|
|
40
40
|
}
|
|
@@ -39,7 +39,7 @@ function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segments, read
|
|
|
39
39
|
* Returned promise will not be rejected.
|
|
40
40
|
*
|
|
41
41
|
* @param fetchOnlyNew - if true, only fetch the segments that not exists, i.e., which `changeNumber` is equal to -1.
|
|
42
|
-
* This param is used by SplitUpdateWorker on server-side SDK, to fetch new registered segments on SPLIT_UPDATE notifications.
|
|
42
|
+
* This param is used by SplitUpdateWorker on server-side SDK, to fetch new registered segments on SPLIT_UPDATE or RB_SEGMENT_UPDATE notifications.
|
|
43
43
|
* @param segmentName - segment name to fetch. By passing `undefined` it fetches the list of segments registered at the storage
|
|
44
44
|
* @param noCache - true to revalidate data to fetch on a SEGMENT_UPDATE notifications.
|
|
45
45
|
* @param till - till target for the provided segmentName, for CDN bypass.
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.splitChangesUpdaterFactory = exports.
|
|
3
|
+
exports.splitChangesUpdaterFactory = exports.computeMutation = exports.parseSegments = void 0;
|
|
4
4
|
var timeout_1 = require("../../../utils/promise/timeout");
|
|
5
5
|
var constants_1 = require("../../../readiness/constants");
|
|
6
6
|
var constants_2 = require("../../../logger/constants");
|
|
7
7
|
var lang_1 = require("../../../utils/lang");
|
|
8
8
|
var constants_3 = require("../../../utils/constants");
|
|
9
9
|
var sets_1 = require("../../../utils/lang/sets");
|
|
10
|
+
var constants_4 = require("../../streaming/constants");
|
|
10
11
|
// Checks that all registered segments have been fetched (changeNumber !== -1 for every segment).
|
|
11
12
|
// Returns a promise that could be rejected.
|
|
12
13
|
// @TODO review together with Segments and MySegments storage APIs
|
|
@@ -21,13 +22,14 @@ function checkAllSegmentsExist(segments) {
|
|
|
21
22
|
* Collect segments from a raw split definition.
|
|
22
23
|
* Exported for testing purposes.
|
|
23
24
|
*/
|
|
24
|
-
function parseSegments(
|
|
25
|
-
|
|
26
|
-
var
|
|
25
|
+
function parseSegments(ruleEntity, matcherType) {
|
|
26
|
+
if (matcherType === void 0) { matcherType = constants_3.IN_SEGMENT; }
|
|
27
|
+
var _a = ruleEntity, conditions = _a.conditions, excluded = _a.excluded;
|
|
28
|
+
var segments = new Set(excluded && excluded.segments);
|
|
27
29
|
for (var i = 0; i < conditions.length; i++) {
|
|
28
30
|
var matchers = conditions[i].matcherGroup.matchers;
|
|
29
31
|
matchers.forEach(function (matcher) {
|
|
30
|
-
if (matcher.matcherType ===
|
|
32
|
+
if (matcher.matcherType === matcherType)
|
|
31
33
|
segments.add(matcher.userDefinedSegmentMatcherData.segmentName);
|
|
32
34
|
});
|
|
33
35
|
}
|
|
@@ -58,24 +60,21 @@ function matchFilters(featureFlag, filters) {
|
|
|
58
60
|
* i.e., an object with added splits, removed splits and used segments.
|
|
59
61
|
* Exported for testing purposes.
|
|
60
62
|
*/
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
parseSegments(split).forEach(function (segmentName) {
|
|
63
|
+
function computeMutation(rules, segments, filters) {
|
|
64
|
+
return rules.reduce(function (accum, ruleEntity) {
|
|
65
|
+
if (ruleEntity.status === 'ACTIVE' && (!filters || matchFilters(ruleEntity, filters))) {
|
|
66
|
+
accum.added.push(ruleEntity);
|
|
67
|
+
parseSegments(ruleEntity).forEach(function (segmentName) {
|
|
67
68
|
segments.add(segmentName);
|
|
68
69
|
});
|
|
69
70
|
}
|
|
70
71
|
else {
|
|
71
|
-
accum.removed.push(
|
|
72
|
+
accum.removed.push(ruleEntity);
|
|
72
73
|
}
|
|
73
74
|
return accum;
|
|
74
|
-
}, { added: [], removed: []
|
|
75
|
-
computed.segments = (0, sets_1.setToArray)(segments);
|
|
76
|
-
return computed;
|
|
75
|
+
}, { added: [], removed: [] });
|
|
77
76
|
}
|
|
78
|
-
exports.
|
|
77
|
+
exports.computeMutation = computeMutation;
|
|
79
78
|
/**
|
|
80
79
|
* factory of SplitChanges updater, a task that:
|
|
81
80
|
* - fetches split changes using `splitChangesFetcher`
|
|
@@ -90,9 +89,10 @@ exports.computeSplitsMutation = computeSplitsMutation;
|
|
|
90
89
|
* @param requestTimeoutBeforeReady - How long the updater will wait for the request to timeout. Default 0, i.e., never timeout.
|
|
91
90
|
* @param retriesOnFailureBeforeReady - How many retries on `/splitChanges` we the updater do in case of failure or timeout. Default 0, i.e., no retries.
|
|
92
91
|
*/
|
|
93
|
-
function splitChangesUpdaterFactory(log, splitChangesFetcher,
|
|
92
|
+
function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, splitFiltersValidation, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, isClientSide) {
|
|
94
93
|
if (requestTimeoutBeforeReady === void 0) { requestTimeoutBeforeReady = 0; }
|
|
95
94
|
if (retriesOnFailureBeforeReady === void 0) { retriesOnFailureBeforeReady = 0; }
|
|
95
|
+
var splits = storage.splits, rbSegments = storage.rbSegments, segments = storage.segments;
|
|
96
96
|
var startingUp = true;
|
|
97
97
|
/** timeout decorator for `splitChangesFetcher` promise */
|
|
98
98
|
function _promiseDecorator(promise) {
|
|
@@ -100,17 +100,6 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments,
|
|
|
100
100
|
promise = (0, timeout_1.timeout)(requestTimeoutBeforeReady, promise);
|
|
101
101
|
return promise;
|
|
102
102
|
}
|
|
103
|
-
/** Returns true if at least one split was updated */
|
|
104
|
-
function isThereUpdate(flagsChange) {
|
|
105
|
-
var added = flagsChange[1], removed = flagsChange[2];
|
|
106
|
-
// There is at least one added or modified feature flag
|
|
107
|
-
if (added && added.some(function (update) { return update; }))
|
|
108
|
-
return true;
|
|
109
|
-
// There is at least one removed feature flag
|
|
110
|
-
if (removed && removed.some(function (update) { return update; }))
|
|
111
|
-
return true;
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
103
|
/**
|
|
115
104
|
* SplitChanges updater returns a promise that resolves with a `false` boolean value if it fails to fetch splits or synchronize them with the storage.
|
|
116
105
|
* Returned promise will not be rejected.
|
|
@@ -118,35 +107,48 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments,
|
|
|
118
107
|
* @param noCache - true to revalidate data to fetch
|
|
119
108
|
* @param till - query param to bypass CDN requests
|
|
120
109
|
*/
|
|
121
|
-
return function splitChangesUpdater(noCache, till,
|
|
110
|
+
return function splitChangesUpdater(noCache, till, instantUpdate) {
|
|
122
111
|
/**
|
|
123
112
|
* @param since - current changeNumber at splitsCache
|
|
124
113
|
* @param retry - current number of retry attempts
|
|
125
114
|
*/
|
|
126
|
-
function _splitChangesUpdater(
|
|
115
|
+
function _splitChangesUpdater(sinces, retry) {
|
|
127
116
|
if (retry === void 0) { retry = 0; }
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
117
|
+
var since = sinces[0], rbSince = sinces[1];
|
|
118
|
+
log.debug(constants_2.SYNC_SPLITS_FETCH, sinces);
|
|
119
|
+
var fetcherPromise = Promise.resolve(instantUpdate ?
|
|
120
|
+
instantUpdate.type === constants_4.SPLIT_UPDATE ?
|
|
121
|
+
// IFFU edge case: a change to a flag that adds an IN_RULE_BASED_SEGMENT matcher that is not present yet
|
|
122
|
+
Promise.resolve(rbSegments.contains(parseSegments(instantUpdate.payload, constants_3.IN_RULE_BASED_SEGMENT))).then(function (contains) {
|
|
123
|
+
return contains ?
|
|
124
|
+
{ ff: { d: [instantUpdate.payload], t: instantUpdate.changeNumber } } :
|
|
125
|
+
splitChangesFetcher(since, noCache, till, rbSince, _promiseDecorator);
|
|
126
|
+
}) :
|
|
127
|
+
{ rbs: { d: [instantUpdate.payload], t: instantUpdate.changeNumber } } :
|
|
128
|
+
splitChangesFetcher(since, noCache, till, rbSince, _promiseDecorator))
|
|
132
129
|
.then(function (splitChanges) {
|
|
133
130
|
startingUp = false;
|
|
134
|
-
var
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
131
|
+
var usedSegments = new Set();
|
|
132
|
+
var ffUpdate = false;
|
|
133
|
+
if (splitChanges.ff) {
|
|
134
|
+
var _a = computeMutation(splitChanges.ff.d, usedSegments, splitFiltersValidation), added = _a.added, removed = _a.removed;
|
|
135
|
+
log.debug(constants_2.SYNC_SPLITS_UPDATE, [added.length, removed.length]);
|
|
136
|
+
ffUpdate = splits.update(added, removed, splitChanges.ff.t);
|
|
137
|
+
}
|
|
138
|
+
var rbsUpdate = false;
|
|
139
|
+
if (splitChanges.rbs) {
|
|
140
|
+
var _b = computeMutation(splitChanges.rbs.d, usedSegments), added = _b.added, removed = _b.removed;
|
|
141
|
+
log.debug(constants_2.SYNC_RBS_UPDATE, [added.length, removed.length]);
|
|
142
|
+
rbsUpdate = rbSegments.update(added, removed, splitChanges.rbs.t);
|
|
143
|
+
}
|
|
144
|
+
return Promise.all([ffUpdate, rbsUpdate,
|
|
145
|
+
// @TODO if at least 1 segment fetch fails due to 404 and other segments are updated in the storage, SDK_UPDATE is not emitted
|
|
146
|
+
segments.registerSegments((0, sets_1.setToArray)(usedSegments))
|
|
147
|
+
]).then(function (_a) {
|
|
148
|
+
var ffChanged = _a[0], rbsChanged = _a[1];
|
|
147
149
|
if (splitsEventEmitter) {
|
|
148
150
|
// To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
|
|
149
|
-
return Promise.resolve(!splitsEventEmitter.splitsArrived || (
|
|
151
|
+
return Promise.resolve(!splitsEventEmitter.splitsArrived || ((ffChanged || rbsChanged) && (isClientSide || checkAllSegmentsExist(segments))))
|
|
150
152
|
.catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
|
|
151
153
|
.then(function (emitSplitsArrivedEvent) {
|
|
152
154
|
// emit SDK events
|
|
@@ -163,16 +165,25 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments,
|
|
|
163
165
|
if (startingUp && retriesOnFailureBeforeReady > retry) {
|
|
164
166
|
retry += 1;
|
|
165
167
|
log.info(constants_2.SYNC_SPLITS_FETCH_RETRY, [retry, error]);
|
|
166
|
-
return _splitChangesUpdater(
|
|
168
|
+
return _splitChangesUpdater(sinces, retry);
|
|
167
169
|
}
|
|
168
170
|
else {
|
|
169
171
|
startingUp = false;
|
|
170
172
|
}
|
|
171
173
|
return false;
|
|
172
174
|
});
|
|
175
|
+
// After triggering the requests, if we have cached splits information let's notify that to emit SDK_READY_FROM_CACHE.
|
|
176
|
+
// Wrapping in a promise since checkCache can be async.
|
|
177
|
+
if (splitsEventEmitter && startingUp) {
|
|
178
|
+
Promise.resolve(splits.checkCache()).then(function (isCacheReady) {
|
|
179
|
+
if (isCacheReady)
|
|
180
|
+
splitsEventEmitter.emit(constants_1.SDK_SPLITS_CACHE_LOADED);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return fetcherPromise;
|
|
173
184
|
}
|
|
174
|
-
|
|
175
|
-
return
|
|
185
|
+
// `getChangeNumber` never rejects or throws error
|
|
186
|
+
return Promise.all([splits.getChangeNumber(), rbSegments.getChangeNumber()]).then(_splitChangesUpdater);
|
|
176
187
|
};
|
|
177
188
|
}
|
|
178
189
|
exports.splitChangesUpdaterFactory = splitChangesUpdaterFactory;
|
|
@@ -78,6 +78,7 @@ function SSEHandlerFactory(log, pushEmitter, telemetryTracker) {
|
|
|
78
78
|
case constants_1.MEMBERSHIPS_MS_UPDATE:
|
|
79
79
|
case constants_1.MEMBERSHIPS_LS_UPDATE:
|
|
80
80
|
case constants_1.SPLIT_KILL:
|
|
81
|
+
case constants_1.RB_SEGMENT_UPDATE:
|
|
81
82
|
pushEmitter.emit(parsedData.type, parsedData);
|
|
82
83
|
break;
|
|
83
84
|
/* occupancy & control events, handled by NotificationManagerKeeper */
|