@splitsoftware/splitio-commons 3.1.1-rc.1 → 3.1.1-rc.10
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 +10 -1
- package/cjs/evaluator/condition/index.js +2 -2
- package/cjs/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +8 -5
- package/cjs/evaluator/index.js +71 -76
- package/cjs/listeners/browser.js +1 -2
- package/cjs/listeners/node.js +4 -4
- package/cjs/logger/constants.js +20 -15
- package/cjs/logger/messages/debug.js +6 -5
- package/cjs/logger/messages/error.js +3 -3
- package/cjs/logger/messages/info.js +4 -3
- package/cjs/logger/messages/warn.js +7 -6
- package/cjs/presets/serverSide.js +2 -2
- package/cjs/readiness/constants.js +4 -5
- package/cjs/readiness/readinessManager.js +23 -23
- package/cjs/readiness/sdkReadinessManager.js +17 -1
- package/cjs/sdkClient/client.js +51 -27
- package/cjs/sdkClient/clientInputValidation.js +17 -6
- package/cjs/sdkClient/sdkClient.js +60 -3
- package/cjs/sdkFactory/index.js +15 -11
- package/cjs/sdkManager/index.js +5 -5
- package/cjs/services/decorateHeaders.js +1 -2
- package/cjs/services/splitApi.js +1 -14
- package/cjs/services/splitHttpClient.js +5 -3
- package/cjs/storages/AbstractSplitsCacheAsync.js +51 -0
- package/cjs/storages/AbstractSplitsCacheSync.js +76 -0
- package/cjs/storages/KeyBuilder.js +6 -6
- package/cjs/storages/KeyBuilderCS.js +5 -5
- package/cjs/storages/KeyBuilderSS.js +2 -2
- package/cjs/storages/getRolloutPlan.js +3 -3
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +2 -1
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +10 -10
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +194 -0
- package/cjs/storages/inLocalStorage/index.js +6 -6
- package/cjs/storages/inLocalStorage/validateCache.js +3 -3
- package/cjs/storages/inMemory/InMemoryStorage.js +4 -4
- package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +5 -5
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +121 -0
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +5 -5
- package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/RedisAdapter.js +8 -5
- package/cjs/storages/inRedis/{DefinitionsCacheInRedis.js → SplitsCacheInRedis.js} +77 -77
- package/cjs/storages/inRedis/index.js +2 -2
- package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
- package/cjs/storages/pluggable/SplitsCachePluggable.js +212 -0
- package/cjs/storages/pluggable/index.js +2 -2
- package/cjs/storages/setRolloutPlan.js +4 -4
- package/cjs/storages/utils.js +0 -1
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +5 -5
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +15 -24
- package/cjs/sync/polling/pollingManagerCS.js +20 -20
- package/cjs/sync/polling/pollingManagerSS.js +15 -15
- package/cjs/sync/polling/syncTasks/segmentsSyncTask.js +3 -2
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +13 -0
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +3 -3
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +6 -6
- package/cjs/sync/polling/updaters/{definitionChangesUpdater.js → splitChangesUpdater.js} +68 -65
- package/cjs/sync/streaming/AuthClient/index.js +1 -1
- package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +1 -1
- package/cjs/sync/streaming/UpdateWorkers/{DefinitionsUpdateWorker.js → SplitsUpdateWorker.js} +19 -16
- package/cjs/sync/streaming/constants.js +3 -3
- package/cjs/sync/streaming/parseUtils.js +11 -11
- package/cjs/sync/streaming/pushManager.js +16 -16
- package/cjs/sync/submitters/eventsSubmitter.js +1 -1
- package/cjs/sync/submitters/impressionCountsSubmitter.js +1 -1
- package/cjs/sync/submitters/impressionsSubmitter.js +4 -5
- package/cjs/sync/submitters/telemetrySubmitter.js +4 -3
- package/cjs/sync/submitters/uniqueKeysSubmitter.js +1 -1
- package/cjs/sync/syncManagerOnline.js +7 -12
- package/cjs/utils/Backoff.js +0 -20
- package/cjs/utils/inputValidation/index.js +7 -7
- package/cjs/utils/inputValidation/isOperational.js +4 -4
- package/cjs/utils/inputValidation/{definition.js → split.js} +10 -10
- package/cjs/utils/inputValidation/{definitionExistence.js → splitExistence.js} +6 -6
- package/cjs/utils/inputValidation/splits.js +25 -0
- package/cjs/utils/labels/index.js +3 -3
- package/cjs/utils/settingsValidation/index.js +0 -2
- package/cjs/utils/settingsValidation/splitFilters.js +3 -3
- package/cjs/utils/settingsValidation/url.js +2 -6
- package/esm/evaluator/condition/index.js +2 -2
- package/esm/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +8 -5
- package/esm/evaluator/index.js +71 -75
- package/esm/listeners/browser.js +1 -2
- package/esm/listeners/node.js +4 -4
- package/esm/logger/constants.js +17 -12
- package/esm/logger/messages/debug.js +6 -5
- package/esm/logger/messages/error.js +3 -3
- package/esm/logger/messages/info.js +4 -3
- package/esm/logger/messages/warn.js +7 -6
- package/esm/presets/serverSide.js +2 -2
- package/esm/readiness/constants.js +3 -4
- package/esm/readiness/readinessManager.js +24 -24
- package/esm/readiness/sdkReadinessManager.js +18 -2
- package/esm/sdkClient/client.js +51 -26
- package/esm/sdkClient/clientInputValidation.js +19 -8
- package/esm/sdkClient/sdkClient.js +60 -3
- package/esm/sdkFactory/index.js +16 -12
- package/esm/sdkManager/index.js +6 -6
- package/esm/services/decorateHeaders.js +1 -2
- package/esm/services/splitApi.js +1 -14
- package/esm/services/splitHttpClient.js +5 -3
- package/esm/storages/AbstractSplitsCacheAsync.js +48 -0
- package/esm/storages/AbstractSplitsCacheSync.js +71 -0
- package/esm/storages/KeyBuilder.js +6 -6
- package/esm/storages/KeyBuilderCS.js +5 -5
- package/esm/storages/KeyBuilderSS.js +2 -2
- package/esm/storages/getRolloutPlan.js +3 -3
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +2 -1
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +7 -7
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +191 -0
- package/esm/storages/inLocalStorage/index.js +6 -6
- package/esm/storages/inLocalStorage/validateCache.js +3 -3
- package/esm/storages/inMemory/InMemoryStorage.js +4 -4
- package/esm/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +2 -2
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/SplitsCacheInMemory.js +118 -0
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +5 -5
- package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
- package/esm/storages/inRedis/RedisAdapter.js +8 -5
- package/esm/storages/inRedis/{DefinitionsCacheInRedis.js → SplitsCacheInRedis.js} +76 -76
- package/esm/storages/inRedis/index.js +2 -2
- package/esm/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
- package/esm/storages/pluggable/SplitsCachePluggable.js +209 -0
- package/esm/storages/pluggable/index.js +2 -2
- package/esm/storages/setRolloutPlan.js +4 -4
- package/esm/storages/utils.js +0 -1
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +6 -6
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +16 -25
- package/esm/sync/polling/pollingManagerCS.js +17 -17
- package/esm/sync/polling/pollingManagerSS.js +15 -15
- package/esm/sync/polling/syncTasks/segmentsSyncTask.js +3 -2
- package/esm/sync/polling/syncTasks/splitsSyncTask.js +9 -0
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +3 -3
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +7 -7
- package/esm/sync/polling/updaters/{definitionChangesUpdater.js → splitChangesUpdater.js} +68 -65
- package/esm/sync/streaming/AuthClient/index.js +1 -1
- package/esm/sync/streaming/SSEHandler/NotificationKeeper.js +2 -2
- package/esm/sync/streaming/SSEHandler/index.js +2 -2
- package/esm/sync/streaming/UpdateWorkers/{DefinitionsUpdateWorker.js → SplitsUpdateWorker.js} +18 -15
- package/esm/sync/streaming/constants.js +2 -2
- package/esm/sync/streaming/parseUtils.js +9 -9
- package/esm/sync/streaming/pushManager.js +18 -18
- package/esm/sync/submitters/eventsSubmitter.js +1 -1
- package/esm/sync/submitters/impressionCountsSubmitter.js +1 -1
- package/esm/sync/submitters/impressionsSubmitter.js +4 -5
- package/esm/sync/submitters/telemetrySubmitter.js +4 -3
- package/esm/sync/submitters/uniqueKeysSubmitter.js +1 -1
- package/esm/sync/syncManagerOnline.js +6 -11
- package/esm/utils/Backoff.js +0 -20
- package/esm/utils/inputValidation/index.js +3 -3
- package/esm/utils/inputValidation/isOperational.js +4 -4
- package/esm/utils/inputValidation/{definition.js → split.js} +8 -8
- package/esm/utils/inputValidation/splitExistence.js +15 -0
- package/esm/utils/inputValidation/splits.js +21 -0
- package/esm/utils/labels/index.js +2 -2
- package/esm/utils/settingsValidation/index.js +0 -2
- package/esm/utils/settingsValidation/splitFilters.js +3 -3
- package/esm/utils/settingsValidation/url.js +2 -6
- package/package.json +6 -7
- package/src/dtos/types.ts +1 -1
- package/src/evaluator/index.ts +11 -5
- package/src/evaluator/types.ts +1 -0
- package/src/presets/serverSide.ts +3 -3
- package/src/sdkClient/client.ts +3 -4
- package/src/sdkClient/sdkLifecycle.ts +3 -0
- package/src/services/authProvider.ts +41 -19
- package/src/services/secureSplitHttpClient.ts +10 -18
- package/src/services/serviceApi.ts +27 -24
- package/src/services/splitApi.ts +10 -9
- package/src/services/types.ts +5 -4
- package/src/storages/inRedis/RedisAdapter.ts +8 -5
- package/src/sync/polling/pollingManagerCS.ts +80 -78
- package/src/sync/polling/pollingManagerSS.ts +49 -45
- package/src/sync/polling/updaters/definitionChangesUpdater.ts +3 -3
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +1 -1
- package/src/sync/streaming/AuthClient/index.ts +14 -15
- package/src/sync/streaming/AuthClient/types.ts +9 -13
- package/src/sync/streaming/SSEClient/index.ts +2 -2
- package/src/sync/streaming/SSEClient/types.ts +2 -2
- package/src/sync/streaming/SSEHandler/index.ts +2 -1
- package/src/sync/streaming/SSEHandler/types.ts +2 -2
- package/src/sync/streaming/constants.ts +1 -0
- package/src/sync/streaming/pushManager.ts +32 -42
- package/src/sync/streaming/types.ts +3 -2
- package/src/sync/submitters/impressionsSubmitter.ts +3 -3
- package/src/sync/submitters/types.ts +2 -2
- package/src/sync/syncManagerOnline.ts +2 -8
- package/src/utils/Backoff.ts +16 -4
- package/types/splitio.d.ts +5 -4
- package/cjs/platform/browser.js +0 -15
- package/cjs/platform/getEventSource/browser.js +0 -8
- package/cjs/platform/getEventSource/eventsource.js +0 -480
- package/cjs/platform/getEventSource/node.js +0 -26
- package/cjs/platform/getFetch/browser.js +0 -9
- package/cjs/platform/getFetch/node.js +0 -27
- package/cjs/platform/getOptions/node.js +0 -25
- package/cjs/platform/node.js +0 -17
- package/cjs/sdkClient/sdkLifecycle.js +0 -72
- package/cjs/sdkClient/trackMethod.js +0 -56
- package/cjs/services/authProvider.js +0 -67
- package/cjs/services/secureSplitHttpClient.js +0 -39
- package/cjs/services/serviceApi.js +0 -145
- package/cjs/storages/AbstractDefinitionsCacheAsync.js +0 -51
- package/cjs/storages/AbstractDefinitionsCacheSync.js +0 -76
- package/cjs/storages/inLocalStorage/DefinitionsCacheInLocal.js +0 -194
- package/cjs/storages/inMemory/DefinitionsCacheInMemory.js +0 -121
- package/cjs/storages/pluggable/DefinitionsCachePluggable.js +0 -212
- package/cjs/sync/polling/syncTasks/definitionsSyncTask.js +0 -13
- package/cjs/utils/EventEmitter.js +0 -391
- package/cjs/utils/filter/bloomFilter.js +0 -37
- package/cjs/utils/inputValidation/definitions.js +0 -25
- package/cjs/utils/inputValidation/target.js +0 -22
- package/esm/platform/browser.js +0 -12
- package/esm/platform/getEventSource/browser.js +0 -4
- package/esm/platform/getEventSource/eventsource.js +0 -480
- package/esm/platform/getEventSource/node.js +0 -20
- package/esm/platform/getFetch/browser.js +0 -5
- package/esm/platform/getFetch/node.js +0 -22
- package/esm/platform/getOptions/node.js +0 -20
- package/esm/platform/node.js +0 -14
- package/esm/sdkClient/sdkLifecycle.js +0 -68
- package/esm/sdkClient/trackMethod.js +0 -52
- package/esm/services/authProvider.js +0 -63
- package/esm/services/secureSplitHttpClient.js +0 -35
- package/esm/services/serviceApi.js +0 -141
- package/esm/storages/AbstractDefinitionsCacheAsync.js +0 -48
- package/esm/storages/AbstractDefinitionsCacheSync.js +0 -71
- package/esm/storages/inLocalStorage/DefinitionsCacheInLocal.js +0 -191
- package/esm/storages/inMemory/DefinitionsCacheInMemory.js +0 -118
- package/esm/storages/pluggable/DefinitionsCachePluggable.js +0 -209
- package/esm/sync/polling/syncTasks/definitionsSyncTask.js +0 -9
- package/esm/utils/EventEmitter.js +0 -387
- package/esm/utils/filter/bloomFilter.js +0 -33
- package/esm/utils/inputValidation/definitionExistence.js +0 -15
- package/esm/utils/inputValidation/definitions.js +0 -21
- package/esm/utils/inputValidation/target.js +0 -18
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __extends, __spreadArray } from "tslib";
|
|
2
2
|
import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
|
|
3
3
|
import { LOG_PREFIX } from './constants';
|
|
4
|
-
import {
|
|
4
|
+
import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
|
|
5
5
|
import { returnDifference } from '../../utils/lang/sets';
|
|
6
6
|
/**
|
|
7
7
|
* Discard errors for an answer of multiple operations.
|
|
@@ -14,17 +14,17 @@ function processPipelineAnswer(results) {
|
|
|
14
14
|
}, []) : [];
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* ISplitsCacheAsync implementation that stores split definitions in Redis.
|
|
18
18
|
* Supported by Node.js
|
|
19
19
|
*/
|
|
20
|
-
var
|
|
21
|
-
__extends(
|
|
22
|
-
function
|
|
20
|
+
var SplitsCacheInRedis = /** @class */ (function (_super) {
|
|
21
|
+
__extends(SplitsCacheInRedis, _super);
|
|
22
|
+
function SplitsCacheInRedis(log, keys, redis, splitFiltersValidation) {
|
|
23
23
|
var _this = _super.call(this) || this;
|
|
24
24
|
_this.log = log;
|
|
25
25
|
_this.redis = redis;
|
|
26
26
|
_this.keys = keys;
|
|
27
|
-
_this.
|
|
27
|
+
_this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
|
|
28
28
|
// There is no need to listen for redis 'error' event, because in that case ioredis calls will be rejected and handled by redis storage adapters.
|
|
29
29
|
// But it is done just to avoid getting the ioredis message `Unhandled error event`.
|
|
30
30
|
_this.redis.on('error', function (e) {
|
|
@@ -35,104 +35,104 @@ var DefinitionsCacheInRedis = /** @class */ (function (_super) {
|
|
|
35
35
|
});
|
|
36
36
|
return _this;
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
SplitsCacheInRedis.prototype._decrementCounts = function (split) {
|
|
39
39
|
var _this = this;
|
|
40
|
-
var ttKey = this.keys.buildTrafficTypeKey(
|
|
40
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
41
41
|
return this.redis.decr(ttKey).then(function (count) {
|
|
42
42
|
if (count === 0)
|
|
43
43
|
return _this.redis.del(ttKey);
|
|
44
44
|
});
|
|
45
45
|
};
|
|
46
|
-
|
|
47
|
-
var ttKey = this.keys.buildTrafficTypeKey(
|
|
46
|
+
SplitsCacheInRedis.prototype._incrementCounts = function (split) {
|
|
47
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
48
48
|
return this.redis.incr(ttKey);
|
|
49
49
|
};
|
|
50
|
-
|
|
50
|
+
SplitsCacheInRedis.prototype._updateFlagSets = function (featureFlagName, flagSetsOfRemovedFlag, flagSetsOfAddedFlag) {
|
|
51
51
|
var _this = this;
|
|
52
|
-
var
|
|
53
|
-
var
|
|
54
|
-
if (this.
|
|
55
|
-
|
|
56
|
-
return _this.
|
|
52
|
+
var removeFromFlagSets = returnDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag);
|
|
53
|
+
var addToFlagSets = returnDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag);
|
|
54
|
+
if (this.flagSetsFilter.length > 0) {
|
|
55
|
+
addToFlagSets = addToFlagSets.filter(function (flagSet) {
|
|
56
|
+
return _this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === flagSet; });
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
|
-
var items = [
|
|
60
|
-
return Promise.all(__spreadArray(__spreadArray([],
|
|
59
|
+
var items = [featureFlagName];
|
|
60
|
+
return Promise.all(__spreadArray(__spreadArray([], removeFromFlagSets.map(function (flagSetName) { return _this.redis.srem(_this.keys.buildFlagSetKey(flagSetName), items); }), true), addToFlagSets.map(function (flagSetName) { return _this.redis.sadd(_this.keys.buildFlagSetKey(flagSetName), items); }), true));
|
|
61
61
|
};
|
|
62
62
|
/**
|
|
63
|
-
* Add a given
|
|
63
|
+
* Add a given split.
|
|
64
64
|
* The returned promise is resolved when the operation success
|
|
65
65
|
* or rejected if it fails (e.g., redis operation fails)
|
|
66
66
|
*/
|
|
67
|
-
|
|
67
|
+
SplitsCacheInRedis.prototype.addSplit = function (split) {
|
|
68
68
|
var _this = this;
|
|
69
|
-
var name =
|
|
70
|
-
var
|
|
71
|
-
return this.redis.get(
|
|
69
|
+
var name = split.name;
|
|
70
|
+
var splitKey = this.keys.buildSplitKey(name);
|
|
71
|
+
return this.redis.get(splitKey).then(function (splitFromStorage) {
|
|
72
72
|
// handling parsing error
|
|
73
|
-
var
|
|
73
|
+
var parsedPreviousSplit, stringifiedNewSplit;
|
|
74
74
|
try {
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
parsedPreviousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : undefined;
|
|
76
|
+
stringifiedNewSplit = JSON.stringify(split);
|
|
77
77
|
}
|
|
78
78
|
catch (e) {
|
|
79
79
|
throw new Error('Error parsing feature flag definition: ' + e);
|
|
80
80
|
}
|
|
81
|
-
return _this.redis.set(
|
|
81
|
+
return _this.redis.set(splitKey, stringifiedNewSplit).then(function () {
|
|
82
82
|
// avoid unnecessary increment/decrement operations
|
|
83
|
-
if (
|
|
83
|
+
if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName)
|
|
84
84
|
return;
|
|
85
85
|
// update traffic type counts
|
|
86
|
-
return _this._incrementCounts(
|
|
87
|
-
if (
|
|
88
|
-
return _this._decrementCounts(
|
|
86
|
+
return _this._incrementCounts(split).then(function () {
|
|
87
|
+
if (parsedPreviousSplit)
|
|
88
|
+
return _this._decrementCounts(parsedPreviousSplit);
|
|
89
89
|
});
|
|
90
|
-
}).then(function () { return _this.
|
|
90
|
+
}).then(function () { return _this._updateFlagSets(name, parsedPreviousSplit && parsedPreviousSplit.sets, split.sets); });
|
|
91
91
|
}).then(function () { return true; });
|
|
92
92
|
};
|
|
93
93
|
/**
|
|
94
|
-
* Remove a given
|
|
95
|
-
* The returned promise is resolved when the operation success, with true or false indicating if the
|
|
94
|
+
* Remove a given split.
|
|
95
|
+
* The returned promise is resolved when the operation success, with true or false indicating if the split existed (and was removed) or not.
|
|
96
96
|
* or rejected if it fails (e.g., redis operation fails).
|
|
97
97
|
*/
|
|
98
|
-
|
|
98
|
+
SplitsCacheInRedis.prototype.removeSplit = function (name) {
|
|
99
99
|
var _this = this;
|
|
100
|
-
return this.
|
|
101
|
-
if (
|
|
102
|
-
return _this._decrementCounts(
|
|
100
|
+
return this.getSplit(name).then(function (split) {
|
|
101
|
+
if (split) {
|
|
102
|
+
return _this._decrementCounts(split).then(function () { return _this._updateFlagSets(name, split.sets); });
|
|
103
103
|
}
|
|
104
104
|
}).then(function () {
|
|
105
|
-
return _this.redis.del(_this.keys.
|
|
105
|
+
return _this.redis.del(_this.keys.buildSplitKey(name)).then(function (status) { return status === 1; });
|
|
106
106
|
});
|
|
107
107
|
};
|
|
108
108
|
/**
|
|
109
|
-
* Get definition or null if it's not defined.
|
|
109
|
+
* Get split definition or null if it's not defined.
|
|
110
110
|
* Returned promise is rejected if redis operation fails.
|
|
111
111
|
*/
|
|
112
|
-
|
|
112
|
+
SplitsCacheInRedis.prototype.getSplit = function (name) {
|
|
113
113
|
if (this.redisError) {
|
|
114
114
|
this.log.error(LOG_PREFIX + this.redisError);
|
|
115
115
|
return Promise.reject(this.redisError);
|
|
116
116
|
}
|
|
117
|
-
return this.redis.get(this.keys.
|
|
118
|
-
.then(function (
|
|
117
|
+
return this.redis.get(this.keys.buildSplitKey(name))
|
|
118
|
+
.then(function (maybeSplit) { return maybeSplit && JSON.parse(maybeSplit); });
|
|
119
119
|
};
|
|
120
120
|
/**
|
|
121
121
|
* Set till number.
|
|
122
122
|
* The returned promise is resolved when the operation success,
|
|
123
123
|
* or rejected if it fails.
|
|
124
124
|
*/
|
|
125
|
-
|
|
126
|
-
return this.redis.set(this.keys.
|
|
125
|
+
SplitsCacheInRedis.prototype.setChangeNumber = function (changeNumber) {
|
|
126
|
+
return this.redis.set(this.keys.buildSplitsTillKey(), changeNumber + '').then(function (status) { return status === 'OK'; });
|
|
127
127
|
};
|
|
128
128
|
/**
|
|
129
129
|
* Get till number or -1 if it's not defined.
|
|
130
130
|
* The returned promise is resolved with the changeNumber or -1 if it doesn't exist or a redis operation fails.
|
|
131
131
|
* The promise will never be rejected.
|
|
132
132
|
*/
|
|
133
|
-
|
|
133
|
+
SplitsCacheInRedis.prototype.getChangeNumber = function () {
|
|
134
134
|
var _this = this;
|
|
135
|
-
return this.redis.get(this.keys.
|
|
135
|
+
return this.redis.get(this.keys.buildSplitsTillKey()).then(function (value) {
|
|
136
136
|
var i = parseInt(value, 10);
|
|
137
137
|
return isNaNNumber(i) ? -1 : i;
|
|
138
138
|
}).catch(function (e) {
|
|
@@ -141,44 +141,44 @@ var DefinitionsCacheInRedis = /** @class */ (function (_super) {
|
|
|
141
141
|
});
|
|
142
142
|
};
|
|
143
143
|
/**
|
|
144
|
-
* Get list of all definitions.
|
|
145
|
-
* The returned promise is resolved with the list of definitions,
|
|
144
|
+
* Get list of all split definitions.
|
|
145
|
+
* The returned promise is resolved with the list of split definitions,
|
|
146
146
|
* or rejected if redis operation fails.
|
|
147
147
|
*/
|
|
148
148
|
// @TODO we need to benchmark which is the maximun number of commands we could pipeline without kill redis performance.
|
|
149
|
-
|
|
149
|
+
SplitsCacheInRedis.prototype.getAll = function () {
|
|
150
150
|
var _this = this;
|
|
151
|
-
return this.redis.keys(this.keys.
|
|
151
|
+
return this.redis.keys(this.keys.searchPatternForSplitKeys())
|
|
152
152
|
.then(function (listOfKeys) { return _this.redis.pipeline(listOfKeys.map(function (k) { return ['get', k]; })).exec(); })
|
|
153
153
|
.then(processPipelineAnswer)
|
|
154
|
-
.then(function (
|
|
155
|
-
return JSON.parse(
|
|
154
|
+
.then(function (splitDefinitions) { return splitDefinitions.map(function (splitDefinition) {
|
|
155
|
+
return JSON.parse(splitDefinition);
|
|
156
156
|
}); });
|
|
157
157
|
};
|
|
158
158
|
/**
|
|
159
|
-
* Get list of
|
|
160
|
-
* The returned promise is resolved with the list of names,
|
|
159
|
+
* Get list of split names.
|
|
160
|
+
* The returned promise is resolved with the list of split names,
|
|
161
161
|
* or rejected if redis operation fails.
|
|
162
162
|
*/
|
|
163
|
-
|
|
163
|
+
SplitsCacheInRedis.prototype.getSplitNames = function () {
|
|
164
164
|
var _this = this;
|
|
165
|
-
return this.redis.keys(this.keys.
|
|
165
|
+
return this.redis.keys(this.keys.searchPatternForSplitKeys()).then(function (listOfKeys) { return listOfKeys.map(_this.keys.extractKey); });
|
|
166
166
|
};
|
|
167
167
|
/**
|
|
168
|
-
* Get list of
|
|
169
|
-
* The returned promise is resolved with the list of names per set,
|
|
168
|
+
* Get list of feature flag names related to a given list of flag set names.
|
|
169
|
+
* The returned promise is resolved with the list of feature flag names per flag set,
|
|
170
170
|
* or rejected if the pipelined redis operation fails (e.g., timeout).
|
|
171
171
|
*/
|
|
172
|
-
|
|
172
|
+
SplitsCacheInRedis.prototype.getNamesByFlagSets = function (flagSets) {
|
|
173
173
|
var _this = this;
|
|
174
|
-
return this.redis.pipeline(
|
|
174
|
+
return this.redis.pipeline(flagSets.map(function (flagSet) { return ['smembers', _this.keys.buildFlagSetKey(flagSet)]; })).exec()
|
|
175
175
|
.then(function (results) { return results ? results.map(function (_a, index) {
|
|
176
176
|
var e = _a[0], value = _a[1];
|
|
177
177
|
if (e === null)
|
|
178
178
|
return value;
|
|
179
|
-
_this.log.error(LOG_PREFIX + "Could not read result from get members of set ".concat(
|
|
179
|
+
_this.log.error(LOG_PREFIX + "Could not read result from get members of flag set ".concat(flagSets[index], " due to an error: ").concat(e));
|
|
180
180
|
}) : []; })
|
|
181
|
-
.then(function (
|
|
181
|
+
.then(function (namesByFlagSets) { return namesByFlagSets.map(function (namesByFlagSet) { return new Set(namesByFlagSet); }); });
|
|
182
182
|
};
|
|
183
183
|
/**
|
|
184
184
|
* Check traffic type existence.
|
|
@@ -186,7 +186,7 @@ var DefinitionsCacheInRedis = /** @class */ (function (_super) {
|
|
|
186
186
|
* In case of redis operation failure, the promise resolves with a true value, assuming that the TT might exist.
|
|
187
187
|
* It will never be rejected.
|
|
188
188
|
*/
|
|
189
|
-
|
|
189
|
+
SplitsCacheInRedis.prototype.trafficTypeExists = function (trafficType) {
|
|
190
190
|
var _this = this;
|
|
191
191
|
// If there is a number there should be > 0, otherwise the TT is considered as not existent.
|
|
192
192
|
return this.redis.get(this.keys.buildTrafficTypeKey(trafficType))
|
|
@@ -207,34 +207,34 @@ var DefinitionsCacheInRedis = /** @class */ (function (_super) {
|
|
|
207
207
|
});
|
|
208
208
|
};
|
|
209
209
|
// @TODO remove or implement. It is not being used.
|
|
210
|
-
|
|
210
|
+
SplitsCacheInRedis.prototype.clear = function () {
|
|
211
211
|
return Promise.resolve();
|
|
212
212
|
};
|
|
213
213
|
/**
|
|
214
|
-
* Fetches multiple definitions.
|
|
214
|
+
* Fetches multiple splits definitions.
|
|
215
215
|
* Returned promise is rejected if redis operation fails.
|
|
216
216
|
*/
|
|
217
|
-
|
|
217
|
+
SplitsCacheInRedis.prototype.getSplits = function (names) {
|
|
218
218
|
var _a;
|
|
219
219
|
var _this = this;
|
|
220
220
|
if (this.redisError) {
|
|
221
221
|
this.log.error(LOG_PREFIX + this.redisError);
|
|
222
222
|
return Promise.reject(this.redisError);
|
|
223
223
|
}
|
|
224
|
-
var keys = names.map(function (name) { return _this.keys.
|
|
225
|
-
return (_a = this.redis).mget.apply(_a, keys).then(function (
|
|
226
|
-
var
|
|
224
|
+
var keys = names.map(function (name) { return _this.keys.buildSplitKey(name); });
|
|
225
|
+
return (_a = this.redis).mget.apply(_a, keys).then(function (splitDefinitions) {
|
|
226
|
+
var splits = {};
|
|
227
227
|
names.forEach(function (name, idx) {
|
|
228
|
-
var
|
|
229
|
-
|
|
228
|
+
var split = splitDefinitions[idx];
|
|
229
|
+
splits[name] = split && JSON.parse(split);
|
|
230
230
|
});
|
|
231
|
-
return Promise.resolve(
|
|
231
|
+
return Promise.resolve(splits);
|
|
232
232
|
})
|
|
233
233
|
.catch(function (e) {
|
|
234
234
|
_this.log.error(LOG_PREFIX + "Could not grab feature flags due to an error: ".concat(e, "."));
|
|
235
235
|
return Promise.reject(e);
|
|
236
236
|
});
|
|
237
237
|
};
|
|
238
|
-
return
|
|
239
|
-
}(
|
|
240
|
-
export {
|
|
238
|
+
return SplitsCacheInRedis;
|
|
239
|
+
}(AbstractSplitsCacheAsync));
|
|
240
|
+
export { SplitsCacheInRedis };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { validatePrefix } from '../KeyBuilder';
|
|
2
2
|
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
3
|
-
import {
|
|
3
|
+
import { SplitsCacheInRedis } from './SplitsCacheInRedis';
|
|
4
4
|
import { SegmentsCacheInRedis } from './SegmentsCacheInRedis';
|
|
5
5
|
import { ImpressionsCacheInRedis } from './ImpressionsCacheInRedis';
|
|
6
6
|
import { EventsCacheInRedis } from './EventsCacheInRedis';
|
|
@@ -45,7 +45,7 @@ export function InRedisStorage(options) {
|
|
|
45
45
|
telemetry.recordConfig();
|
|
46
46
|
});
|
|
47
47
|
return {
|
|
48
|
-
|
|
48
|
+
splits: new SplitsCacheInRedis(log, keys, redisClient, settings.sync.__splitFiltersValidation),
|
|
49
49
|
rbSegments: new RBSegmentsCacheInRedis(log, keys, redisClient),
|
|
50
50
|
segments: new SegmentsCacheInRedis(log, keys, redisClient),
|
|
51
51
|
impressions: new ImpressionsCacheInRedis(log, keys.buildImpressionsKey(), redisClient, metadata),
|
|
@@ -31,7 +31,7 @@ var RBSegmentsCachePluggable = /** @class */ (function () {
|
|
|
31
31
|
return _this.wrapper.set(key, stringifiedNewRBSegment).then(function () { return true; });
|
|
32
32
|
})),
|
|
33
33
|
Promise.all(toRemove.map(function (toRemove) {
|
|
34
|
-
var key = _this.keys.buildRBSegmentKey(toRemove);
|
|
34
|
+
var key = _this.keys.buildRBSegmentKey(toRemove.name);
|
|
35
35
|
return _this.wrapper.del(key);
|
|
36
36
|
}))
|
|
37
37
|
]).then(function (_a) {
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { __extends, __spreadArray } from "tslib";
|
|
2
|
+
import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
|
|
3
|
+
import { LOG_PREFIX } from './constants';
|
|
4
|
+
import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
|
|
5
|
+
import { returnDifference } from '../../utils/lang/sets';
|
|
6
|
+
/**
|
|
7
|
+
* ISplitsCacheAsync implementation for pluggable storages.
|
|
8
|
+
*/
|
|
9
|
+
var SplitsCachePluggable = /** @class */ (function (_super) {
|
|
10
|
+
__extends(SplitsCachePluggable, _super);
|
|
11
|
+
/**
|
|
12
|
+
* Create a SplitsCache that uses a storage wrapper.
|
|
13
|
+
* @param log - Logger instance.
|
|
14
|
+
* @param keys - Key builder.
|
|
15
|
+
* @param wrapper - Adapted wrapper storage.
|
|
16
|
+
*/
|
|
17
|
+
function SplitsCachePluggable(log, keys, wrapper, splitFiltersValidation) {
|
|
18
|
+
var _this = _super.call(this) || this;
|
|
19
|
+
_this.log = log;
|
|
20
|
+
_this.keys = keys;
|
|
21
|
+
_this.wrapper = wrapper;
|
|
22
|
+
_this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
|
|
23
|
+
return _this;
|
|
24
|
+
}
|
|
25
|
+
SplitsCachePluggable.prototype._decrementCounts = function (split) {
|
|
26
|
+
var _this = this;
|
|
27
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
28
|
+
return this.wrapper.decr(ttKey).then(function (count) {
|
|
29
|
+
if (count === 0)
|
|
30
|
+
return _this.wrapper.del(ttKey);
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
SplitsCachePluggable.prototype._incrementCounts = function (split) {
|
|
34
|
+
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
35
|
+
return this.wrapper.incr(ttKey);
|
|
36
|
+
};
|
|
37
|
+
SplitsCachePluggable.prototype._updateFlagSets = function (featureFlagName, flagSetsOfRemovedFlag, flagSetsOfAddedFlag) {
|
|
38
|
+
var _this = this;
|
|
39
|
+
var removeFromFlagSets = returnDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag);
|
|
40
|
+
var addToFlagSets = returnDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag);
|
|
41
|
+
if (this.flagSetsFilter.length > 0) {
|
|
42
|
+
addToFlagSets = addToFlagSets.filter(function (flagSet) {
|
|
43
|
+
return _this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === flagSet; });
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
var items = [featureFlagName];
|
|
47
|
+
return Promise.all(__spreadArray(__spreadArray([], removeFromFlagSets.map(function (flagSetName) { return _this.wrapper.removeItems(_this.keys.buildFlagSetKey(flagSetName), items); }), true), addToFlagSets.map(function (flagSetName) { return _this.wrapper.addItems(_this.keys.buildFlagSetKey(flagSetName), items); }), true));
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Add a given split.
|
|
51
|
+
* The returned promise is resolved when the operation success
|
|
52
|
+
* or rejected if it fails (e.g., wrapper operation fails)
|
|
53
|
+
*/
|
|
54
|
+
SplitsCachePluggable.prototype.addSplit = function (split) {
|
|
55
|
+
var _this = this;
|
|
56
|
+
var name = split.name;
|
|
57
|
+
var splitKey = this.keys.buildSplitKey(name);
|
|
58
|
+
return this.wrapper.get(splitKey).then(function (splitFromStorage) {
|
|
59
|
+
// handling parsing error
|
|
60
|
+
var parsedPreviousSplit, stringifiedNewSplit;
|
|
61
|
+
try {
|
|
62
|
+
parsedPreviousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : undefined;
|
|
63
|
+
stringifiedNewSplit = JSON.stringify(split);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
throw new Error('Error parsing feature flag definition: ' + e);
|
|
67
|
+
}
|
|
68
|
+
return _this.wrapper.set(splitKey, stringifiedNewSplit).then(function () {
|
|
69
|
+
// avoid unnecessary increment/decrement operations
|
|
70
|
+
if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName)
|
|
71
|
+
return;
|
|
72
|
+
// update traffic type counts
|
|
73
|
+
return _this._incrementCounts(split).then(function () {
|
|
74
|
+
if (parsedPreviousSplit)
|
|
75
|
+
return _this._decrementCounts(parsedPreviousSplit);
|
|
76
|
+
});
|
|
77
|
+
}).then(function () { return _this._updateFlagSets(name, parsedPreviousSplit && parsedPreviousSplit.sets, split.sets); });
|
|
78
|
+
}).then(function () { return true; });
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Remove a given split.
|
|
82
|
+
* The returned promise is resolved when the operation success, with a boolean indicating if the split existed or not.
|
|
83
|
+
* or rejected if it fails (e.g., wrapper operation fails).
|
|
84
|
+
*/
|
|
85
|
+
SplitsCachePluggable.prototype.removeSplit = function (name) {
|
|
86
|
+
var _this = this;
|
|
87
|
+
return this.getSplit(name).then(function (split) {
|
|
88
|
+
if (split) {
|
|
89
|
+
return _this._decrementCounts(split).then(function () { return _this._updateFlagSets(name, split.sets); });
|
|
90
|
+
}
|
|
91
|
+
}).then(function () {
|
|
92
|
+
return _this.wrapper.del(_this.keys.buildSplitKey(name));
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Get split.
|
|
97
|
+
* The returned promise is resolved with the split definition or null if it's not defined,
|
|
98
|
+
* or rejected if wrapper operation fails.
|
|
99
|
+
*/
|
|
100
|
+
SplitsCachePluggable.prototype.getSplit = function (name) {
|
|
101
|
+
return this.wrapper.get(this.keys.buildSplitKey(name))
|
|
102
|
+
.then(function (maybeSplit) { return maybeSplit && JSON.parse(maybeSplit); });
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Get list of splits.
|
|
106
|
+
* The returned promise is resolved with a map of split names to their split definition or null if it's not defined,
|
|
107
|
+
* or rejected if wrapper operation fails.
|
|
108
|
+
*/
|
|
109
|
+
SplitsCachePluggable.prototype.getSplits = function (names) {
|
|
110
|
+
var _this = this;
|
|
111
|
+
var keys = names.map(function (name) { return _this.keys.buildSplitKey(name); });
|
|
112
|
+
return this.wrapper.getMany(keys).then(function (splitDefinitions) {
|
|
113
|
+
var splits = {};
|
|
114
|
+
names.forEach(function (name, idx) {
|
|
115
|
+
var split = splitDefinitions[idx];
|
|
116
|
+
splits[name] = split && JSON.parse(split);
|
|
117
|
+
});
|
|
118
|
+
return Promise.resolve(splits);
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Get list of all split definitions.
|
|
123
|
+
* The returned promise is resolved with the list of split definitions,
|
|
124
|
+
* or rejected if wrapper operation fails.
|
|
125
|
+
*/
|
|
126
|
+
SplitsCachePluggable.prototype.getAll = function () {
|
|
127
|
+
var _this = this;
|
|
128
|
+
return this.wrapper.getKeysByPrefix(this.keys.buildSplitKeyPrefix())
|
|
129
|
+
.then(function (listOfKeys) { return _this.wrapper.getMany(listOfKeys); })
|
|
130
|
+
.then(function (splitDefinitions) { return splitDefinitions.map(function (splitDefinition) {
|
|
131
|
+
return JSON.parse(splitDefinition);
|
|
132
|
+
}); });
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Get list of split names.
|
|
136
|
+
* The returned promise is resolved with the list of split names,
|
|
137
|
+
* or rejected if wrapper operation fails.
|
|
138
|
+
*/
|
|
139
|
+
SplitsCachePluggable.prototype.getSplitNames = function () {
|
|
140
|
+
var _this = this;
|
|
141
|
+
return this.wrapper.getKeysByPrefix(this.keys.buildSplitKeyPrefix()).then(function (listOfKeys) { return listOfKeys.map(_this.keys.extractKey); });
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Get list of feature flag names related to a given list of flag set names.
|
|
145
|
+
* The returned promise is resolved with the list of feature flag names per flag set.
|
|
146
|
+
* It never rejects (If there is a wrapper error for some flag set, an empty set is returned for it).
|
|
147
|
+
*/
|
|
148
|
+
SplitsCachePluggable.prototype.getNamesByFlagSets = function (flagSets) {
|
|
149
|
+
var _this = this;
|
|
150
|
+
return Promise.all(flagSets.map(function (flagSet) {
|
|
151
|
+
var flagSetKey = _this.keys.buildFlagSetKey(flagSet);
|
|
152
|
+
return _this.wrapper.getItems(flagSetKey).catch(function () { return []; });
|
|
153
|
+
})).then(function (namesByFlagSets) { return namesByFlagSets.map(function (namesByFlagSet) { return new Set(namesByFlagSet); }); });
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Check traffic type existence.
|
|
157
|
+
* The returned promise is resolved with a boolean indicating whether the TT exist or not.
|
|
158
|
+
* In case of wrapper operation failures, the promise resolves with a true value, assuming that the TT might exist.
|
|
159
|
+
* It will never be rejected.
|
|
160
|
+
*/
|
|
161
|
+
SplitsCachePluggable.prototype.trafficTypeExists = function (trafficType) {
|
|
162
|
+
var _this = this;
|
|
163
|
+
// If there is a number there should be > 0, otherwise the TT is considered as not existent.
|
|
164
|
+
return this.wrapper.get(this.keys.buildTrafficTypeKey(trafficType))
|
|
165
|
+
.then(function (ttCount) {
|
|
166
|
+
if (ttCount === null)
|
|
167
|
+
return false; // if entry doesn't exist, means that TT doesn't exist
|
|
168
|
+
ttCount = parseInt(ttCount, 10);
|
|
169
|
+
if (!isFiniteNumber(ttCount) || ttCount < 0) {
|
|
170
|
+
_this.log.info(LOG_PREFIX + "Could not validate traffic type existence of ".concat(trafficType, " due to data corruption of some sorts."));
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
return ttCount > 0;
|
|
174
|
+
}).catch(function (e) {
|
|
175
|
+
_this.log.error(LOG_PREFIX + "Could not validate traffic type existence of ".concat(trafficType, " due to an error: ").concat(e, "."));
|
|
176
|
+
// If there is an error, bypass the validation so the event can get tracked.
|
|
177
|
+
return true;
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* Set till number.
|
|
182
|
+
* The returned promise is resolved when the operation success,
|
|
183
|
+
* or rejected if it fails (e.g., wrapper operation fails).
|
|
184
|
+
*/
|
|
185
|
+
SplitsCachePluggable.prototype.setChangeNumber = function (changeNumber) {
|
|
186
|
+
return this.wrapper.set(this.keys.buildSplitsTillKey(), changeNumber + '');
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Get till number or -1 if it's not defined.
|
|
190
|
+
* The returned promise is resolved with the changeNumber or -1 if it doesn't exist or a wrapper operation fails.
|
|
191
|
+
* The promise will never be rejected.
|
|
192
|
+
*/
|
|
193
|
+
SplitsCachePluggable.prototype.getChangeNumber = function () {
|
|
194
|
+
var _this = this;
|
|
195
|
+
return this.wrapper.get(this.keys.buildSplitsTillKey()).then(function (value) {
|
|
196
|
+
var i = parseInt(value, 10);
|
|
197
|
+
return isNaNNumber(i) ? -1 : i;
|
|
198
|
+
}).catch(function (e) {
|
|
199
|
+
_this.log.error(LOG_PREFIX + 'Could not retrieve changeNumber from storage. Error: ' + e);
|
|
200
|
+
return -1;
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
// @TODO implement if required by DataLoader or producer mode
|
|
204
|
+
SplitsCachePluggable.prototype.clear = function () {
|
|
205
|
+
return Promise.resolve(true);
|
|
206
|
+
};
|
|
207
|
+
return SplitsCachePluggable;
|
|
208
|
+
}(AbstractSplitsCacheAsync));
|
|
209
|
+
export { SplitsCachePluggable };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __assign } from "tslib";
|
|
2
2
|
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
3
|
-
import {
|
|
3
|
+
import { SplitsCachePluggable } from './SplitsCachePluggable';
|
|
4
4
|
import { SegmentsCachePluggable } from './SegmentsCachePluggable';
|
|
5
5
|
import { ImpressionsCachePluggable } from './ImpressionsCachePluggable';
|
|
6
6
|
import { EventsCachePluggable } from './EventsCachePluggable';
|
|
@@ -103,7 +103,7 @@ export function PluggableStorage(options) {
|
|
|
103
103
|
return e; // Propagate error for shared clients
|
|
104
104
|
});
|
|
105
105
|
return {
|
|
106
|
-
|
|
106
|
+
splits: new SplitsCachePluggable(log, keys, wrapper, settings.sync.__splitFiltersValidation),
|
|
107
107
|
rbSegments: new RBSegmentsCachePluggable(log, keys, wrapper),
|
|
108
108
|
segments: new SegmentsCachePluggable(log, keys, wrapper),
|
|
109
109
|
impressions: isPartialConsumer ? new ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
@@ -20,12 +20,12 @@ export function validateRolloutPlan(log, settings) {
|
|
|
20
20
|
* Otherwise, the storage is handled as a server-side storage (segments is an instance of SegmentsCache).
|
|
21
21
|
*/
|
|
22
22
|
export function setRolloutPlan(log, rolloutPlan, storage, matchingKey) {
|
|
23
|
-
var
|
|
23
|
+
var splits = storage.splits, rbSegments = storage.rbSegments, segments = storage.segments, largeSegments = storage.largeSegments;
|
|
24
24
|
var _a = rolloutPlan.splitChanges, ff = _a.ff, rbs = _a.rbs;
|
|
25
25
|
log.debug("storage: set feature flags and segments".concat(matchingKey ? " for key ".concat(matchingKey) : ''));
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
if (splits && ff) {
|
|
27
|
+
splits.clear();
|
|
28
|
+
splits.update(ff.d || [], [], ff.t);
|
|
29
29
|
}
|
|
30
30
|
if (rbSegments && rbs) {
|
|
31
31
|
rbSegments.clear();
|
package/esm/storages/utils.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { forOwn } from '../../../utils/lang';
|
|
2
2
|
import { syncTaskFactory } from '../../syncTask';
|
|
3
3
|
import { CONTROL } from '../../../utils/constants';
|
|
4
|
-
import {
|
|
4
|
+
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED, SDK_SPLITS_CACHE_LOADED, FLAGS_UPDATE, SEGMENTS_UPDATE } from '../../../readiness/constants';
|
|
5
5
|
import { SYNC_OFFLINE_DATA, ERROR_SYNC_OFFLINE_LOADING } from '../../../logger/constants';
|
|
6
6
|
/**
|
|
7
7
|
* Offline equivalent of `splitChangesUpdaterFactory`
|
|
8
8
|
*/
|
|
9
9
|
export function fromObjectUpdaterFactory(splitsParser, storage, readiness, settings) {
|
|
10
|
-
var log = settings.log,
|
|
10
|
+
var log = settings.log, splitsCache = storage.splits;
|
|
11
11
|
var startingUp = true;
|
|
12
12
|
return function objectUpdater() {
|
|
13
13
|
var splits = [];
|
|
@@ -36,16 +36,16 @@ export function fromObjectUpdaterFactory(splitsParser, storage, readiness, setti
|
|
|
36
36
|
});
|
|
37
37
|
});
|
|
38
38
|
return Promise.all([
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
splitsCache.clear(),
|
|
40
|
+
splitsCache.update(splits, [], Date.now())
|
|
41
41
|
]).then(function () {
|
|
42
|
-
readiness.
|
|
42
|
+
readiness.splits.emit(SDK_SPLITS_ARRIVED, { type: FLAGS_UPDATE, names: [] });
|
|
43
43
|
if (startingUp) {
|
|
44
44
|
startingUp = false;
|
|
45
45
|
Promise.resolve(storage.validateCache ? storage.validateCache() : { initialCacheLoad: true /* Fallback: assume initial load when validateCache doesn't exist */ }).then(function (cacheMetadata) {
|
|
46
46
|
// Emits SDK_READY_FROM_CACHE
|
|
47
47
|
if (!cacheMetadata.initialCacheLoad) {
|
|
48
|
-
readiness.
|
|
48
|
+
readiness.splits.emit(SDK_SPLITS_CACHE_LOADED, cacheMetadata);
|
|
49
49
|
}
|
|
50
50
|
// Emits SDK_READY
|
|
51
51
|
readiness.segments.emit(SDK_SEGMENTS_ARRIVED, { type: SEGMENTS_UPDATE, names: [] });
|