@splitsoftware/splitio-commons 3.1.1-rc.10 → 3.1.1-rc.11

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 (208) hide show
  1. package/CHANGES.txt +2 -0
  2. package/cjs/evaluator/condition/index.js +2 -2
  3. package/cjs/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +5 -8
  4. package/cjs/evaluator/index.js +81 -71
  5. package/cjs/listeners/browser.js +2 -1
  6. package/cjs/listeners/node.js +4 -4
  7. package/cjs/logger/constants.js +15 -20
  8. package/cjs/logger/messages/debug.js +5 -6
  9. package/cjs/logger/messages/error.js +3 -3
  10. package/cjs/logger/messages/info.js +3 -4
  11. package/cjs/logger/messages/warn.js +6 -7
  12. package/cjs/platform/browser.js +15 -0
  13. package/cjs/platform/getEventSource/browser.js +8 -0
  14. package/cjs/platform/getEventSource/eventsource.js +480 -0
  15. package/cjs/platform/getEventSource/node.js +26 -0
  16. package/cjs/platform/getFetch/browser.js +9 -0
  17. package/cjs/platform/getFetch/node.js +27 -0
  18. package/cjs/platform/getOptions/node.js +25 -0
  19. package/cjs/platform/node.js +17 -0
  20. package/cjs/presets/serverSide.js +2 -2
  21. package/cjs/readiness/constants.js +5 -4
  22. package/cjs/readiness/readinessManager.js +23 -23
  23. package/cjs/readiness/sdkReadinessManager.js +1 -17
  24. package/cjs/sdkClient/client.js +24 -50
  25. package/cjs/sdkClient/clientInputValidation.js +6 -17
  26. package/cjs/sdkClient/sdkClient.js +3 -60
  27. package/cjs/sdkClient/sdkLifecycle.js +74 -0
  28. package/cjs/sdkClient/trackMethod.js +56 -0
  29. package/cjs/sdkFactory/index.js +11 -15
  30. package/cjs/sdkManager/index.js +5 -5
  31. package/cjs/services/authProvider.js +80 -0
  32. package/cjs/services/decorateHeaders.js +2 -1
  33. package/cjs/services/secureSplitHttpClient.js +36 -0
  34. package/cjs/services/serviceApi.js +147 -0
  35. package/cjs/services/splitApi.js +24 -10
  36. package/cjs/services/splitHttpClient.js +3 -5
  37. package/cjs/storages/AbstractDefinitionsCacheAsync.js +51 -0
  38. package/cjs/storages/AbstractDefinitionsCacheSync.js +76 -0
  39. package/cjs/storages/KeyBuilder.js +6 -6
  40. package/cjs/storages/KeyBuilderCS.js +5 -5
  41. package/cjs/storages/KeyBuilderSS.js +2 -2
  42. package/cjs/storages/getRolloutPlan.js +3 -3
  43. package/cjs/storages/inLocalStorage/DefinitionsCacheInLocal.js +194 -0
  44. package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +1 -2
  45. package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +10 -10
  46. package/cjs/storages/inLocalStorage/index.js +6 -6
  47. package/cjs/storages/inLocalStorage/validateCache.js +3 -3
  48. package/cjs/storages/inMemory/DefinitionsCacheInMemory.js +121 -0
  49. package/cjs/storages/inMemory/InMemoryStorage.js +4 -4
  50. package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -5
  51. package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +5 -5
  52. package/cjs/storages/inMemory/SegmentsCacheInMemory.js +1 -1
  53. package/cjs/storages/inMemory/TelemetryCacheInMemory.js +5 -5
  54. package/cjs/storages/inRedis/{SplitsCacheInRedis.js → DefinitionsCacheInRedis.js} +77 -77
  55. package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
  56. package/cjs/storages/inRedis/index.js +2 -2
  57. package/cjs/storages/pluggable/DefinitionsCachePluggable.js +212 -0
  58. package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
  59. package/cjs/storages/pluggable/index.js +2 -2
  60. package/cjs/storages/setRolloutPlan.js +4 -4
  61. package/cjs/storages/utils.js +1 -0
  62. package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +5 -5
  63. package/cjs/sync/polling/fetchers/splitChangesFetcher.js +24 -15
  64. package/cjs/sync/polling/pollingManagerCS.js +86 -81
  65. package/cjs/sync/polling/pollingManagerSS.js +44 -36
  66. package/cjs/sync/polling/syncTasks/definitionsSyncTask.js +13 -0
  67. package/cjs/sync/polling/syncTasks/segmentsSyncTask.js +2 -3
  68. package/cjs/sync/polling/updaters/{splitChangesUpdater.js → definitionChangesUpdater.js} +66 -69
  69. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +3 -3
  70. package/cjs/sync/polling/updaters/segmentChangesUpdater.js +6 -6
  71. package/cjs/sync/streaming/AuthClient/index.js +13 -14
  72. package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +1 -1
  73. package/cjs/sync/streaming/SSEHandler/index.js +2 -1
  74. package/cjs/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.js → DefinitionsUpdateWorker.js} +16 -19
  75. package/cjs/sync/streaming/constants.js +4 -3
  76. package/cjs/sync/streaming/parseUtils.js +11 -11
  77. package/cjs/sync/streaming/pushManager.js +20 -25
  78. package/cjs/sync/submitters/eventsSubmitter.js +1 -1
  79. package/cjs/sync/submitters/impressionCountsSubmitter.js +1 -1
  80. package/cjs/sync/submitters/impressionsSubmitter.js +5 -4
  81. package/cjs/sync/submitters/telemetrySubmitter.js +3 -4
  82. package/cjs/sync/submitters/uniqueKeysSubmitter.js +1 -1
  83. package/cjs/sync/syncManagerOnline.js +5 -5
  84. package/cjs/utils/Backoff.js +35 -3
  85. package/cjs/utils/EventEmitter.js +391 -0
  86. package/cjs/utils/filter/bloomFilter.js +37 -0
  87. package/cjs/utils/inputValidation/{split.js → definition.js} +10 -10
  88. package/cjs/utils/inputValidation/{splitExistence.js → definitionExistence.js} +6 -6
  89. package/cjs/utils/inputValidation/definitions.js +25 -0
  90. package/cjs/utils/inputValidation/index.js +7 -7
  91. package/cjs/utils/inputValidation/isOperational.js +4 -4
  92. package/cjs/utils/inputValidation/target.js +22 -0
  93. package/cjs/utils/labels/index.js +3 -3
  94. package/cjs/utils/settingsValidation/index.js +2 -0
  95. package/cjs/utils/settingsValidation/splitFilters.js +3 -3
  96. package/cjs/utils/settingsValidation/url.js +6 -2
  97. package/esm/evaluator/condition/index.js +2 -2
  98. package/esm/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +5 -8
  99. package/esm/evaluator/index.js +80 -71
  100. package/esm/listeners/browser.js +2 -1
  101. package/esm/listeners/node.js +4 -4
  102. package/esm/logger/constants.js +12 -17
  103. package/esm/logger/messages/debug.js +5 -6
  104. package/esm/logger/messages/error.js +3 -3
  105. package/esm/logger/messages/info.js +3 -4
  106. package/esm/logger/messages/warn.js +6 -7
  107. package/esm/platform/browser.js +12 -0
  108. package/esm/platform/getEventSource/browser.js +4 -0
  109. package/esm/platform/getEventSource/eventsource.js +480 -0
  110. package/esm/platform/getEventSource/node.js +20 -0
  111. package/esm/platform/getFetch/browser.js +5 -0
  112. package/esm/platform/getFetch/node.js +22 -0
  113. package/esm/platform/getOptions/node.js +20 -0
  114. package/esm/platform/node.js +14 -0
  115. package/esm/presets/serverSide.js +2 -2
  116. package/esm/readiness/constants.js +4 -3
  117. package/esm/readiness/readinessManager.js +24 -24
  118. package/esm/readiness/sdkReadinessManager.js +2 -18
  119. package/esm/sdkClient/client.js +23 -50
  120. package/esm/sdkClient/clientInputValidation.js +8 -19
  121. package/esm/sdkClient/sdkClient.js +3 -60
  122. package/esm/sdkClient/sdkLifecycle.js +70 -0
  123. package/esm/sdkClient/trackMethod.js +52 -0
  124. package/esm/sdkFactory/index.js +12 -16
  125. package/esm/sdkManager/index.js +6 -6
  126. package/esm/services/authProvider.js +76 -0
  127. package/esm/services/decorateHeaders.js +2 -1
  128. package/esm/services/secureSplitHttpClient.js +32 -0
  129. package/esm/services/serviceApi.js +143 -0
  130. package/esm/services/splitApi.js +24 -10
  131. package/esm/services/splitHttpClient.js +3 -5
  132. package/esm/storages/AbstractDefinitionsCacheAsync.js +48 -0
  133. package/esm/storages/AbstractDefinitionsCacheSync.js +71 -0
  134. package/esm/storages/KeyBuilder.js +6 -6
  135. package/esm/storages/KeyBuilderCS.js +5 -5
  136. package/esm/storages/KeyBuilderSS.js +2 -2
  137. package/esm/storages/getRolloutPlan.js +3 -3
  138. package/esm/storages/inLocalStorage/DefinitionsCacheInLocal.js +191 -0
  139. package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +1 -2
  140. package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +7 -7
  141. package/esm/storages/inLocalStorage/index.js +6 -6
  142. package/esm/storages/inLocalStorage/validateCache.js +3 -3
  143. package/esm/storages/inMemory/DefinitionsCacheInMemory.js +118 -0
  144. package/esm/storages/inMemory/InMemoryStorage.js +4 -4
  145. package/esm/storages/inMemory/InMemoryStorageCS.js +5 -5
  146. package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +2 -2
  147. package/esm/storages/inMemory/SegmentsCacheInMemory.js +1 -1
  148. package/esm/storages/inMemory/TelemetryCacheInMemory.js +5 -5
  149. package/esm/storages/inRedis/{SplitsCacheInRedis.js → DefinitionsCacheInRedis.js} +76 -76
  150. package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
  151. package/esm/storages/inRedis/index.js +2 -2
  152. package/esm/storages/pluggable/DefinitionsCachePluggable.js +209 -0
  153. package/esm/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
  154. package/esm/storages/pluggable/index.js +2 -2
  155. package/esm/storages/setRolloutPlan.js +4 -4
  156. package/esm/storages/utils.js +1 -0
  157. package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +6 -6
  158. package/esm/sync/polling/fetchers/splitChangesFetcher.js +25 -16
  159. package/esm/sync/polling/pollingManagerCS.js +87 -82
  160. package/esm/sync/polling/pollingManagerSS.js +44 -36
  161. package/esm/sync/polling/syncTasks/definitionsSyncTask.js +9 -0
  162. package/esm/sync/polling/syncTasks/segmentsSyncTask.js +2 -3
  163. package/esm/sync/polling/updaters/definitionChangesUpdater.js +191 -0
  164. package/esm/sync/polling/updaters/mySegmentsUpdater.js +3 -3
  165. package/esm/sync/polling/updaters/segmentChangesUpdater.js +7 -7
  166. package/esm/sync/streaming/AuthClient/index.js +11 -11
  167. package/esm/sync/streaming/SSEHandler/NotificationKeeper.js +2 -2
  168. package/esm/sync/streaming/SSEHandler/index.js +3 -2
  169. package/esm/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.js → DefinitionsUpdateWorker.js} +15 -18
  170. package/esm/sync/streaming/constants.js +3 -2
  171. package/esm/sync/streaming/parseUtils.js +9 -9
  172. package/esm/sync/streaming/pushManager.js +22 -27
  173. package/esm/sync/submitters/eventsSubmitter.js +1 -1
  174. package/esm/sync/submitters/impressionCountsSubmitter.js +1 -1
  175. package/esm/sync/submitters/impressionsSubmitter.js +5 -4
  176. package/esm/sync/submitters/telemetrySubmitter.js +3 -4
  177. package/esm/sync/submitters/uniqueKeysSubmitter.js +1 -1
  178. package/esm/sync/syncManagerOnline.js +4 -4
  179. package/esm/utils/Backoff.js +35 -3
  180. package/esm/utils/EventEmitter.js +387 -0
  181. package/esm/utils/filter/bloomFilter.js +33 -0
  182. package/esm/utils/inputValidation/{split.js → definition.js} +8 -8
  183. package/esm/utils/inputValidation/definitionExistence.js +15 -0
  184. package/esm/utils/inputValidation/definitions.js +21 -0
  185. package/esm/utils/inputValidation/index.js +3 -3
  186. package/esm/utils/inputValidation/isOperational.js +4 -4
  187. package/esm/utils/inputValidation/target.js +18 -0
  188. package/esm/utils/labels/index.js +2 -2
  189. package/esm/utils/settingsValidation/index.js +2 -0
  190. package/esm/utils/settingsValidation/splitFilters.js +3 -3
  191. package/esm/utils/settingsValidation/url.js +6 -2
  192. package/package.json +1 -1
  193. package/cjs/storages/AbstractSplitsCacheAsync.js +0 -51
  194. package/cjs/storages/AbstractSplitsCacheSync.js +0 -76
  195. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +0 -194
  196. package/cjs/storages/inMemory/SplitsCacheInMemory.js +0 -121
  197. package/cjs/storages/pluggable/SplitsCachePluggable.js +0 -212
  198. package/cjs/sync/polling/syncTasks/splitsSyncTask.js +0 -13
  199. package/cjs/utils/inputValidation/splits.js +0 -25
  200. package/esm/storages/AbstractSplitsCacheAsync.js +0 -48
  201. package/esm/storages/AbstractSplitsCacheSync.js +0 -71
  202. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +0 -191
  203. package/esm/storages/inMemory/SplitsCacheInMemory.js +0 -118
  204. package/esm/storages/pluggable/SplitsCachePluggable.js +0 -209
  205. package/esm/sync/polling/syncTasks/splitsSyncTask.js +0 -9
  206. package/esm/sync/polling/updaters/splitChangesUpdater.js +0 -194
  207. package/esm/utils/inputValidation/splitExistence.js +0 -15
  208. package/esm/utils/inputValidation/splits.js +0 -21
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateSplits = void 0;
4
- var constants_1 = require("../../logger/constants");
5
- var lang_1 = require("../lang");
6
- var split_1 = require("./split");
7
- function validateSplits(log, maybeSplits, method, listName, item) {
8
- if (listName === void 0) { listName = 'feature flag names'; }
9
- if (item === void 0) { item = 'feature flag name'; }
10
- if (Array.isArray(maybeSplits) && maybeSplits.length > 0) {
11
- var validatedArray_1 = [];
12
- // Remove invalid values
13
- maybeSplits.forEach(function (maybeSplit) {
14
- var splitName = (0, split_1.validateSplit)(log, maybeSplit, method, item);
15
- if (splitName)
16
- validatedArray_1.push(splitName);
17
- });
18
- // Strip off duplicated values if we have valid split names then return
19
- if (validatedArray_1.length)
20
- return (0, lang_1.uniq)(validatedArray_1);
21
- }
22
- log.error(constants_1.ERROR_EMPTY_ARRAY, [method, listName]);
23
- return false;
24
- }
25
- exports.validateSplits = validateSplits;
@@ -1,48 +0,0 @@
1
- import { objectAssign } from '../utils/lang/objectAssign';
2
- /**
3
- * This class provides a skeletal implementation of the ISplitsCacheAsync interface
4
- * to minimize the effort required to implement this interface.
5
- */
6
- var AbstractSplitsCacheAsync = /** @class */ (function () {
7
- function AbstractSplitsCacheAsync() {
8
- }
9
- AbstractSplitsCacheAsync.prototype.update = function (toAdd, toRemove, changeNumber) {
10
- var _this = this;
11
- return Promise.all([
12
- this.setChangeNumber(changeNumber),
13
- Promise.all(toAdd.map(function (addedFF) { return _this.addSplit(addedFF); })),
14
- Promise.all(toRemove.map(function (removedFF) { return _this.removeSplit(removedFF.name); }))
15
- ]).then(function (_a) {
16
- var added = _a[1], removed = _a[2];
17
- return added.some(function (result) { return result; }) || removed.some(function (result) { return result; });
18
- });
19
- };
20
- // @TODO revisit segment-related methods ('usesSegments', 'getRegisteredSegments', 'registerSegments')
21
- // noop, just keeping the interface. This is used by standalone client-side API only, and so only implemented by InMemory and InLocalStorage.
22
- AbstractSplitsCacheAsync.prototype.usesSegments = function () {
23
- return Promise.resolve(true);
24
- };
25
- /**
26
- * Kill `name` split and set `defaultTreatment` and `changeNumber`.
27
- * Used for SPLIT_KILL push notifications.
28
- *
29
- * @returns a promise that is resolved once the split kill operation is performed. The fulfillment value is a boolean: `true` if the operation successed updating the split or `false` if no split is updated,
30
- * for instance, if the `changeNumber` is old, or if the split is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
31
- * The promise will never be rejected.
32
- */
33
- AbstractSplitsCacheAsync.prototype.killLocally = function (name, defaultTreatment, changeNumber) {
34
- var _this = this;
35
- return this.getSplit(name).then(function (split) {
36
- if (split && (!split.changeNumber || split.changeNumber < changeNumber)) {
37
- var newSplit = objectAssign({}, split);
38
- newSplit.killed = true;
39
- newSplit.defaultTreatment = defaultTreatment;
40
- newSplit.changeNumber = changeNumber;
41
- return _this.addSplit(newSplit);
42
- }
43
- return false;
44
- }).catch(function () { return false; });
45
- };
46
- return AbstractSplitsCacheAsync;
47
- }());
48
- export { AbstractSplitsCacheAsync };
@@ -1,71 +0,0 @@
1
- import { objectAssign } from '../utils/lang/objectAssign';
2
- import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
3
- /**
4
- * This class provides a skeletal implementation of the ISplitsCacheSync interface
5
- * to minimize the effort required to implement this interface.
6
- */
7
- var AbstractSplitsCacheSync = /** @class */ (function () {
8
- function AbstractSplitsCacheSync() {
9
- }
10
- AbstractSplitsCacheSync.prototype.update = function (toAdd, toRemove, changeNumber) {
11
- var _this = this;
12
- var updated = toAdd.map(function (addedFF) { return _this.addSplit(addedFF); }).some(function (result) { return result; });
13
- updated = toRemove.map(function (removedFF) { return _this.removeSplit(removedFF.name); }).some(function (result) { return result; }) || updated;
14
- this.setChangeNumber(changeNumber);
15
- return updated;
16
- };
17
- AbstractSplitsCacheSync.prototype.getSplits = function (names) {
18
- var _this = this;
19
- var splits = {};
20
- names.forEach(function (name) {
21
- splits[name] = _this.getSplit(name);
22
- });
23
- return splits;
24
- };
25
- AbstractSplitsCacheSync.prototype.getAll = function () {
26
- var _this = this;
27
- return this.getSplitNames().map(function (key) { return _this.getSplit(key); });
28
- };
29
- /**
30
- * Kill `name` split and set `defaultTreatment` and `changeNumber`.
31
- * Used for SPLIT_KILL push notifications.
32
- *
33
- * @returns `true` if the operation successed updating the split, or `false` if no split is updated,
34
- * for instance, if the `changeNumber` is old, or if the split is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
35
- */
36
- AbstractSplitsCacheSync.prototype.killLocally = function (name, defaultTreatment, changeNumber) {
37
- var split = this.getSplit(name);
38
- if (split && (!split.changeNumber || split.changeNumber < changeNumber)) {
39
- var newSplit = objectAssign({}, split);
40
- newSplit.killed = true;
41
- newSplit.defaultTreatment = defaultTreatment;
42
- newSplit.changeNumber = changeNumber;
43
- return this.addSplit(newSplit);
44
- }
45
- return false;
46
- };
47
- return AbstractSplitsCacheSync;
48
- }());
49
- export { AbstractSplitsCacheSync };
50
- /**
51
- * Given a parsed split, it returns a boolean flagging if its conditions use segments matchers (rules & whitelists).
52
- * This util is intended to simplify the implementation of `splitsCache::usesSegments` method
53
- */
54
- export function usesSegments(ruleEntity) {
55
- var conditions = ruleEntity.conditions || [];
56
- for (var i = 0; i < conditions.length; i++) {
57
- var matchers = conditions[i].matcherGroup.matchers;
58
- for (var j = 0; j < matchers.length; j++) {
59
- var matcher = matchers[j].matcherType;
60
- if (matcher === IN_SEGMENT || matcher === IN_LARGE_SEGMENT)
61
- return true;
62
- }
63
- }
64
- var excluded = ruleEntity.excluded;
65
- if (excluded && excluded.segments && excluded.segments.length > 0)
66
- return true;
67
- return false;
68
- }
69
- export function usesSegmentsSync(storage) {
70
- return storage.splits.usesSegments() || storage.rbSegments.usesSegments();
71
- }
@@ -1,191 +0,0 @@
1
- import { __extends } from "tslib";
2
- import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
3
- import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
4
- import { LOG_PREFIX } from './constants';
5
- import { setToArray } from '../../utils/lang/sets';
6
- var SplitsCacheInLocal = /** @class */ (function (_super) {
7
- __extends(SplitsCacheInLocal, _super);
8
- function SplitsCacheInLocal(settings, keys, storage) {
9
- var _this = _super.call(this) || this;
10
- _this.keys = keys;
11
- _this.log = settings.log;
12
- _this.flagSetsFilter = settings.sync.__splitFiltersValidation.groupedFilters.bySet;
13
- _this.storage = storage;
14
- return _this;
15
- }
16
- SplitsCacheInLocal.prototype._decrementCount = function (key) {
17
- var count = toNumber(this.storage.getItem(key)) - 1;
18
- if (count > 0)
19
- this.storage.setItem(key, count + '');
20
- else
21
- this.storage.removeItem(key);
22
- };
23
- SplitsCacheInLocal.prototype._decrementCounts = function (split) {
24
- try {
25
- var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
26
- this._decrementCount(ttKey);
27
- if (usesSegments(split)) {
28
- var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
29
- this._decrementCount(segmentsCountKey);
30
- }
31
- }
32
- catch (e) {
33
- this.log.error(LOG_PREFIX + e);
34
- }
35
- };
36
- SplitsCacheInLocal.prototype._incrementCounts = function (split) {
37
- try {
38
- var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
39
- this.storage.setItem(ttKey, (toNumber(this.storage.getItem(ttKey)) + 1) + '');
40
- if (usesSegments(split)) {
41
- var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
42
- this.storage.setItem(segmentsCountKey, (toNumber(this.storage.getItem(segmentsCountKey)) + 1) + '');
43
- }
44
- }
45
- catch (e) {
46
- this.log.error(LOG_PREFIX + e);
47
- }
48
- };
49
- /**
50
- * Removes all splits cache related data from localStorage (splits, counters, changeNumber and lastUpdated).
51
- * We cannot simply call `localStorage.clear()` since that implies removing user items from the storage.
52
- */
53
- SplitsCacheInLocal.prototype.clear = function () {
54
- var _this = this;
55
- // collect item keys
56
- var len = this.storage.length;
57
- var accum = [];
58
- for (var cur = 0; cur < len; cur++) {
59
- var key = this.storage.key(cur);
60
- if (key != null && this.keys.isSplitsCacheKey(key))
61
- accum.push(key);
62
- }
63
- // remove items
64
- accum.forEach(function (key) {
65
- _this.storage.removeItem(key);
66
- });
67
- this.hasSync = false;
68
- };
69
- SplitsCacheInLocal.prototype.addSplit = function (split) {
70
- var name = split.name;
71
- var splitKey = this.keys.buildSplitKey(name);
72
- var splitFromStorage = this.storage.getItem(splitKey);
73
- var previousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : null;
74
- if (previousSplit) {
75
- this._decrementCounts(previousSplit);
76
- this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
77
- }
78
- this.storage.setItem(splitKey, JSON.stringify(split));
79
- this._incrementCounts(split);
80
- this.addToFlagSets(split);
81
- return true;
82
- };
83
- SplitsCacheInLocal.prototype.removeSplit = function (name) {
84
- var split = this.getSplit(name);
85
- if (!split)
86
- return false;
87
- this.storage.removeItem(this.keys.buildSplitKey(name));
88
- this._decrementCounts(split);
89
- this.removeFromFlagSets(split.name, split.sets);
90
- return true;
91
- };
92
- SplitsCacheInLocal.prototype.getSplit = function (name) {
93
- var item = this.storage.getItem(this.keys.buildSplitKey(name));
94
- return item && JSON.parse(item);
95
- };
96
- SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
97
- try {
98
- this.storage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
99
- // update "last updated" timestamp with current time
100
- this.storage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
101
- this.hasSync = true;
102
- return true;
103
- }
104
- catch (e) {
105
- this.log.error(LOG_PREFIX + e);
106
- return false;
107
- }
108
- };
109
- SplitsCacheInLocal.prototype.getChangeNumber = function () {
110
- var n = -1;
111
- var value = this.storage.getItem(this.keys.buildSplitsTillKey());
112
- if (value !== null) {
113
- value = parseInt(value, 10);
114
- return isNaNNumber(value) ? n : value;
115
- }
116
- return n;
117
- };
118
- SplitsCacheInLocal.prototype.getSplitNames = function () {
119
- var len = this.storage.length;
120
- var accum = [];
121
- var cur = 0;
122
- while (cur < len) {
123
- var key = this.storage.key(cur);
124
- if (key != null && this.keys.isSplitKey(key))
125
- accum.push(this.keys.extractKey(key));
126
- cur++;
127
- }
128
- return accum;
129
- };
130
- SplitsCacheInLocal.prototype.trafficTypeExists = function (trafficType) {
131
- var ttCount = toNumber(this.storage.getItem(this.keys.buildTrafficTypeKey(trafficType)));
132
- return isFiniteNumber(ttCount) && ttCount > 0;
133
- };
134
- SplitsCacheInLocal.prototype.usesSegments = function () {
135
- // If cache hasn't been synchronized with the cloud, assume we need them.
136
- if (!this.hasSync)
137
- return true;
138
- var storedCount = this.storage.getItem(this.keys.buildSplitsWithSegmentCountKey());
139
- var splitsWithSegmentsCount = storedCount === null ? 0 : toNumber(storedCount);
140
- return isFiniteNumber(splitsWithSegmentsCount) ?
141
- splitsWithSegmentsCount > 0 :
142
- true;
143
- };
144
- SplitsCacheInLocal.prototype.getNamesByFlagSets = function (flagSets) {
145
- var _this = this;
146
- return flagSets.map(function (flagSet) {
147
- var flagSetKey = _this.keys.buildFlagSetKey(flagSet);
148
- var flagSetFromStorage = _this.storage.getItem(flagSetKey);
149
- return new Set(flagSetFromStorage ? JSON.parse(flagSetFromStorage) : []);
150
- });
151
- };
152
- SplitsCacheInLocal.prototype.addToFlagSets = function (featureFlag) {
153
- var _this = this;
154
- if (!featureFlag.sets)
155
- return;
156
- featureFlag.sets.forEach(function (featureFlagSet) {
157
- if (_this.flagSetsFilter.length > 0 && !_this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === featureFlagSet; }))
158
- return;
159
- var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
160
- var flagSetFromStorage = _this.storage.getItem(flagSetKey);
161
- var flagSetCache = new Set(flagSetFromStorage ? JSON.parse(flagSetFromStorage) : []);
162
- if (flagSetCache.has(featureFlag.name))
163
- return;
164
- flagSetCache.add(featureFlag.name);
165
- _this.storage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
166
- });
167
- };
168
- SplitsCacheInLocal.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
169
- var _this = this;
170
- if (!flagSets)
171
- return;
172
- flagSets.forEach(function (flagSet) {
173
- _this.removeNames(flagSet, featureFlagName);
174
- });
175
- };
176
- SplitsCacheInLocal.prototype.removeNames = function (flagSetName, featureFlagName) {
177
- var flagSetKey = this.keys.buildFlagSetKey(flagSetName);
178
- var flagSetFromStorage = this.storage.getItem(flagSetKey);
179
- if (!flagSetFromStorage)
180
- return;
181
- var flagSetCache = new Set(JSON.parse(flagSetFromStorage));
182
- flagSetCache.delete(featureFlagName);
183
- if (flagSetCache.size === 0) {
184
- this.storage.removeItem(flagSetKey);
185
- return;
186
- }
187
- this.storage.setItem(flagSetKey, JSON.stringify(setToArray(flagSetCache)));
188
- };
189
- return SplitsCacheInLocal;
190
- }(AbstractSplitsCacheSync));
191
- export { SplitsCacheInLocal };
@@ -1,118 +0,0 @@
1
- import { __extends } from "tslib";
2
- import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
3
- import { isFiniteNumber } from '../../utils/lang';
4
- /**
5
- * Default ISplitsCacheSync implementation that stores split definitions in memory.
6
- */
7
- var SplitsCacheInMemory = /** @class */ (function (_super) {
8
- __extends(SplitsCacheInMemory, _super);
9
- function SplitsCacheInMemory(splitFiltersValidation) {
10
- var _this = _super.call(this) || this;
11
- _this.splitsCache = {};
12
- _this.ttCache = {};
13
- _this.changeNumber = -1;
14
- _this.segmentsCount = 0;
15
- _this.flagSetsCache = {};
16
- _this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
17
- return _this;
18
- }
19
- SplitsCacheInMemory.prototype.clear = function () {
20
- this.splitsCache = {};
21
- this.ttCache = {};
22
- this.changeNumber = -1;
23
- this.segmentsCount = 0;
24
- this.flagSetsCache = {};
25
- };
26
- SplitsCacheInMemory.prototype.addSplit = function (split) {
27
- var name = split.name;
28
- var previousSplit = this.getSplit(name);
29
- if (previousSplit) { // We had this Split already
30
- var previousTtName = previousSplit.trafficTypeName;
31
- this.ttCache[previousTtName]--;
32
- if (!this.ttCache[previousTtName])
33
- delete this.ttCache[previousTtName];
34
- this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
35
- // Subtract from segments count for the previous version of this Split
36
- if (usesSegments(previousSplit))
37
- this.segmentsCount--;
38
- }
39
- // Store the Split.
40
- this.splitsCache[name] = split;
41
- // Update TT cache
42
- var ttName = split.trafficTypeName;
43
- this.ttCache[ttName] = (this.ttCache[ttName] || 0) + 1;
44
- this.addToFlagSets(split);
45
- // Add to segments count for the new version of the Split
46
- if (usesSegments(split))
47
- this.segmentsCount++;
48
- return true;
49
- };
50
- SplitsCacheInMemory.prototype.removeSplit = function (name) {
51
- var split = this.getSplit(name);
52
- if (!split)
53
- return false;
54
- // Delete the Split
55
- delete this.splitsCache[name];
56
- var ttName = split.trafficTypeName;
57
- this.ttCache[ttName]--; // Update tt cache
58
- if (!this.ttCache[ttName])
59
- delete this.ttCache[ttName];
60
- this.removeFromFlagSets(split.name, split.sets);
61
- // Update the segments count.
62
- if (usesSegments(split))
63
- this.segmentsCount--;
64
- return true;
65
- };
66
- SplitsCacheInMemory.prototype.getSplit = function (name) {
67
- return this.splitsCache[name] || null;
68
- };
69
- SplitsCacheInMemory.prototype.setChangeNumber = function (changeNumber) {
70
- this.changeNumber = changeNumber;
71
- return true;
72
- };
73
- SplitsCacheInMemory.prototype.getChangeNumber = function () {
74
- return this.changeNumber;
75
- };
76
- SplitsCacheInMemory.prototype.getSplitNames = function () {
77
- return Object.keys(this.splitsCache);
78
- };
79
- SplitsCacheInMemory.prototype.trafficTypeExists = function (trafficType) {
80
- return isFiniteNumber(this.ttCache[trafficType]) && this.ttCache[trafficType] > 0;
81
- };
82
- SplitsCacheInMemory.prototype.usesSegments = function () {
83
- return this.getChangeNumber() === -1 || this.segmentsCount > 0;
84
- };
85
- SplitsCacheInMemory.prototype.getNamesByFlagSets = function (flagSets) {
86
- var _this = this;
87
- return flagSets.map(function (flagSet) { return _this.flagSetsCache[flagSet] || new Set(); });
88
- };
89
- SplitsCacheInMemory.prototype.addToFlagSets = function (featureFlag) {
90
- var _this = this;
91
- if (!featureFlag.sets)
92
- return;
93
- featureFlag.sets.forEach(function (featureFlagSet) {
94
- if (_this.flagSetsFilter.length > 0 && !_this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === featureFlagSet; }))
95
- return;
96
- if (!_this.flagSetsCache[featureFlagSet])
97
- _this.flagSetsCache[featureFlagSet] = new Set([]);
98
- _this.flagSetsCache[featureFlagSet].add(featureFlag.name);
99
- });
100
- };
101
- SplitsCacheInMemory.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
102
- var _this = this;
103
- if (!flagSets)
104
- return;
105
- flagSets.forEach(function (flagSet) {
106
- _this.removeNames(flagSet, featureFlagName);
107
- });
108
- };
109
- SplitsCacheInMemory.prototype.removeNames = function (flagSetName, featureFlagName) {
110
- if (!this.flagSetsCache[flagSetName])
111
- return;
112
- this.flagSetsCache[flagSetName].delete(featureFlagName);
113
- if (this.flagSetsCache[flagSetName].size === 0)
114
- delete this.flagSetsCache[flagSetName];
115
- };
116
- return SplitsCacheInMemory;
117
- }(AbstractSplitsCacheSync));
118
- export { SplitsCacheInMemory };
@@ -1,209 +0,0 @@
1
- import { __extends, __spreadArray } from "tslib";
2
- import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
3
- import { LOG_PREFIX } from './constants';
4
- import { AbstractSplitsCacheAsync } from '../AbstractSplitsCacheAsync';
5
- import { returnDifference } from '../../utils/lang/sets';
6
- /**
7
- * ISplitsCacheAsync implementation for pluggable storages.
8
- */
9
- var SplitsCachePluggable = /** @class */ (function (_super) {
10
- __extends(SplitsCachePluggable, _super);
11
- /**
12
- * Create a SplitsCache that uses a storage wrapper.
13
- * @param log - Logger instance.
14
- * @param keys - Key builder.
15
- * @param wrapper - Adapted wrapper storage.
16
- */
17
- function SplitsCachePluggable(log, keys, wrapper, splitFiltersValidation) {
18
- var _this = _super.call(this) || this;
19
- _this.log = log;
20
- _this.keys = keys;
21
- _this.wrapper = wrapper;
22
- _this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
23
- return _this;
24
- }
25
- SplitsCachePluggable.prototype._decrementCounts = function (split) {
26
- var _this = this;
27
- var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
28
- return this.wrapper.decr(ttKey).then(function (count) {
29
- if (count === 0)
30
- return _this.wrapper.del(ttKey);
31
- });
32
- };
33
- SplitsCachePluggable.prototype._incrementCounts = function (split) {
34
- var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
35
- return this.wrapper.incr(ttKey);
36
- };
37
- SplitsCachePluggable.prototype._updateFlagSets = function (featureFlagName, flagSetsOfRemovedFlag, flagSetsOfAddedFlag) {
38
- var _this = this;
39
- var removeFromFlagSets = returnDifference(flagSetsOfRemovedFlag, flagSetsOfAddedFlag);
40
- var addToFlagSets = returnDifference(flagSetsOfAddedFlag, flagSetsOfRemovedFlag);
41
- if (this.flagSetsFilter.length > 0) {
42
- addToFlagSets = addToFlagSets.filter(function (flagSet) {
43
- return _this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === flagSet; });
44
- });
45
- }
46
- var items = [featureFlagName];
47
- return Promise.all(__spreadArray(__spreadArray([], removeFromFlagSets.map(function (flagSetName) { return _this.wrapper.removeItems(_this.keys.buildFlagSetKey(flagSetName), items); }), true), addToFlagSets.map(function (flagSetName) { return _this.wrapper.addItems(_this.keys.buildFlagSetKey(flagSetName), items); }), true));
48
- };
49
- /**
50
- * Add a given split.
51
- * The returned promise is resolved when the operation success
52
- * or rejected if it fails (e.g., wrapper operation fails)
53
- */
54
- SplitsCachePluggable.prototype.addSplit = function (split) {
55
- var _this = this;
56
- var name = split.name;
57
- var splitKey = this.keys.buildSplitKey(name);
58
- return this.wrapper.get(splitKey).then(function (splitFromStorage) {
59
- // handling parsing error
60
- var parsedPreviousSplit, stringifiedNewSplit;
61
- try {
62
- parsedPreviousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : undefined;
63
- stringifiedNewSplit = JSON.stringify(split);
64
- }
65
- catch (e) {
66
- throw new Error('Error parsing feature flag definition: ' + e);
67
- }
68
- return _this.wrapper.set(splitKey, stringifiedNewSplit).then(function () {
69
- // avoid unnecessary increment/decrement operations
70
- if (parsedPreviousSplit && parsedPreviousSplit.trafficTypeName === split.trafficTypeName)
71
- return;
72
- // update traffic type counts
73
- return _this._incrementCounts(split).then(function () {
74
- if (parsedPreviousSplit)
75
- return _this._decrementCounts(parsedPreviousSplit);
76
- });
77
- }).then(function () { return _this._updateFlagSets(name, parsedPreviousSplit && parsedPreviousSplit.sets, split.sets); });
78
- }).then(function () { return true; });
79
- };
80
- /**
81
- * Remove a given split.
82
- * The returned promise is resolved when the operation success, with a boolean indicating if the split existed or not.
83
- * or rejected if it fails (e.g., wrapper operation fails).
84
- */
85
- SplitsCachePluggable.prototype.removeSplit = function (name) {
86
- var _this = this;
87
- return this.getSplit(name).then(function (split) {
88
- if (split) {
89
- return _this._decrementCounts(split).then(function () { return _this._updateFlagSets(name, split.sets); });
90
- }
91
- }).then(function () {
92
- return _this.wrapper.del(_this.keys.buildSplitKey(name));
93
- });
94
- };
95
- /**
96
- * Get split.
97
- * The returned promise is resolved with the split definition or null if it's not defined,
98
- * or rejected if wrapper operation fails.
99
- */
100
- SplitsCachePluggable.prototype.getSplit = function (name) {
101
- return this.wrapper.get(this.keys.buildSplitKey(name))
102
- .then(function (maybeSplit) { return maybeSplit && JSON.parse(maybeSplit); });
103
- };
104
- /**
105
- * Get list of splits.
106
- * The returned promise is resolved with a map of split names to their split definition or null if it's not defined,
107
- * or rejected if wrapper operation fails.
108
- */
109
- SplitsCachePluggable.prototype.getSplits = function (names) {
110
- var _this = this;
111
- var keys = names.map(function (name) { return _this.keys.buildSplitKey(name); });
112
- return this.wrapper.getMany(keys).then(function (splitDefinitions) {
113
- var splits = {};
114
- names.forEach(function (name, idx) {
115
- var split = splitDefinitions[idx];
116
- splits[name] = split && JSON.parse(split);
117
- });
118
- return Promise.resolve(splits);
119
- });
120
- };
121
- /**
122
- * Get list of all split definitions.
123
- * The returned promise is resolved with the list of split definitions,
124
- * or rejected if wrapper operation fails.
125
- */
126
- SplitsCachePluggable.prototype.getAll = function () {
127
- var _this = this;
128
- return this.wrapper.getKeysByPrefix(this.keys.buildSplitKeyPrefix())
129
- .then(function (listOfKeys) { return _this.wrapper.getMany(listOfKeys); })
130
- .then(function (splitDefinitions) { return splitDefinitions.map(function (splitDefinition) {
131
- return JSON.parse(splitDefinition);
132
- }); });
133
- };
134
- /**
135
- * Get list of split names.
136
- * The returned promise is resolved with the list of split names,
137
- * or rejected if wrapper operation fails.
138
- */
139
- SplitsCachePluggable.prototype.getSplitNames = function () {
140
- var _this = this;
141
- return this.wrapper.getKeysByPrefix(this.keys.buildSplitKeyPrefix()).then(function (listOfKeys) { return listOfKeys.map(_this.keys.extractKey); });
142
- };
143
- /**
144
- * Get list of feature flag names related to a given list of flag set names.
145
- * The returned promise is resolved with the list of feature flag names per flag set.
146
- * It never rejects (If there is a wrapper error for some flag set, an empty set is returned for it).
147
- */
148
- SplitsCachePluggable.prototype.getNamesByFlagSets = function (flagSets) {
149
- var _this = this;
150
- return Promise.all(flagSets.map(function (flagSet) {
151
- var flagSetKey = _this.keys.buildFlagSetKey(flagSet);
152
- return _this.wrapper.getItems(flagSetKey).catch(function () { return []; });
153
- })).then(function (namesByFlagSets) { return namesByFlagSets.map(function (namesByFlagSet) { return new Set(namesByFlagSet); }); });
154
- };
155
- /**
156
- * Check traffic type existence.
157
- * The returned promise is resolved with a boolean indicating whether the TT exist or not.
158
- * In case of wrapper operation failures, the promise resolves with a true value, assuming that the TT might exist.
159
- * It will never be rejected.
160
- */
161
- SplitsCachePluggable.prototype.trafficTypeExists = function (trafficType) {
162
- var _this = this;
163
- // If there is a number there should be > 0, otherwise the TT is considered as not existent.
164
- return this.wrapper.get(this.keys.buildTrafficTypeKey(trafficType))
165
- .then(function (ttCount) {
166
- if (ttCount === null)
167
- return false; // if entry doesn't exist, means that TT doesn't exist
168
- ttCount = parseInt(ttCount, 10);
169
- if (!isFiniteNumber(ttCount) || ttCount < 0) {
170
- _this.log.info(LOG_PREFIX + "Could not validate traffic type existence of ".concat(trafficType, " due to data corruption of some sorts."));
171
- return false;
172
- }
173
- return ttCount > 0;
174
- }).catch(function (e) {
175
- _this.log.error(LOG_PREFIX + "Could not validate traffic type existence of ".concat(trafficType, " due to an error: ").concat(e, "."));
176
- // If there is an error, bypass the validation so the event can get tracked.
177
- return true;
178
- });
179
- };
180
- /**
181
- * Set till number.
182
- * The returned promise is resolved when the operation success,
183
- * or rejected if it fails (e.g., wrapper operation fails).
184
- */
185
- SplitsCachePluggable.prototype.setChangeNumber = function (changeNumber) {
186
- return this.wrapper.set(this.keys.buildSplitsTillKey(), changeNumber + '');
187
- };
188
- /**
189
- * Get till number or -1 if it's not defined.
190
- * The returned promise is resolved with the changeNumber or -1 if it doesn't exist or a wrapper operation fails.
191
- * The promise will never be rejected.
192
- */
193
- SplitsCachePluggable.prototype.getChangeNumber = function () {
194
- var _this = this;
195
- return this.wrapper.get(this.keys.buildSplitsTillKey()).then(function (value) {
196
- var i = parseInt(value, 10);
197
- return isNaNNumber(i) ? -1 : i;
198
- }).catch(function (e) {
199
- _this.log.error(LOG_PREFIX + 'Could not retrieve changeNumber from storage. Error: ' + e);
200
- return -1;
201
- });
202
- };
203
- // @TODO implement if required by DataLoader or producer mode
204
- SplitsCachePluggable.prototype.clear = function () {
205
- return Promise.resolve(true);
206
- };
207
- return SplitsCachePluggable;
208
- }(AbstractSplitsCacheAsync));
209
- export { SplitsCachePluggable };
@@ -1,9 +0,0 @@
1
- import { syncTaskFactory } from '../../syncTask';
2
- import { splitChangesFetcherFactory } from '../fetchers/splitChangesFetcher';
3
- import { splitChangesUpdaterFactory } from '../updaters/splitChangesUpdater';
4
- /**
5
- * Creates a sync task that periodically executes a `splitChangesUpdater` task
6
- */
7
- export function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings, isClientSide) {
8
- return syncTaskFactory(settings.log, splitChangesUpdaterFactory(settings.log, splitChangesFetcherFactory(fetchSplitChanges, settings, storage), storage, settings.sync.__splitFiltersValidation, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, isClientSide), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
9
- }