@splitsoftware/splitio-commons 1.10.1-rc.4 → 1.12.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.txt +16 -10
- package/cjs/evaluator/index.js +22 -3
- package/cjs/logger/constants.js +6 -4
- package/cjs/logger/messages/warn.js +5 -3
- package/cjs/sdkClient/client.js +19 -16
- package/cjs/sdkClient/clientInputValidation.js +16 -16
- package/cjs/sdkFactory/index.js +1 -1
- package/cjs/sdkManager/index.js +14 -13
- package/cjs/storages/KeyBuilder.js +1 -1
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +3 -10
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +2 -10
- package/cjs/storages/inRedis/RedisAdapter.js +32 -13
- package/cjs/storages/inRedis/SegmentsCacheInRedis.js +2 -2
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +38 -22
- package/cjs/storages/inRedis/index.js +1 -1
- package/cjs/storages/pluggable/SplitsCachePluggable.js +27 -11
- package/cjs/storages/pluggable/index.js +1 -1
- package/cjs/utils/constants/index.js +16 -2
- package/cjs/utils/inputValidation/index.js +5 -5
- package/cjs/utils/inputValidation/{splitExistance.js → splitExistence.js} +3 -3
- package/cjs/utils/inputValidation/{trafficTypeExistance.js → trafficTypeExistence.js} +6 -6
- package/cjs/utils/lang/sets.js +11 -1
- package/cjs/utils/settingsValidation/index.js +1 -1
- package/cjs/utils/settingsValidation/splitFilters.js +25 -17
- package/esm/evaluator/index.js +23 -4
- package/esm/logger/constants.js +4 -2
- package/esm/logger/messages/warn.js +5 -3
- package/esm/sdkClient/client.js +20 -17
- package/esm/sdkClient/clientInputValidation.js +18 -18
- package/esm/sdkFactory/index.js +1 -1
- package/esm/sdkManager/index.js +11 -10
- package/esm/storages/KeyBuilder.js +1 -1
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +4 -11
- package/esm/storages/inMemory/SplitsCacheInMemory.js +3 -11
- package/esm/storages/inRedis/RedisAdapter.js +32 -13
- package/esm/storages/inRedis/SegmentsCacheInRedis.js +2 -2
- package/esm/storages/inRedis/SplitsCacheInRedis.js +40 -24
- package/esm/storages/inRedis/index.js +1 -1
- package/esm/storages/pluggable/SplitsCachePluggable.js +29 -13
- package/esm/storages/pluggable/index.js +1 -1
- package/esm/utils/constants/index.js +14 -0
- package/esm/utils/inputValidation/index.js +2 -2
- package/esm/utils/inputValidation/{splitExistance.js → splitExistence.js} +1 -1
- package/esm/utils/inputValidation/{trafficTypeExistance.js → trafficTypeExistence.js} +4 -4
- package/esm/utils/lang/sets.js +9 -0
- package/esm/utils/settingsValidation/index.js +1 -1
- package/esm/utils/settingsValidation/splitFilters.js +17 -9
- package/package.json +1 -1
- package/src/evaluator/index.ts +28 -5
- package/src/logger/constants.ts +4 -2
- package/src/logger/messages/warn.ts +9 -7
- package/src/sdkClient/client.ts +18 -18
- package/src/sdkClient/clientInputValidation.ts +18 -18
- package/src/sdkFactory/index.ts +1 -1
- package/src/sdkFactory/types.ts +3 -7
- package/src/sdkManager/index.ts +14 -14
- package/src/storages/AbstractSplitsCacheAsync.ts +1 -1
- package/src/storages/AbstractSplitsCacheSync.ts +1 -1
- package/src/storages/KeyBuilder.ts +1 -1
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +8 -15
- package/src/storages/inMemory/SplitsCacheInMemory.ts +6 -14
- package/src/storages/inRedis/EventsCacheInRedis.ts +3 -3
- package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +3 -3
- package/src/storages/inRedis/ImpressionsCacheInRedis.ts +3 -3
- package/src/storages/inRedis/RedisAdapter.ts +38 -16
- package/src/storages/inRedis/SegmentsCacheInRedis.ts +5 -5
- package/src/storages/inRedis/SplitsCacheInRedis.ts +49 -28
- package/src/storages/inRedis/TelemetryCacheInRedis.ts +2 -2
- package/src/storages/inRedis/UniqueKeysCacheInRedis.ts +3 -3
- package/src/storages/inRedis/index.ts +1 -1
- package/src/storages/pluggable/SplitsCachePluggable.ts +35 -13
- package/src/storages/pluggable/index.ts +1 -1
- package/src/storages/types.ts +5 -5
- package/src/trackers/impressionObserver/utils.ts +1 -1
- package/src/types.ts +0 -2
- package/src/utils/constants/index.ts +16 -0
- package/src/utils/inputValidation/index.ts +2 -2
- package/src/utils/inputValidation/{splitExistance.ts → splitExistence.ts} +1 -1
- package/src/utils/inputValidation/{trafficTypeExistance.ts → trafficTypeExistence.ts} +4 -4
- package/src/utils/lang/sets.ts +9 -1
- package/src/utils/redis/RedisMock.ts +1 -3
- package/src/utils/settingsValidation/index.ts +1 -1
- package/src/utils/settingsValidation/splitFilters.ts +19 -11
- package/types/evaluator/index.d.ts +1 -1
- package/types/logger/constants.d.ts +4 -2
- package/types/sdkFactory/types.d.ts +3 -3
- package/types/sdkManager/index.d.ts +2 -3
- package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
- package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +1 -1
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +1 -1
- package/types/storages/inRedis/EventsCacheInRedis.d.ts +2 -2
- package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +3 -2
- package/types/storages/inRedis/ImpressionsCacheInRedis.d.ts +2 -2
- package/types/storages/inRedis/RedisAdapter.d.ts +1 -1
- package/types/storages/inRedis/SegmentsCacheInRedis.d.ts +3 -3
- package/types/storages/inRedis/SplitsCacheInRedis.d.ts +10 -14
- package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +2 -2
- package/types/storages/inRedis/UniqueKeysCacheInRedis.d.ts +3 -2
- package/types/storages/pluggable/SplitsCachePluggable.d.ts +10 -9
- package/types/storages/types.d.ts +5 -5
- package/types/trackers/impressionObserver/utils.d.ts +1 -1
- package/types/types.d.ts +0 -2
- package/types/utils/constants/index.d.ts +12 -0
- package/types/utils/inputValidation/index.d.ts +2 -2
- package/types/utils/inputValidation/splitExistence.d.ts +7 -0
- package/types/utils/inputValidation/trafficTypeExistence.d.ts +9 -0
- package/types/utils/lang/sets.d.ts +1 -0
- package/types/utils/settingsValidation/splitFilters.d.ts +3 -2
package/esm/evaluator/index.js
CHANGED
|
@@ -2,7 +2,8 @@ import { Engine } from './Engine';
|
|
|
2
2
|
import { thenable } from '../utils/promise/thenable';
|
|
3
3
|
import * as LabelsConstants from '../utils/labels';
|
|
4
4
|
import { CONTROL } from '../utils/constants';
|
|
5
|
-
import { setToArray } from '../utils/lang/sets';
|
|
5
|
+
import { setToArray, returnSetsUnion, _Set } from '../utils/lang/sets';
|
|
6
|
+
import { WARN_FLAGSET_WITHOUT_FLAGS } from '../logger/constants';
|
|
6
7
|
var treatmentException = {
|
|
7
8
|
treatment: CONTROL,
|
|
8
9
|
label: LabelsConstants.EXCEPTION,
|
|
@@ -50,8 +51,23 @@ export function evaluateFeatures(log, key, splitNames, attributes, storage) {
|
|
|
50
51
|
}) :
|
|
51
52
|
getEvaluations(log, splitNames, parsedSplits, key, attributes, storage);
|
|
52
53
|
}
|
|
53
|
-
export function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, storage) {
|
|
54
|
+
export function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, storage, method) {
|
|
54
55
|
var storedFlagNames;
|
|
56
|
+
function evaluate(featureFlagsByFlagSets) {
|
|
57
|
+
var featureFlags = new _Set();
|
|
58
|
+
for (var i = 0; i < flagSets.length; i++) {
|
|
59
|
+
var featureFlagByFlagSet = featureFlagsByFlagSets[i];
|
|
60
|
+
if (featureFlagByFlagSet.size) {
|
|
61
|
+
featureFlags = returnSetsUnion(featureFlags, featureFlagByFlagSet);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
log.warn(WARN_FLAGSET_WITHOUT_FLAGS, [method, flagSets[i]]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return featureFlags.size ?
|
|
68
|
+
evaluateFeatures(log, key, setToArray(featureFlags), attributes, storage) :
|
|
69
|
+
{};
|
|
70
|
+
}
|
|
55
71
|
// get features by flag sets
|
|
56
72
|
try {
|
|
57
73
|
storedFlagNames = storage.splits.getNamesByFlagSets(flagSets);
|
|
@@ -62,8 +78,11 @@ export function evaluateFeaturesByFlagSets(log, key, flagSets, attributes, stora
|
|
|
62
78
|
}
|
|
63
79
|
// evaluate related features
|
|
64
80
|
return thenable(storedFlagNames) ?
|
|
65
|
-
storedFlagNames.then(function (
|
|
66
|
-
|
|
81
|
+
storedFlagNames.then(function (storedFlagNames) { return evaluate(storedFlagNames); })
|
|
82
|
+
.catch(function () {
|
|
83
|
+
return {};
|
|
84
|
+
}) :
|
|
85
|
+
evaluate(storedFlagNames);
|
|
67
86
|
}
|
|
68
87
|
function getEvaluation(log, splitJSON, key, attributes, storage) {
|
|
69
88
|
var evaluation = {
|
package/esm/logger/constants.js
CHANGED
|
@@ -89,14 +89,16 @@ export var WARN_NOT_EXISTENT_SPLIT = 215;
|
|
|
89
89
|
export var WARN_LOWERCASE_TRAFFIC_TYPE = 216;
|
|
90
90
|
export var WARN_NOT_EXISTENT_TT = 217;
|
|
91
91
|
export var WARN_INTEGRATION_INVALID = 218;
|
|
92
|
+
export var WARN_SPLITS_FILTER_IGNORED = 219;
|
|
92
93
|
export var WARN_SPLITS_FILTER_INVALID = 220;
|
|
93
94
|
export var WARN_SPLITS_FILTER_EMPTY = 221;
|
|
94
95
|
export var WARN_SDK_KEY = 222;
|
|
95
96
|
export var STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 = 223;
|
|
96
97
|
export var STREAMING_PARSING_SPLIT_UPDATE = 224;
|
|
97
|
-
export var
|
|
98
|
-
export var
|
|
98
|
+
export var WARN_INVALID_FLAGSET = 225;
|
|
99
|
+
export var WARN_LOWERCASE_FLAGSET = 226;
|
|
99
100
|
export var WARN_FLAGSET_NOT_CONFIGURED = 227;
|
|
101
|
+
export var WARN_FLAGSET_WITHOUT_FLAGS = 228;
|
|
100
102
|
export var ERROR_ENGINE_COMBINER_IFELSEIF = 300;
|
|
101
103
|
export var ERROR_LOGLEVEL_INVALID = 301;
|
|
102
104
|
export var ERROR_CLIENT_LISTENER = 302;
|
|
@@ -23,14 +23,16 @@ export var codesWarn = codesError.concat([
|
|
|
23
23
|
[c.WARN_NOT_EXISTENT_SPLIT, '%s: feature flag "%s" does not exist in this environment. Please double check what feature flags exist in the Split user interface.'],
|
|
24
24
|
[c.WARN_LOWERCASE_TRAFFIC_TYPE, '%s: traffic_type_name should be all lowercase - converting string to lowercase.'],
|
|
25
25
|
[c.WARN_NOT_EXISTENT_TT, '%s: traffic type "%s" does not have any corresponding feature flag in this environment, make sure you\'re tracking your events to a valid traffic type defined in the Split user interface.'],
|
|
26
|
-
[c.WARN_FLAGSET_NOT_CONFIGURED, '%s:
|
|
26
|
+
[c.WARN_FLAGSET_NOT_CONFIGURED, '%s: you passed %s which is not part of the configured FlagSetsFilter, ignoring Flag Set.'],
|
|
27
27
|
// initialization / settings validation
|
|
28
28
|
[c.WARN_INTEGRATION_INVALID, c.LOG_PREFIX_SETTINGS + ': %s integration item(s) at settings is invalid. %s'],
|
|
29
|
+
[c.WARN_SPLITS_FILTER_IGNORED, c.LOG_PREFIX_SETTINGS + ': feature flag filters are not applicable for Consumer modes where the SDK does not keep rollout data in sync. Filters were discarded'],
|
|
29
30
|
[c.WARN_SPLITS_FILTER_INVALID, c.LOG_PREFIX_SETTINGS + ': feature flag filter at position %s is invalid. It must be an object with a valid filter type ("bySet", "byName" or "byPrefix") and a list of "values".'],
|
|
30
31
|
[c.WARN_SPLITS_FILTER_EMPTY, c.LOG_PREFIX_SETTINGS + ': feature flag filter configuration must be a non-empty array of filter objects.'],
|
|
31
32
|
[c.WARN_SDK_KEY, c.LOG_PREFIX_SETTINGS + ': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'],
|
|
32
33
|
[c.STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, c.LOG_PREFIX_SYNC_STREAMING + 'Fetching MySegments due to an error processing %s notification: %s'],
|
|
33
34
|
[c.STREAMING_PARSING_SPLIT_UPDATE, c.LOG_PREFIX_SYNC_STREAMING + 'Fetching SplitChanges due to an error processing SPLIT_UPDATE notification: %s'],
|
|
34
|
-
[c.
|
|
35
|
-
[c.
|
|
35
|
+
[c.WARN_INVALID_FLAGSET, '%s: you passed %s, flag set must adhere to the regular expressions %s. This means a flag set must start with a letter or number, be in lowercase, alphanumeric and have a max length of 50 characters. %s was discarded.'],
|
|
36
|
+
[c.WARN_LOWERCASE_FLAGSET, '%s: flag set %s should be all lowercase - converting string to lowercase.'],
|
|
37
|
+
[c.WARN_FLAGSET_WITHOUT_FLAGS, '%s: you passed %s flag set that does not contain cached feature flag names. Please double check what flag sets are in use in the Split user interface.'],
|
|
36
38
|
]);
|
package/esm/sdkClient/client.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { evaluateFeature, evaluateFeatures, evaluateFeaturesByFlagSets } from '../evaluator';
|
|
2
2
|
import { thenable } from '../utils/promise/thenable';
|
|
3
3
|
import { getMatching, getBucketing } from '../utils/key';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { validateSplitExistence } from '../utils/inputValidation/splitExistence';
|
|
5
|
+
import { validateTrafficTypeExistence } from '../utils/inputValidation/trafficTypeExistence';
|
|
6
6
|
import { SDK_NOT_READY } from '../utils/labels';
|
|
7
|
-
import { CONTROL, TREATMENT, TREATMENTS, TREATMENT_WITH_CONFIG, TREATMENTS_WITH_CONFIG, TRACK, TREATMENTS_WITH_CONFIG_BY_FLAGSETS, TREATMENTS_BY_FLAGSETS, TREATMENTS_BY_FLAGSET, TREATMENTS_WITH_CONFIG_BY_FLAGSET } from '../utils/constants';
|
|
7
|
+
import { CONTROL, TREATMENT, TREATMENTS, TREATMENT_WITH_CONFIG, TREATMENTS_WITH_CONFIG, TRACK, TREATMENTS_WITH_CONFIG_BY_FLAGSETS, TREATMENTS_BY_FLAGSETS, TREATMENTS_BY_FLAGSET, TREATMENTS_WITH_CONFIG_BY_FLAGSET, GET_TREATMENTS_WITH_CONFIG, GET_TREATMENTS_BY_FLAG_SETS, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, GET_TREATMENTS_BY_FLAG_SET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, GET_TREATMENT_WITH_CONFIG, GET_TREATMENT, GET_TREATMENTS, TRACK_FN_LABEL } from '../utils/constants';
|
|
8
8
|
import { IMPRESSION, IMPRESSION_QUEUEING } from '../logger/constants';
|
|
9
9
|
import { isStorageSync } from '../trackers/impressionObserver/utils';
|
|
10
10
|
var treatmentNotReady = { treatment: CONTROL, label: SDK_NOT_READY };
|
|
@@ -21,12 +21,13 @@ function treatmentsNotReady(featureFlagNames) {
|
|
|
21
21
|
export function clientFactory(params) {
|
|
22
22
|
var readinessManager = params.sdkReadinessManager.readinessManager, storage = params.storage, settings = params.settings, impressionsTracker = params.impressionsTracker, eventTracker = params.eventTracker, telemetryTracker = params.telemetryTracker;
|
|
23
23
|
var log = settings.log, mode = settings.mode;
|
|
24
|
-
function getTreatment(key, featureFlagName, attributes, withConfig) {
|
|
24
|
+
function getTreatment(key, featureFlagName, attributes, withConfig, methodName) {
|
|
25
25
|
if (withConfig === void 0) { withConfig = false; }
|
|
26
|
+
if (methodName === void 0) { methodName = GET_TREATMENT; }
|
|
26
27
|
var stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENT_WITH_CONFIG : TREATMENT);
|
|
27
28
|
var wrapUp = function (evaluationResult) {
|
|
28
29
|
var queue = [];
|
|
29
|
-
var treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig,
|
|
30
|
+
var treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig, methodName, queue);
|
|
30
31
|
impressionsTracker.track(queue, attributes);
|
|
31
32
|
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
32
33
|
return treatment;
|
|
@@ -39,16 +40,17 @@ export function clientFactory(params) {
|
|
|
39
40
|
return thenable(evaluation) ? evaluation.then(function (res) { return wrapUp(res); }) : wrapUp(evaluation);
|
|
40
41
|
}
|
|
41
42
|
function getTreatmentWithConfig(key, featureFlagName, attributes) {
|
|
42
|
-
return getTreatment(key, featureFlagName, attributes, true);
|
|
43
|
+
return getTreatment(key, featureFlagName, attributes, true, GET_TREATMENT_WITH_CONFIG);
|
|
43
44
|
}
|
|
44
|
-
function getTreatments(key, featureFlagNames, attributes, withConfig) {
|
|
45
|
+
function getTreatments(key, featureFlagNames, attributes, withConfig, methodName) {
|
|
45
46
|
if (withConfig === void 0) { withConfig = false; }
|
|
47
|
+
if (methodName === void 0) { methodName = GET_TREATMENTS; }
|
|
46
48
|
var stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENTS_WITH_CONFIG : TREATMENTS);
|
|
47
49
|
var wrapUp = function (evaluationResults) {
|
|
48
50
|
var queue = [];
|
|
49
51
|
var treatments = {};
|
|
50
52
|
Object.keys(evaluationResults).forEach(function (featureFlagName) {
|
|
51
|
-
treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig,
|
|
53
|
+
treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
|
|
52
54
|
});
|
|
53
55
|
impressionsTracker.track(queue, attributes);
|
|
54
56
|
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
@@ -62,36 +64,37 @@ export function clientFactory(params) {
|
|
|
62
64
|
return thenable(evaluations) ? evaluations.then(function (res) { return wrapUp(res); }) : wrapUp(evaluations);
|
|
63
65
|
}
|
|
64
66
|
function getTreatmentsWithConfig(key, featureFlagNames, attributes) {
|
|
65
|
-
return getTreatments(key, featureFlagNames, attributes, true);
|
|
67
|
+
return getTreatments(key, featureFlagNames, attributes, true, GET_TREATMENTS_WITH_CONFIG);
|
|
66
68
|
}
|
|
67
|
-
function getTreatmentsByFlagSets(key, flagSetNames, attributes, withConfig, method) {
|
|
69
|
+
function getTreatmentsByFlagSets(key, flagSetNames, attributes, withConfig, method, methodName) {
|
|
68
70
|
if (withConfig === void 0) { withConfig = false; }
|
|
69
71
|
if (method === void 0) { method = TREATMENTS_BY_FLAGSETS; }
|
|
72
|
+
if (methodName === void 0) { methodName = GET_TREATMENTS_BY_FLAG_SETS; }
|
|
70
73
|
var stopTelemetryTracker = telemetryTracker.trackEval(method);
|
|
71
74
|
var wrapUp = function (evaluationResults) {
|
|
72
75
|
var queue = [];
|
|
73
76
|
var treatments = {};
|
|
74
77
|
var evaluations = evaluationResults;
|
|
75
78
|
Object.keys(evaluations).forEach(function (featureFlagName) {
|
|
76
|
-
treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig,
|
|
79
|
+
treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
|
|
77
80
|
});
|
|
78
81
|
impressionsTracker.track(queue, attributes);
|
|
79
82
|
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
80
83
|
return treatments;
|
|
81
84
|
};
|
|
82
85
|
var evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
|
|
83
|
-
evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage) :
|
|
86
|
+
evaluateFeaturesByFlagSets(log, key, flagSetNames, attributes, storage, methodName) :
|
|
84
87
|
isStorageSync(settings) ? {} : Promise.resolve({}); // Promisify if async
|
|
85
88
|
return thenable(evaluations) ? evaluations.then(function (res) { return wrapUp(res); }) : wrapUp(evaluations);
|
|
86
89
|
}
|
|
87
90
|
function getTreatmentsWithConfigByFlagSets(key, flagSetNames, attributes) {
|
|
88
|
-
return getTreatmentsByFlagSets(key, flagSetNames, attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSETS);
|
|
91
|
+
return getTreatmentsByFlagSets(key, flagSetNames, attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSETS, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS);
|
|
89
92
|
}
|
|
90
93
|
function getTreatmentsByFlagSet(key, flagSetName, attributes) {
|
|
91
|
-
return getTreatmentsByFlagSets(key, [flagSetName], attributes, false, TREATMENTS_BY_FLAGSET);
|
|
94
|
+
return getTreatmentsByFlagSets(key, [flagSetName], attributes, false, TREATMENTS_BY_FLAGSET, GET_TREATMENTS_BY_FLAG_SET);
|
|
92
95
|
}
|
|
93
96
|
function getTreatmentsWithConfigByFlagSet(key, flagSetName, attributes) {
|
|
94
|
-
return getTreatmentsByFlagSets(key, [flagSetName], attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSET);
|
|
97
|
+
return getTreatmentsByFlagSets(key, [flagSetName], attributes, true, TREATMENTS_WITH_CONFIG_BY_FLAGSET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET);
|
|
95
98
|
}
|
|
96
99
|
// Internal function
|
|
97
100
|
function processEvaluation(evaluation, featureFlagName, key, attributes, withConfig, invokingMethodName, queue) {
|
|
@@ -99,7 +102,7 @@ export function clientFactory(params) {
|
|
|
99
102
|
var bucketingKey = getBucketing(key);
|
|
100
103
|
var treatment = evaluation.treatment, label = evaluation.label, changeNumber = evaluation.changeNumber, _a = evaluation.config, config = _a === void 0 ? null : _a;
|
|
101
104
|
log.info(IMPRESSION, [featureFlagName, matchingKey, treatment, label]);
|
|
102
|
-
if (
|
|
105
|
+
if (validateSplitExistence(log, readinessManager, featureFlagName, label, invokingMethodName)) {
|
|
103
106
|
log.info(IMPRESSION_QUEUEING);
|
|
104
107
|
queue.push({
|
|
105
108
|
feature: featureFlagName,
|
|
@@ -133,7 +136,7 @@ export function clientFactory(params) {
|
|
|
133
136
|
properties: properties
|
|
134
137
|
};
|
|
135
138
|
// This may be async but we only warn, we don't actually care if it is valid or not in terms of queueing the event.
|
|
136
|
-
|
|
139
|
+
validateTrafficTypeExistence(log, readinessManager, storage.splits, mode, trafficTypeName, TRACK_FN_LABEL);
|
|
137
140
|
var result = eventTracker.track(eventData, size);
|
|
138
141
|
if (thenable(result)) {
|
|
139
142
|
return result.then(function (result) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { validateAttributes, validateEvent, validateEventValue, validateEventProperties, validateKey, validateSplit, validateSplits, validateTrafficType, validateIfNotDestroyed, validateIfOperational } from '../utils/inputValidation';
|
|
3
3
|
import { startsWith } from '../utils/lang';
|
|
4
|
-
import { CONTROL, CONTROL_WITH_CONFIG } from '../utils/constants';
|
|
4
|
+
import { CONTROL, CONTROL_WITH_CONFIG, GET_TREATMENT, GET_TREATMENTS, GET_TREATMENTS_BY_FLAG_SET, GET_TREATMENTS_BY_FLAG_SETS, GET_TREATMENTS_WITH_CONFIG, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, GET_TREATMENT_WITH_CONFIG, TRACK_FN_LABEL } from '../utils/constants';
|
|
5
5
|
import { isStorageSync } from '../trackers/impressionObserver/utils';
|
|
6
|
-
import {
|
|
6
|
+
import { validateFlagSets } from '../utils/settingsValidation/splitFilters';
|
|
7
7
|
/**
|
|
8
8
|
* Decorator that validates the input before actually executing the client methods.
|
|
9
9
|
* We should "guard" the client here, while not polluting the "real" implementation of those methods.
|
|
@@ -15,7 +15,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
15
15
|
* Avoid repeating this validations code
|
|
16
16
|
*/
|
|
17
17
|
function validateEvaluationParams(maybeKey, maybeFeatureFlagNameOrNames, maybeAttributes, methodName, maybeFlagSetNameOrNames) {
|
|
18
|
-
var multi = startsWith(methodName,
|
|
18
|
+
var multi = startsWith(methodName, GET_TREATMENTS);
|
|
19
19
|
var key = validateKey(log, maybeKey, methodName);
|
|
20
20
|
var splitOrSplits = false;
|
|
21
21
|
var flagSetOrFlagSets = [];
|
|
@@ -25,7 +25,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
25
25
|
var attributes = validateAttributes(log, maybeAttributes, methodName);
|
|
26
26
|
var isNotDestroyed = validateIfNotDestroyed(log, readinessManager, methodName);
|
|
27
27
|
if (maybeFlagSetNameOrNames) {
|
|
28
|
-
flagSetOrFlagSets =
|
|
28
|
+
flagSetOrFlagSets = validateFlagSets(log, methodName, maybeFlagSetNameOrNames, settings.sync.__splitFiltersValidation.groupedFilters.bySet);
|
|
29
29
|
}
|
|
30
30
|
validateIfOperational(log, readinessManager, methodName, splitOrSplits);
|
|
31
31
|
var valid = isNotDestroyed && key && (splitOrSplits || flagSetOrFlagSets.length > 0) && attributes !== false;
|
|
@@ -41,7 +41,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
41
41
|
return isSync ? value : Promise.resolve(value);
|
|
42
42
|
}
|
|
43
43
|
function getTreatment(maybeKey, maybeFeatureFlagName, maybeAttributes) {
|
|
44
|
-
var params = validateEvaluationParams(maybeKey, maybeFeatureFlagName, maybeAttributes,
|
|
44
|
+
var params = validateEvaluationParams(maybeKey, maybeFeatureFlagName, maybeAttributes, GET_TREATMENT);
|
|
45
45
|
if (params.valid) {
|
|
46
46
|
return client.getTreatment(params.key, params.splitOrSplits, params.attributes);
|
|
47
47
|
}
|
|
@@ -50,7 +50,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
function getTreatmentWithConfig(maybeKey, maybeFeatureFlagName, maybeAttributes) {
|
|
53
|
-
var params = validateEvaluationParams(maybeKey, maybeFeatureFlagName, maybeAttributes,
|
|
53
|
+
var params = validateEvaluationParams(maybeKey, maybeFeatureFlagName, maybeAttributes, GET_TREATMENT_WITH_CONFIG);
|
|
54
54
|
if (params.valid) {
|
|
55
55
|
return client.getTreatmentWithConfig(params.key, params.splitOrSplits, params.attributes);
|
|
56
56
|
}
|
|
@@ -59,7 +59,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
function getTreatments(maybeKey, maybeFeatureFlagNames, maybeAttributes) {
|
|
62
|
-
var params = validateEvaluationParams(maybeKey, maybeFeatureFlagNames, maybeAttributes,
|
|
62
|
+
var params = validateEvaluationParams(maybeKey, maybeFeatureFlagNames, maybeAttributes, GET_TREATMENTS);
|
|
63
63
|
if (params.valid) {
|
|
64
64
|
return client.getTreatments(params.key, params.splitOrSplits, params.attributes);
|
|
65
65
|
}
|
|
@@ -71,7 +71,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
function getTreatmentsWithConfig(maybeKey, maybeFeatureFlagNames, maybeAttributes) {
|
|
74
|
-
var params = validateEvaluationParams(maybeKey, maybeFeatureFlagNames, maybeAttributes,
|
|
74
|
+
var params = validateEvaluationParams(maybeKey, maybeFeatureFlagNames, maybeAttributes, GET_TREATMENTS_WITH_CONFIG);
|
|
75
75
|
if (params.valid) {
|
|
76
76
|
return client.getTreatmentsWithConfig(params.key, params.splitOrSplits, params.attributes);
|
|
77
77
|
}
|
|
@@ -83,7 +83,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
function getTreatmentsByFlagSets(maybeKey, maybeFlagSets, maybeAttributes) {
|
|
86
|
-
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes,
|
|
86
|
+
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, GET_TREATMENTS_BY_FLAG_SETS, maybeFlagSets);
|
|
87
87
|
if (params.valid) {
|
|
88
88
|
return client.getTreatmentsByFlagSets(params.key, params.flagSetOrFlagSets, params.attributes);
|
|
89
89
|
}
|
|
@@ -92,7 +92,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
function getTreatmentsWithConfigByFlagSets(maybeKey, maybeFlagSets, maybeAttributes) {
|
|
95
|
-
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes,
|
|
95
|
+
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, maybeFlagSets);
|
|
96
96
|
if (params.valid) {
|
|
97
97
|
return client.getTreatmentsWithConfigByFlagSets(params.key, params.flagSetOrFlagSets, params.attributes);
|
|
98
98
|
}
|
|
@@ -101,7 +101,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
function getTreatmentsByFlagSet(maybeKey, maybeFlagSet, maybeAttributes) {
|
|
104
|
-
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes,
|
|
104
|
+
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, GET_TREATMENTS_BY_FLAG_SET, [maybeFlagSet]);
|
|
105
105
|
if (params.valid) {
|
|
106
106
|
return client.getTreatmentsByFlagSet(params.key, params.flagSetOrFlagSets[0], params.attributes);
|
|
107
107
|
}
|
|
@@ -110,7 +110,7 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
function getTreatmentsWithConfigByFlagSet(maybeKey, maybeFlagSet, maybeAttributes) {
|
|
113
|
-
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes,
|
|
113
|
+
var params = validateEvaluationParams(maybeKey, undefined, maybeAttributes, GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET, [maybeFlagSet]);
|
|
114
114
|
if (params.valid) {
|
|
115
115
|
return client.getTreatmentsWithConfigByFlagSet(params.key, params.flagSetOrFlagSets[0], params.attributes);
|
|
116
116
|
}
|
|
@@ -119,12 +119,12 @@ export function clientInputValidationDecorator(settings, client, readinessManage
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
function track(maybeKey, maybeTT, maybeEvent, maybeEventValue, maybeProperties) {
|
|
122
|
-
var key = validateKey(log, maybeKey,
|
|
123
|
-
var tt = validateTrafficType(log, maybeTT,
|
|
124
|
-
var event = validateEvent(log, maybeEvent,
|
|
125
|
-
var eventValue = validateEventValue(log, maybeEventValue,
|
|
126
|
-
var _a = validateEventProperties(log, maybeProperties,
|
|
127
|
-
var isNotDestroyed = validateIfNotDestroyed(log, readinessManager,
|
|
122
|
+
var key = validateKey(log, maybeKey, TRACK_FN_LABEL);
|
|
123
|
+
var tt = validateTrafficType(log, maybeTT, TRACK_FN_LABEL);
|
|
124
|
+
var event = validateEvent(log, maybeEvent, TRACK_FN_LABEL);
|
|
125
|
+
var eventValue = validateEventValue(log, maybeEventValue, TRACK_FN_LABEL);
|
|
126
|
+
var _a = validateEventProperties(log, maybeProperties, TRACK_FN_LABEL), properties = _a.properties, size = _a.size;
|
|
127
|
+
var isNotDestroyed = validateIfNotDestroyed(log, readinessManager, TRACK_FN_LABEL);
|
|
128
128
|
if (isNotDestroyed && key && tt && event && eventValue !== false && properties !== false) { // @ts-expect-error
|
|
129
129
|
return client.track(key, tt, event, eventValue, properties, size);
|
|
130
130
|
}
|
package/esm/sdkFactory/index.js
CHANGED
|
@@ -63,7 +63,7 @@ export function sdkFactory(params) {
|
|
|
63
63
|
ctx.signalListener = signalListener;
|
|
64
64
|
// SDK client and manager
|
|
65
65
|
var clientMethod = sdkClientMethodFactory(ctx);
|
|
66
|
-
var managerInstance = sdkManagerFactory(
|
|
66
|
+
var managerInstance = sdkManagerFactory(settings, storage.splits, sdkReadinessManager);
|
|
67
67
|
syncManager && syncManager.start();
|
|
68
68
|
signalListener && signalListener.start();
|
|
69
69
|
log.info(NEW_FACTORY);
|
package/esm/sdkManager/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { thenable } from '../utils/promise/thenable';
|
|
3
3
|
import { find } from '../utils/lang';
|
|
4
|
-
import { validateSplit,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
var NAMES_FN_LABEL = 'names';
|
|
4
|
+
import { validateSplit, validateSplitExistence, validateIfNotDestroyed, validateIfOperational } from '../utils/inputValidation';
|
|
5
|
+
import { isStorageSync } from '../trackers/impressionObserver/utils';
|
|
6
|
+
import { SPLIT_FN_LABEL, SPLITS_FN_LABEL, NAMES_FN_LABEL } from '../utils/constants';
|
|
8
7
|
function collectTreatments(splitObject) {
|
|
9
8
|
var conditions = splitObject.conditions;
|
|
10
9
|
// Rollout conditions are supposed to have the entire partitions list, so we find the first one.
|
|
@@ -38,8 +37,10 @@ function objectsToViews(splitObjects) {
|
|
|
38
37
|
});
|
|
39
38
|
return views;
|
|
40
39
|
}
|
|
41
|
-
export function sdkManagerFactory(
|
|
40
|
+
export function sdkManagerFactory(settings, splits, _a) {
|
|
42
41
|
var readinessManager = _a.readinessManager, sdkStatus = _a.sdkStatus;
|
|
42
|
+
var log = settings.log;
|
|
43
|
+
var isSync = isStorageSync(settings);
|
|
43
44
|
return objectAssign(
|
|
44
45
|
// Proto-linkage of the readiness Event Emitter
|
|
45
46
|
Object.create(sdkStatus), {
|
|
@@ -49,16 +50,16 @@ export function sdkManagerFactory(log, splits, _a) {
|
|
|
49
50
|
split: function (featureFlagName) {
|
|
50
51
|
var splitName = validateSplit(log, featureFlagName, SPLIT_FN_LABEL);
|
|
51
52
|
if (!validateIfNotDestroyed(log, readinessManager, SPLIT_FN_LABEL) || !validateIfOperational(log, readinessManager, SPLIT_FN_LABEL) || !splitName) {
|
|
52
|
-
return null;
|
|
53
|
+
return isSync ? null : Promise.resolve(null);
|
|
53
54
|
}
|
|
54
55
|
var split = splits.getSplit(splitName);
|
|
55
56
|
if (thenable(split)) {
|
|
56
57
|
return split.catch(function () { return null; }).then(function (result) {
|
|
57
|
-
|
|
58
|
+
validateSplitExistence(log, readinessManager, splitName, result, SPLIT_FN_LABEL);
|
|
58
59
|
return objectToView(result);
|
|
59
60
|
});
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
+
validateSplitExistence(log, readinessManager, splitName, split, SPLIT_FN_LABEL);
|
|
62
63
|
return objectToView(split);
|
|
63
64
|
},
|
|
64
65
|
/**
|
|
@@ -66,7 +67,7 @@ export function sdkManagerFactory(log, splits, _a) {
|
|
|
66
67
|
*/
|
|
67
68
|
splits: function () {
|
|
68
69
|
if (!validateIfNotDestroyed(log, readinessManager, SPLITS_FN_LABEL) || !validateIfOperational(log, readinessManager, SPLITS_FN_LABEL)) {
|
|
69
|
-
return [];
|
|
70
|
+
return isSync ? [] : Promise.resolve([]);
|
|
70
71
|
}
|
|
71
72
|
var currentSplits = splits.getAll();
|
|
72
73
|
return thenable(currentSplits) ?
|
|
@@ -78,7 +79,7 @@ export function sdkManagerFactory(log, splits, _a) {
|
|
|
78
79
|
*/
|
|
79
80
|
names: function () {
|
|
80
81
|
if (!validateIfNotDestroyed(log, readinessManager, NAMES_FN_LABEL) || !validateIfOperational(log, readinessManager, NAMES_FN_LABEL)) {
|
|
81
|
-
return [];
|
|
82
|
+
return isSync ? [] : Promise.resolve([]);
|
|
82
83
|
}
|
|
83
84
|
var splitNames = splits.getSplitNames();
|
|
84
85
|
return thenable(splitNames) ?
|
|
@@ -13,7 +13,7 @@ var KeyBuilder = /** @class */ (function () {
|
|
|
13
13
|
return this.prefix + ".trafficType." + trafficType;
|
|
14
14
|
};
|
|
15
15
|
KeyBuilder.prototype.buildFlagSetKey = function (flagSet) {
|
|
16
|
-
return this.prefix + ".
|
|
16
|
+
return this.prefix + ".flagSet." + flagSet;
|
|
17
17
|
};
|
|
18
18
|
KeyBuilder.prototype.buildSplitKey = function (splitName) {
|
|
19
19
|
return this.prefix + ".split." + splitName;
|
|
@@ -2,7 +2,7 @@ import { __extends } from "tslib";
|
|
|
2
2
|
import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
|
|
3
3
|
import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
|
|
4
4
|
import { LOG_PREFIX } from './constants';
|
|
5
|
-
import { _Set,
|
|
5
|
+
import { _Set, setToArray } from '../../utils/lang/sets';
|
|
6
6
|
/**
|
|
7
7
|
* ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
|
|
8
8
|
*/
|
|
@@ -228,16 +228,11 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
228
228
|
};
|
|
229
229
|
SplitsCacheInLocal.prototype.getNamesByFlagSets = function (flagSets) {
|
|
230
230
|
var _this = this;
|
|
231
|
-
|
|
232
|
-
flagSets.forEach(function (flagSet) {
|
|
231
|
+
return flagSets.map(function (flagSet) {
|
|
233
232
|
var flagSetKey = _this.keys.buildFlagSetKey(flagSet);
|
|
234
233
|
var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
|
|
235
|
-
|
|
236
|
-
var flagSetCache = new _Set(JSON.parse(flagSetFromLocalStorage));
|
|
237
|
-
toReturn = returnSetsUnion(toReturn, flagSetCache);
|
|
238
|
-
}
|
|
234
|
+
return new _Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
|
|
239
235
|
});
|
|
240
|
-
return toReturn;
|
|
241
236
|
};
|
|
242
237
|
SplitsCacheInLocal.prototype.addToFlagSets = function (featureFlag) {
|
|
243
238
|
var _this = this;
|
|
@@ -248,9 +243,7 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
|
248
243
|
return;
|
|
249
244
|
var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
|
|
250
245
|
var flagSetFromLocalStorage = localStorage.getItem(flagSetKey);
|
|
251
|
-
|
|
252
|
-
flagSetFromLocalStorage = '[]';
|
|
253
|
-
var flagSetCache = new _Set(JSON.parse(flagSetFromLocalStorage));
|
|
246
|
+
var flagSetCache = new _Set(flagSetFromLocalStorage ? JSON.parse(flagSetFromLocalStorage) : []);
|
|
254
247
|
flagSetCache.add(featureFlag.name);
|
|
255
248
|
localStorage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
|
|
256
249
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __extends } from "tslib";
|
|
2
2
|
import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
|
|
3
3
|
import { isFiniteNumber } from '../../utils/lang';
|
|
4
|
-
import { _Set
|
|
4
|
+
import { _Set } from '../../utils/lang/sets';
|
|
5
5
|
/**
|
|
6
6
|
* Default ISplitsCacheSync implementation that stores split definitions in memory.
|
|
7
7
|
* Supported by all JS runtimes.
|
|
@@ -9,14 +9,13 @@ import { _Set, returnSetsUnion } from '../../utils/lang/sets';
|
|
|
9
9
|
var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
10
10
|
__extends(SplitsCacheInMemory, _super);
|
|
11
11
|
function SplitsCacheInMemory(splitFiltersValidation) {
|
|
12
|
-
if (splitFiltersValidation === void 0) { splitFiltersValidation = { queryString: null, groupedFilters: { bySet: [], byName: [], byPrefix: [] }, validFilters: [] }; }
|
|
13
12
|
var _this = _super.call(this) || this;
|
|
14
13
|
_this.splitsCache = {};
|
|
15
14
|
_this.ttCache = {};
|
|
16
15
|
_this.changeNumber = -1;
|
|
17
16
|
_this.splitsWithSegmentsCount = 0;
|
|
18
17
|
_this.flagSetsCache = {};
|
|
19
|
-
_this.flagSetsFilter = splitFiltersValidation.groupedFilters.bySet;
|
|
18
|
+
_this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
|
|
20
19
|
return _this;
|
|
21
20
|
}
|
|
22
21
|
SplitsCacheInMemory.prototype.clear = function () {
|
|
@@ -93,14 +92,7 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
|
|
|
93
92
|
};
|
|
94
93
|
SplitsCacheInMemory.prototype.getNamesByFlagSets = function (flagSets) {
|
|
95
94
|
var _this = this;
|
|
96
|
-
|
|
97
|
-
flagSets.forEach(function (flagSet) {
|
|
98
|
-
var featureFlagNames = _this.flagSetsCache[flagSet];
|
|
99
|
-
if (featureFlagNames) {
|
|
100
|
-
toReturn = returnSetsUnion(toReturn, featureFlagNames);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
return toReturn;
|
|
95
|
+
return flagSets.map(function (flagSet) { return _this.flagSetsCache[flagSet] || new _Set(); });
|
|
104
96
|
};
|
|
105
97
|
SplitsCacheInMemory.prototype.addToFlagSets = function (featureFlag) {
|
|
106
98
|
var _this = this;
|
|
@@ -6,7 +6,8 @@ import { thenable } from '../../utils/promise/thenable';
|
|
|
6
6
|
import { timeout } from '../../utils/promise/timeout';
|
|
7
7
|
var LOG_PREFIX = 'storage:redis-adapter: ';
|
|
8
8
|
// If we ever decide to fully wrap every method, there's a Commander.getBuiltinCommands from ioredis.
|
|
9
|
-
var METHODS_TO_PROMISE_WRAP = ['set', 'exec', 'del', 'get', 'keys', 'sadd', 'srem', 'sismember', 'smembers', 'incr', 'rpush', '
|
|
9
|
+
var METHODS_TO_PROMISE_WRAP = ['set', 'exec', 'del', 'get', 'keys', 'sadd', 'srem', 'sismember', 'smembers', 'incr', 'rpush', 'expire', 'mget', 'lrange', 'ltrim', 'hset', 'hincrby', 'popNRaw'];
|
|
10
|
+
var METHODS_TO_PROMISE_WRAP_EXEC = ['pipeline'];
|
|
10
11
|
// Not part of the settings since it'll vary on each storage. We should be removing storage specific logic from elsewhere.
|
|
11
12
|
var DEFAULT_OPTIONS = {
|
|
12
13
|
connectionTimeout: 10000,
|
|
@@ -24,6 +25,7 @@ var DEFAULT_LIBRARY_OPTIONS = {
|
|
|
24
25
|
var RedisAdapter = /** @class */ (function (_super) {
|
|
25
26
|
__extends(RedisAdapter, _super);
|
|
26
27
|
function RedisAdapter(log, storageSettings) {
|
|
28
|
+
if (storageSettings === void 0) { storageSettings = {}; }
|
|
27
29
|
var _this = this;
|
|
28
30
|
var options = RedisAdapter._defineOptions(storageSettings);
|
|
29
31
|
// Call the ioredis constructor
|
|
@@ -55,14 +57,15 @@ var RedisAdapter = /** @class */ (function (_super) {
|
|
|
55
57
|
};
|
|
56
58
|
RedisAdapter.prototype._setTimeoutWrappers = function () {
|
|
57
59
|
var instance = this;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
instance
|
|
60
|
+
var wrapCommand = function (originalMethod, methodName) {
|
|
61
|
+
// The value of "this" in this function should be the instance actually executing the method. It might be the instance referred (the base one)
|
|
62
|
+
// or it can be the instance of a Pipeline object.
|
|
63
|
+
return function () {
|
|
61
64
|
var params = arguments;
|
|
65
|
+
var caller = this;
|
|
62
66
|
function commandWrapper() {
|
|
63
|
-
instance.log.debug(LOG_PREFIX +
|
|
64
|
-
|
|
65
|
-
var result = originalMethod.apply(instance, params);
|
|
67
|
+
instance.log.debug(LOG_PREFIX + "Executing " + methodName + ".");
|
|
68
|
+
var result = originalMethod.apply(caller, params);
|
|
66
69
|
if (thenable(result)) {
|
|
67
70
|
// For handling pending commands on disconnect, add to the set and remove once finished.
|
|
68
71
|
// On sync commands there's no need, only thenables.
|
|
@@ -73,7 +76,7 @@ var RedisAdapter = /** @class */ (function (_super) {
|
|
|
73
76
|
// Both success and error remove from queue.
|
|
74
77
|
result.then(cleanUpRunningCommandsCb, cleanUpRunningCommandsCb);
|
|
75
78
|
return timeout(instance._options.operationTimeout, result).catch(function (err) {
|
|
76
|
-
instance.log.error(LOG_PREFIX +
|
|
79
|
+
instance.log.error("" + LOG_PREFIX + methodName + " operation threw an error or exceeded configured timeout of " + instance._options.operationTimeout + "ms. Message: " + err);
|
|
77
80
|
// Handling is not the adapter responsibility.
|
|
78
81
|
throw err;
|
|
79
82
|
});
|
|
@@ -81,12 +84,12 @@ var RedisAdapter = /** @class */ (function (_super) {
|
|
|
81
84
|
return result;
|
|
82
85
|
}
|
|
83
86
|
if (instance._notReadyCommandsQueue) {
|
|
84
|
-
return new Promise(function (
|
|
87
|
+
return new Promise(function (resolve, reject) {
|
|
85
88
|
instance._notReadyCommandsQueue.unshift({
|
|
86
|
-
resolve:
|
|
87
|
-
reject:
|
|
89
|
+
resolve: resolve,
|
|
90
|
+
reject: reject,
|
|
88
91
|
command: commandWrapper,
|
|
89
|
-
name:
|
|
92
|
+
name: methodName.toUpperCase()
|
|
90
93
|
});
|
|
91
94
|
});
|
|
92
95
|
}
|
|
@@ -94,6 +97,22 @@ var RedisAdapter = /** @class */ (function (_super) {
|
|
|
94
97
|
return commandWrapper();
|
|
95
98
|
}
|
|
96
99
|
};
|
|
100
|
+
};
|
|
101
|
+
// Wrap regular async methods to track timeouts and queue when Redis is not yet executing commands.
|
|
102
|
+
METHODS_TO_PROMISE_WRAP.forEach(function (methodName) {
|
|
103
|
+
var originalFn = instance[methodName];
|
|
104
|
+
instance[methodName] = wrapCommand(originalFn, methodName);
|
|
105
|
+
});
|
|
106
|
+
// Special handling for pipeline~like methods. We need to wrap the async trigger, which is exec, but return the Pipeline right away.
|
|
107
|
+
METHODS_TO_PROMISE_WRAP_EXEC.forEach(function (methodName) {
|
|
108
|
+
var originalFn = instance[methodName];
|
|
109
|
+
// "First level wrapper" to handle the sync execution and wrap async, queueing later if applicable.
|
|
110
|
+
instance[methodName] = function () {
|
|
111
|
+
var res = originalFn.apply(instance, arguments);
|
|
112
|
+
var originalExec = res.exec;
|
|
113
|
+
res.exec = wrapCommand(originalExec, methodName + '.exec').bind(res);
|
|
114
|
+
return res;
|
|
115
|
+
};
|
|
97
116
|
});
|
|
98
117
|
};
|
|
99
118
|
RedisAdapter.prototype._setDisconnectWrapper = function () {
|
|
@@ -104,7 +123,7 @@ var RedisAdapter = /** @class */ (function (_super) {
|
|
|
104
123
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
105
124
|
params[_i] = arguments[_i];
|
|
106
125
|
}
|
|
107
|
-
setTimeout(function
|
|
126
|
+
setTimeout(function deferredDisconnect() {
|
|
108
127
|
if (instance._runningCommands.size > 0) {
|
|
109
128
|
instance.log.info(LOG_PREFIX + ("Attempting to disconnect but there are " + instance._runningCommands.size + " commands still waiting for resolution. Defering disconnection until those finish."));
|
|
110
129
|
Promise.all(setToArray(instance._runningCommands))
|
|
@@ -51,9 +51,9 @@ var SegmentsCacheInRedis = /** @class */ (function () {
|
|
|
51
51
|
SegmentsCacheInRedis.prototype.getRegisteredSegments = function () {
|
|
52
52
|
return this.redis.smembers(this.keys.buildRegisteredSegmentsKey());
|
|
53
53
|
};
|
|
54
|
-
// @TODO remove
|
|
54
|
+
// @TODO remove or implement. It is not being used.
|
|
55
55
|
SegmentsCacheInRedis.prototype.clear = function () {
|
|
56
|
-
return
|
|
56
|
+
return Promise.resolve();
|
|
57
57
|
};
|
|
58
58
|
return SegmentsCacheInRedis;
|
|
59
59
|
}());
|