@splitsoftware/splitio-commons 1.11.0 → 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.
Files changed (132) hide show
  1. package/CHANGES.txt +15 -9
  2. package/cjs/evaluator/index.js +19 -3
  3. package/cjs/logger/constants.js +6 -4
  4. package/cjs/logger/messages/warn.js +5 -3
  5. package/cjs/sdkClient/client.js +19 -16
  6. package/cjs/sdkClient/clientInputValidation.js +16 -16
  7. package/cjs/sdkFactory/index.js +1 -1
  8. package/cjs/sdkManager/index.js +14 -13
  9. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +3 -10
  10. package/cjs/storages/inMemory/SplitsCacheInMemory.js +2 -10
  11. package/cjs/storages/inRedis/RedisAdapter.js +32 -13
  12. package/cjs/storages/inRedis/SegmentsCacheInRedis.js +2 -2
  13. package/cjs/storages/inRedis/SplitsCacheInRedis.js +39 -22
  14. package/cjs/storages/inRedis/index.js +1 -1
  15. package/cjs/storages/pluggable/SplitsCachePluggable.js +28 -11
  16. package/cjs/storages/pluggable/index.js +1 -1
  17. package/cjs/utils/constants/index.js +16 -2
  18. package/cjs/utils/inputValidation/index.js +5 -5
  19. package/cjs/utils/inputValidation/{splitExistance.js → splitExistence.js} +3 -3
  20. package/cjs/utils/inputValidation/{trafficTypeExistance.js → trafficTypeExistence.js} +6 -6
  21. package/cjs/utils/lang/sets.js +11 -1
  22. package/cjs/utils/settingsValidation/index.js +1 -1
  23. package/cjs/utils/settingsValidation/splitFilters.js +25 -17
  24. package/esm/evaluator/index.js +20 -4
  25. package/esm/logger/constants.js +4 -2
  26. package/esm/logger/messages/warn.js +5 -3
  27. package/esm/sdkClient/client.js +20 -17
  28. package/esm/sdkClient/clientInputValidation.js +18 -18
  29. package/esm/sdkFactory/index.js +1 -1
  30. package/esm/sdkManager/index.js +11 -10
  31. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +4 -11
  32. package/esm/storages/inMemory/SplitsCacheInMemory.js +3 -11
  33. package/esm/storages/inRedis/RedisAdapter.js +32 -13
  34. package/esm/storages/inRedis/SegmentsCacheInRedis.js +2 -2
  35. package/esm/storages/inRedis/SplitsCacheInRedis.js +40 -23
  36. package/esm/storages/inRedis/index.js +1 -1
  37. package/esm/storages/pluggable/SplitsCachePluggable.js +29 -12
  38. package/esm/storages/pluggable/index.js +1 -1
  39. package/esm/utils/constants/index.js +14 -0
  40. package/esm/utils/inputValidation/index.js +2 -2
  41. package/esm/utils/inputValidation/{splitExistance.js → splitExistence.js} +1 -1
  42. package/esm/utils/inputValidation/{trafficTypeExistance.js → trafficTypeExistence.js} +4 -4
  43. package/esm/utils/lang/sets.js +9 -0
  44. package/esm/utils/settingsValidation/index.js +1 -1
  45. package/esm/utils/settingsValidation/splitFilters.js +17 -9
  46. package/package.json +1 -1
  47. package/src/evaluator/index.ts +24 -4
  48. package/src/logger/constants.ts +4 -2
  49. package/src/logger/messages/warn.ts +9 -7
  50. package/src/sdkClient/client.ts +18 -18
  51. package/src/sdkClient/clientInputValidation.ts +18 -18
  52. package/src/sdkFactory/index.ts +1 -1
  53. package/src/sdkFactory/types.ts +3 -7
  54. package/src/sdkManager/index.ts +14 -14
  55. package/src/storages/AbstractSplitsCacheAsync.ts +1 -1
  56. package/src/storages/AbstractSplitsCacheSync.ts +1 -1
  57. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +8 -15
  58. package/src/storages/inMemory/SplitsCacheInMemory.ts +6 -14
  59. package/src/storages/inRedis/EventsCacheInRedis.ts +3 -3
  60. package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +3 -3
  61. package/src/storages/inRedis/ImpressionsCacheInRedis.ts +3 -3
  62. package/src/storages/inRedis/RedisAdapter.ts +38 -16
  63. package/src/storages/inRedis/SegmentsCacheInRedis.ts +5 -5
  64. package/src/storages/inRedis/SplitsCacheInRedis.ts +49 -28
  65. package/src/storages/inRedis/TelemetryCacheInRedis.ts +2 -2
  66. package/src/storages/inRedis/UniqueKeysCacheInRedis.ts +3 -3
  67. package/src/storages/inRedis/index.ts +1 -1
  68. package/src/storages/pluggable/SplitsCachePluggable.ts +35 -13
  69. package/src/storages/pluggable/index.ts +1 -1
  70. package/src/storages/types.ts +5 -5
  71. package/src/trackers/impressionObserver/utils.ts +1 -1
  72. package/src/types.ts +0 -2
  73. package/src/utils/constants/index.ts +16 -0
  74. package/src/utils/inputValidation/index.ts +2 -2
  75. package/src/utils/inputValidation/{splitExistance.ts → splitExistence.ts} +1 -1
  76. package/src/utils/inputValidation/{trafficTypeExistance.ts → trafficTypeExistence.ts} +4 -4
  77. package/src/utils/lang/sets.ts +9 -1
  78. package/src/utils/redis/RedisMock.ts +1 -3
  79. package/src/utils/settingsValidation/index.ts +1 -1
  80. package/src/utils/settingsValidation/splitFilters.ts +19 -11
  81. package/types/evaluator/index.d.ts +1 -1
  82. package/types/logger/constants.d.ts +4 -2
  83. package/types/sdkClient/identity.d.ts +6 -0
  84. package/types/sdkFactory/types.d.ts +3 -3
  85. package/types/sdkManager/index.d.ts +2 -3
  86. package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
  87. package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
  88. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +1 -1
  89. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +1 -1
  90. package/types/storages/inRedis/EventsCacheInRedis.d.ts +2 -2
  91. package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +3 -2
  92. package/types/storages/inRedis/ImpressionsCacheInRedis.d.ts +2 -2
  93. package/types/storages/inRedis/RedisAdapter.d.ts +1 -1
  94. package/types/storages/inRedis/SegmentsCacheInRedis.d.ts +3 -3
  95. package/types/storages/inRedis/SplitsCacheInRedis.d.ts +10 -14
  96. package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +2 -2
  97. package/types/storages/inRedis/{uniqueKeysCacheInRedis.d.ts → UniqueKeysCacheInRedis.d.ts} +3 -2
  98. package/types/storages/pluggable/SplitsCachePluggable.d.ts +10 -9
  99. package/types/storages/types.d.ts +5 -5
  100. package/types/trackers/impressionObserver/utils.d.ts +1 -1
  101. package/types/types.d.ts +0 -2
  102. package/types/utils/constants/index.d.ts +12 -0
  103. package/types/utils/inputValidation/index.d.ts +2 -2
  104. package/types/utils/inputValidation/sdkKey.d.ts +7 -0
  105. package/types/utils/inputValidation/splitExistence.d.ts +7 -0
  106. package/types/utils/inputValidation/trafficTypeExistence.d.ts +9 -0
  107. package/types/utils/lang/sets.d.ts +1 -0
  108. package/types/utils/settingsValidation/splitFilters.d.ts +3 -2
  109. package/types/myLogger.d.ts +0 -5
  110. package/types/sdkClient/types.d.ts +0 -18
  111. package/types/storages/inMemory/CountsCacheInMemory.d.ts +0 -20
  112. package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +0 -20
  113. package/types/storages/inRedis/CountsCacheInRedis.d.ts +0 -9
  114. package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +0 -9
  115. package/types/storages/metadataBuilder.d.ts +0 -3
  116. package/types/sync/offline/LocalhostFromFile.d.ts +0 -2
  117. package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +0 -2
  118. package/types/sync/offline/updaters/splitChangesUpdater.d.ts +0 -0
  119. package/types/sync/submitters/eventsSyncTask.d.ts +0 -8
  120. package/types/sync/submitters/impressionCountsSubmitterInRedis.d.ts +0 -5
  121. package/types/sync/submitters/impressionCountsSyncTask.d.ts +0 -13
  122. package/types/sync/submitters/impressionsSyncTask.d.ts +0 -14
  123. package/types/sync/submitters/metricsSyncTask.d.ts +0 -12
  124. package/types/sync/submitters/submitterSyncTask.d.ts +0 -10
  125. package/types/sync/submitters/uniqueKeysSubmitterInRedis.d.ts +0 -5
  126. package/types/sync/syncTaskComposite.d.ts +0 -5
  127. package/types/trackers/filter/bloomFilter.d.ts +0 -10
  128. package/types/trackers/filter/dictionaryFilter.d.ts +0 -8
  129. package/types/trackers/filter/types.d.ts +0 -5
  130. package/types/utils/timeTracker/index.d.ts +0 -70
  131. /package/types/storages/inMemory/{uniqueKeysCacheInMemory.d.ts → UniqueKeysCacheInMemory.d.ts} +0 -0
  132. /package/types/storages/inMemory/{uniqueKeysCacheInMemoryCS.d.ts → UniqueKeysCacheInMemoryCS.d.ts} +0 -0
@@ -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 { validateSplitExistance } from '../utils/inputValidation/splitExistance';
5
- import { validateTrafficTypeExistance } from '../utils/inputValidation/trafficTypeExistance';
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, "getTreatment" + (withConfig ? 'withConfig' : ''), queue);
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, "getTreatments" + (withConfig ? 'withConfig' : ''), queue);
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, "getTreatmentsByFlagSets" + (withConfig ? 'WithConfig' : ''), queue);
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 (validateSplitExistance(log, readinessManager, featureFlagName, label, invokingMethodName)) {
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
- validateTrafficTypeExistance(log, readinessManager, storage.splits, mode, trafficTypeName, 'track');
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 { flagSetsAreValid } from '../utils/settingsValidation/splitFilters';
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, 'getTreatments');
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 = flagSetsAreValid(log, methodName, maybeFlagSetNameOrNames, settings.sync.__splitFiltersValidation.groupedFilters.bySet);
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, 'getTreatment');
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, 'getTreatmentWithConfig');
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, 'getTreatments');
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, 'getTreatmentsWithConfig');
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, 'getTreatmentsByFlagSets', maybeFlagSets);
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, 'getTreatmentsWithConfigByFlagSets', maybeFlagSets);
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, 'getTreatmentsByFlagSet', [maybeFlagSet]);
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, 'getTreatmentsWithConfigByFlagSet', [maybeFlagSet]);
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, 'track');
123
- var tt = validateTrafficType(log, maybeTT, 'track');
124
- var event = validateEvent(log, maybeEvent, 'track');
125
- var eventValue = validateEventValue(log, maybeEventValue, 'track');
126
- var _a = validateEventProperties(log, maybeProperties, 'track'), properties = _a.properties, size = _a.size;
127
- var isNotDestroyed = validateIfNotDestroyed(log, readinessManager, 'track');
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
  }
@@ -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(log, storage.splits, sdkReadinessManager);
66
+ var managerInstance = sdkManagerFactory(settings, storage.splits, sdkReadinessManager);
67
67
  syncManager && syncManager.start();
68
68
  signalListener && signalListener.start();
69
69
  log.info(NEW_FACTORY);
@@ -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, validateSplitExistance, validateIfNotDestroyed, validateIfOperational } from '../utils/inputValidation';
5
- var SPLIT_FN_LABEL = 'split';
6
- var SPLITS_FN_LABEL = 'splits';
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(log, splits, _a) {
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
- validateSplitExistance(log, readinessManager, splitName, result, SPLIT_FN_LABEL);
58
+ validateSplitExistence(log, readinessManager, splitName, result, SPLIT_FN_LABEL);
58
59
  return objectToView(result);
59
60
  });
60
61
  }
61
- validateSplitExistance(log, readinessManager, splitName, split, SPLIT_FN_LABEL);
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) ?
@@ -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, returnSetsUnion, setToArray } from '../../utils/lang/sets';
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
- var toReturn = new _Set([]);
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
- if (flagSetFromLocalStorage) {
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
- if (!flagSetFromLocalStorage)
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, returnSetsUnion } from '../../utils/lang/sets';
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
- var toReturn = new _Set([]);
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', 'pipeline', 'expire', 'mget', 'lrange', 'ltrim', 'hset'];
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
- METHODS_TO_PROMISE_WRAP.forEach(function (method) {
59
- var originalMethod = instance[method];
60
- instance[method] = function () {
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 + ("Executing " + method + "."));
64
- // Return original method
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 + (method + " operation threw an error or exceeded configured timeout of " + instance._options.operationTimeout + "ms. Message: " + err));
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 (res, rej) {
87
+ return new Promise(function (resolve, reject) {
85
88
  instance._notReadyCommandsQueue.unshift({
86
- resolve: res,
87
- reject: rej,
89
+ resolve: resolve,
90
+ reject: reject,
88
91
  command: commandWrapper,
89
- name: method.toUpperCase()
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 deferedDisconnect() {
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/review. It is not being used.
54
+ // @TODO remove or implement. It is not being used.
55
55
  SegmentsCacheInRedis.prototype.clear = function () {
56
- return this.redis.flushdb().then(function (status) { return status === 'OK'; });
56
+ return Promise.resolve();
57
57
  };
58
58
  return SegmentsCacheInRedis;
59
59
  }());
@@ -1,7 +1,8 @@
1
- import { __extends } from "tslib";
1
+ import { __extends, __spreadArray } from "tslib";
2
2
  import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
3
3
  import { LOG_PREFIX } from './constants';
4
4
  import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
5
+ import { _Set, returnDifference } from '../../utils/lang/sets';
5
6
  /**
6
7
  * Discard errors for an answer of multiple operations.
7
8
  */
@@ -18,11 +19,12 @@ function processPipelineAnswer(results) {
18
19
  */
19
20
  var SplitsCacheInRedis = /** @class */ (function (_super) {
20
21
  __extends(SplitsCacheInRedis, _super);
21
- function SplitsCacheInRedis(log, keys, redis) {
22
+ function SplitsCacheInRedis(log, keys, redis, splitFiltersValidation) {
22
23
  var _this = _super.call(this) || this;
23
24
  _this.log = log;
24
25
  _this.redis = redis;
25
26
  _this.keys = keys;
27
+ _this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
26
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.
27
29
  // But it is done just to avoid getting the ioredis message `Unhandled error event`.
28
30
  _this.redis.on('error', function (e) {
@@ -45,6 +47,18 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
45
47
  var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
46
48
  return this.redis.incr(ttKey);
47
49
  };
50
+ SplitsCacheInRedis.prototype._updateFlagSets = function (featureFlagName, flagSetsOfRemovedFlag, flagSetsOfAddedFlag) {
51
+ var _this = 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
+ });
58
+ }
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
+ };
48
62
  /**
49
63
  * Add a given split.
50
64
  * The returned promise is resolved when the operation success
@@ -54,16 +68,16 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
54
68
  var _this = this;
55
69
  var splitKey = this.keys.buildSplitKey(name);
56
70
  return this.redis.get(splitKey).then(function (splitFromStorage) {
57
- // handling parsing errors
58
- var parsedPreviousSplit, newStringifiedSplit;
71
+ // handling parsing error
72
+ var parsedPreviousSplit, stringifiedNewSplit;
59
73
  try {
60
74
  parsedPreviousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : undefined;
61
- newStringifiedSplit = JSON.stringify(split);
75
+ stringifiedNewSplit = JSON.stringify(split);
62
76
  }
63
77
  catch (e) {
64
78
  throw new Error('Error parsing feature flag definition: ' + e);
65
79
  }
66
- return _this.redis.set(splitKey, newStringifiedSplit).then(function () {
80
+ return _this.redis.set(splitKey, stringifiedNewSplit).then(function () {
67
81
  // avoid unnecessary increment/decrement operations
68
82
  if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName)
69
83
  return;
@@ -72,7 +86,7 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
72
86
  if (parsedPreviousSplit)
73
87
  return _this._decrementCounts(parsedPreviousSplit);
74
88
  });
75
- });
89
+ }).then(function () { return _this._updateFlagSets(name, parsedPreviousSplit && parsedPreviousSplit.sets, split.sets); });
76
90
  }).then(function () { return true; });
77
91
  };
78
92
  /**
@@ -93,8 +107,9 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
93
107
  var _this = this;
94
108
  return this.getSplit(name).then(function (split) {
95
109
  if (split) {
96
- _this._decrementCounts(split);
110
+ return _this._decrementCounts(split).then(function () { return _this._updateFlagSets(name, split.sets); });
97
111
  }
112
+ }).then(function () {
98
113
  return _this.redis.del(_this.keys.buildSplitKey(name));
99
114
  });
100
115
  };
@@ -169,14 +184,20 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
169
184
  return this.redis.keys(this.keys.searchPatternForSplitKeys()).then(function (listOfKeys) { return listOfKeys.map(_this.keys.extractKey); });
170
185
  };
171
186
  /**
172
- * Get list of split names related to a given flag set names list.
173
- * The returned promise is resolved with the list of split names,
174
- * or rejected if wrapper operation fails.
175
- * @todo this is a no-op method to be implemented
187
+ * Get list of feature flag names related to a given list of flag set names.
188
+ * The returned promise is resolved with the list of feature flag names per flag set,
189
+ * or rejected if the pipelined redis operation fails (e.g., timeout).
176
190
  */
177
- SplitsCacheInRedis.prototype.getNamesByFlagSets = function () {
178
- this.log.error(LOG_PREFIX + 'ByFlagSet/s evaluations are not supported with Redis storage yet.');
179
- return Promise.reject();
191
+ SplitsCacheInRedis.prototype.getNamesByFlagSets = function (flagSets) {
192
+ var _this = this;
193
+ return this.redis.pipeline(flagSets.map(function (flagSet) { return ['smembers', _this.keys.buildFlagSetKey(flagSet)]; })).exec()
194
+ .then(function (results) { return results.map(function (_a, index) {
195
+ var e = _a[0], value = _a[1];
196
+ if (e === null)
197
+ return value;
198
+ _this.log.error(LOG_PREFIX + ("Could not read result from get members of flag set " + flagSets[index] + " due to an error: " + e));
199
+ }); })
200
+ .then(function (namesByFlagSets) { return namesByFlagSets.map(function (namesByFlagSet) { return new _Set(namesByFlagSet); }); });
180
201
  };
181
202
  /**
182
203
  * Check traffic type existence.
@@ -193,24 +214,20 @@ var SplitsCacheInRedis = /** @class */ (function (_super) {
193
214
  return false; // if entry doesn't exist, means that TT doesn't exist
194
215
  ttCount = parseInt(ttCount, 10);
195
216
  if (!isFiniteNumber(ttCount) || ttCount < 0) {
196
- _this.log.info(LOG_PREFIX + ("Could not validate traffic type existance of " + trafficType + " due to data corruption of some sorts."));
217
+ _this.log.info(LOG_PREFIX + ("Could not validate traffic type existence of " + trafficType + " due to data corruption of some sorts."));
197
218
  return false;
198
219
  }
199
220
  return ttCount > 0;
200
221
  })
201
222
  .catch(function (e) {
202
- _this.log.error(LOG_PREFIX + ("Could not validate traffic type existance of " + trafficType + " due to an error: " + e + "."));
223
+ _this.log.error(LOG_PREFIX + ("Could not validate traffic type existence of " + trafficType + " due to an error: " + e + "."));
203
224
  // If there is an error, bypass the validation so the event can get tracked.
204
225
  return true;
205
226
  });
206
227
  };
207
- /**
208
- * Delete everything in the current database.
209
- *
210
- * @NOTE documentation says it never fails.
211
- */
228
+ // @TODO remove or implement. It is not being used.
212
229
  SplitsCacheInRedis.prototype.clear = function () {
213
- return this.redis.flushdb().then(function (status) { return status === 'OK'; });
230
+ return Promise.resolve();
214
231
  };
215
232
  /**
216
233
  * Fetches multiple splits definitions.