@splitsoftware/splitio-commons 1.6.2-rc.8 → 1.7.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 (177) hide show
  1. package/CHANGES.txt +4 -1
  2. package/cjs/evaluator/index.js +5 -5
  3. package/cjs/listeners/browser.js +9 -11
  4. package/cjs/sdkClient/client.js +19 -7
  5. package/cjs/sdkFactory/index.js +7 -25
  6. package/cjs/services/splitApi.js +4 -4
  7. package/cjs/storages/AbstractSplitsCacheAsync.js +1 -1
  8. package/cjs/storages/AbstractSplitsCacheSync.js +1 -1
  9. package/cjs/storages/KeyBuilderSS.js +9 -9
  10. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +0 -1
  11. package/cjs/storages/inLocalStorage/index.js +15 -11
  12. package/cjs/storages/inMemory/InMemoryStorage.js +11 -8
  13. package/cjs/storages/inMemory/InMemoryStorageCS.js +11 -8
  14. package/cjs/storages/inMemory/TelemetryCacheInMemory.js +65 -37
  15. package/cjs/storages/inMemory/{uniqueKeysCacheInMemory.js → UniqueKeysCacheInMemory.js} +24 -25
  16. package/cjs/storages/inMemory/{uniqueKeysCacheInMemoryCS.js → UniqueKeysCacheInMemoryCS.js} +10 -12
  17. package/cjs/storages/inRedis/EventsCacheInRedis.js +1 -1
  18. package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +37 -2
  19. package/cjs/storages/inRedis/ImpressionsCacheInRedis.js +2 -19
  20. package/cjs/storages/inRedis/TelemetryCacheInRedis.js +100 -0
  21. package/cjs/storages/inRedis/{uniqueKeysCacheInRedis.js → UniqueKeysCacheInRedis.js} +16 -4
  22. package/cjs/storages/inRedis/index.js +6 -4
  23. package/cjs/storages/pluggable/ImpressionCountsCachePluggable.js +81 -0
  24. package/cjs/storages/pluggable/ImpressionsCachePluggable.js +2 -19
  25. package/cjs/storages/pluggable/TelemetryCachePluggable.js +126 -0
  26. package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +61 -0
  27. package/cjs/storages/pluggable/inMemoryWrapper.js +8 -6
  28. package/cjs/storages/pluggable/index.js +51 -18
  29. package/cjs/storages/utils.js +73 -0
  30. package/cjs/sync/submitters/submitterManager.js +1 -1
  31. package/cjs/sync/submitters/telemetrySubmitter.js +4 -37
  32. package/cjs/sync/submitters/uniqueKeysSubmitter.js +4 -3
  33. package/cjs/trackers/impressionObserver/utils.js +1 -17
  34. package/cjs/trackers/uniqueKeysTracker.js +1 -1
  35. package/cjs/utils/lang/maps.js +15 -7
  36. package/cjs/utils/redis/RedisMock.js +31 -0
  37. package/cjs/utils/settingsValidation/index.js +7 -4
  38. package/esm/evaluator/index.js +5 -5
  39. package/esm/listeners/browser.js +9 -11
  40. package/esm/sdkClient/client.js +19 -7
  41. package/esm/sdkFactory/index.js +7 -25
  42. package/esm/services/splitApi.js +4 -4
  43. package/esm/storages/AbstractSplitsCacheAsync.js +1 -1
  44. package/esm/storages/AbstractSplitsCacheSync.js +1 -1
  45. package/esm/storages/KeyBuilderSS.js +8 -8
  46. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +0 -1
  47. package/esm/storages/inLocalStorage/index.js +16 -12
  48. package/esm/storages/inMemory/InMemoryStorage.js +13 -10
  49. package/esm/storages/inMemory/InMemoryStorageCS.js +12 -9
  50. package/esm/storages/inMemory/TelemetryCacheInMemory.js +64 -37
  51. package/esm/storages/inMemory/{uniqueKeysCacheInMemory.js → UniqueKeysCacheInMemory.js} +22 -24
  52. package/esm/storages/inMemory/{uniqueKeysCacheInMemoryCS.js → UniqueKeysCacheInMemoryCS.js} +10 -12
  53. package/esm/storages/inRedis/EventsCacheInRedis.js +1 -1
  54. package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +37 -2
  55. package/esm/storages/inRedis/ImpressionsCacheInRedis.js +2 -19
  56. package/esm/storages/inRedis/TelemetryCacheInRedis.js +100 -0
  57. package/esm/storages/inRedis/{uniqueKeysCacheInRedis.js → UniqueKeysCacheInRedis.js} +15 -3
  58. package/esm/storages/inRedis/index.js +5 -3
  59. package/esm/storages/pluggable/ImpressionCountsCachePluggable.js +78 -0
  60. package/esm/storages/pluggable/ImpressionsCachePluggable.js +2 -19
  61. package/esm/storages/pluggable/TelemetryCachePluggable.js +126 -0
  62. package/esm/storages/pluggable/UniqueKeysCachePluggable.js +58 -0
  63. package/esm/storages/pluggable/inMemoryWrapper.js +8 -6
  64. package/esm/storages/pluggable/index.js +52 -19
  65. package/esm/storages/utils.js +65 -0
  66. package/esm/sync/submitters/submitterManager.js +1 -1
  67. package/esm/sync/submitters/telemetrySubmitter.js +4 -36
  68. package/esm/sync/submitters/uniqueKeysSubmitter.js +4 -3
  69. package/esm/trackers/impressionObserver/utils.js +1 -15
  70. package/esm/trackers/uniqueKeysTracker.js +1 -1
  71. package/esm/utils/lang/maps.js +15 -7
  72. package/esm/utils/redis/RedisMock.js +28 -0
  73. package/esm/utils/settingsValidation/index.js +7 -4
  74. package/package.json +2 -2
  75. package/src/consent/sdkUserConsent.ts +1 -1
  76. package/src/evaluator/index.ts +6 -6
  77. package/src/listeners/browser.ts +9 -13
  78. package/src/logger/.DS_Store +0 -0
  79. package/src/sdkClient/client.ts +21 -8
  80. package/src/sdkClient/sdkClient.ts +1 -1
  81. package/src/sdkFactory/index.ts +10 -33
  82. package/src/sdkFactory/types.ts +2 -2
  83. package/src/services/splitApi.ts +6 -6
  84. package/src/services/types.ts +2 -2
  85. package/src/storages/AbstractSplitsCacheAsync.ts +1 -1
  86. package/src/storages/AbstractSplitsCacheSync.ts +1 -1
  87. package/src/storages/KeyBuilderSS.ts +13 -11
  88. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +0 -1
  89. package/src/storages/inLocalStorage/index.ts +17 -12
  90. package/src/storages/inMemory/AttributesCacheInMemory.ts +7 -7
  91. package/src/storages/inMemory/ImpressionCountsCacheInMemory.ts +2 -2
  92. package/src/storages/inMemory/InMemoryStorage.ts +14 -10
  93. package/src/storages/inMemory/InMemoryStorageCS.ts +13 -10
  94. package/src/storages/inMemory/TelemetryCacheInMemory.ts +72 -35
  95. package/src/storages/inMemory/{uniqueKeysCacheInMemory.ts → UniqueKeysCacheInMemory.ts} +26 -28
  96. package/src/storages/inMemory/{uniqueKeysCacheInMemoryCS.ts → UniqueKeysCacheInMemoryCS.ts} +15 -17
  97. package/src/storages/inRedis/EventsCacheInRedis.ts +1 -1
  98. package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +51 -8
  99. package/src/storages/inRedis/ImpressionsCacheInRedis.ts +2 -22
  100. package/src/storages/inRedis/TelemetryCacheInRedis.ts +122 -1
  101. package/src/storages/inRedis/{uniqueKeysCacheInRedis.ts → UniqueKeysCacheInRedis.ts} +25 -12
  102. package/src/storages/inRedis/index.ts +6 -3
  103. package/src/storages/pluggable/ImpressionCountsCachePluggable.ts +92 -0
  104. package/src/storages/pluggable/ImpressionsCachePluggable.ts +3 -23
  105. package/src/storages/pluggable/TelemetryCachePluggable.ts +147 -1
  106. package/src/storages/pluggable/UniqueKeysCachePluggable.ts +67 -0
  107. package/src/storages/pluggable/inMemoryWrapper.ts +6 -6
  108. package/src/storages/pluggable/index.ts +56 -20
  109. package/src/storages/types.ts +53 -70
  110. package/src/storages/utils.ts +78 -0
  111. package/src/sync/submitters/submitter.ts +2 -2
  112. package/src/sync/submitters/submitterManager.ts +1 -1
  113. package/src/sync/submitters/telemetrySubmitter.ts +9 -39
  114. package/src/sync/submitters/types.ts +33 -17
  115. package/src/sync/submitters/uniqueKeysSubmitter.ts +6 -5
  116. package/src/trackers/impressionObserver/utils.ts +1 -16
  117. package/src/trackers/impressionsTracker.ts +2 -2
  118. package/src/trackers/strategy/strategyDebug.ts +4 -4
  119. package/src/trackers/strategy/strategyNone.ts +9 -9
  120. package/src/trackers/strategy/strategyOptimized.ts +9 -9
  121. package/src/trackers/uniqueKeysTracker.ts +6 -6
  122. package/src/types.ts +0 -2
  123. package/src/utils/lang/maps.ts +20 -8
  124. package/src/utils/redis/RedisMock.ts +33 -0
  125. package/src/utils/settingsValidation/index.ts +5 -5
  126. package/types/services/types.d.ts +2 -2
  127. package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
  128. package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
  129. package/types/storages/KeyBuilderSS.d.ts +5 -2
  130. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +0 -1
  131. package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +23 -9
  132. package/types/storages/inMemory/uniqueKeysCacheInMemory.d.ts +9 -9
  133. package/types/storages/inMemory/uniqueKeysCacheInMemoryCS.d.ts +2 -4
  134. package/types/storages/inRedis/EventsCacheInRedis.d.ts +1 -1
  135. package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +3 -1
  136. package/types/storages/inRedis/ImpressionsCacheInRedis.d.ts +0 -1
  137. package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +16 -1
  138. package/types/storages/inRedis/uniqueKeysCacheInRedis.d.ts +8 -2
  139. package/types/storages/pluggable/ImpressionCountsCachePluggable.d.ts +16 -0
  140. package/types/storages/pluggable/ImpressionsCachePluggable.d.ts +1 -2
  141. package/types/storages/pluggable/TelemetryCachePluggable.d.ts +17 -1
  142. package/types/storages/pluggable/UniqueKeysCachePluggable.d.ts +20 -0
  143. package/types/storages/types.d.ts +42 -49
  144. package/types/storages/utils.d.ts +8 -0
  145. package/types/sync/submitters/submitter.d.ts +2 -2
  146. package/types/sync/submitters/telemetrySubmitter.d.ts +2 -10
  147. package/types/sync/submitters/types.d.ts +27 -18
  148. package/types/trackers/impressionObserver/utils.d.ts +0 -8
  149. package/types/trackers/strategy/strategyNone.d.ts +2 -2
  150. package/types/trackers/strategy/strategyOptimized.d.ts +2 -2
  151. package/types/trackers/uniqueKeysTracker.d.ts +1 -1
  152. package/types/types.d.ts +0 -2
  153. package/types/utils/lang/maps.d.ts +6 -2
  154. package/types/utils/redis/RedisMock.d.ts +4 -0
  155. package/types/utils/settingsValidation/index.d.ts +0 -1
  156. package/cjs/storages/metadataBuilder.js +0 -12
  157. package/esm/storages/metadataBuilder.js +0 -8
  158. package/src/storages/metadataBuilder.ts +0 -11
  159. package/types/sdkClient/types.d.ts +0 -18
  160. package/types/storages/inMemory/CountsCacheInMemory.d.ts +0 -20
  161. package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +0 -20
  162. package/types/storages/inRedis/CountsCacheInRedis.d.ts +0 -9
  163. package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +0 -9
  164. package/types/sync/offline/LocalhostFromFile.d.ts +0 -2
  165. package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +0 -2
  166. package/types/sync/submitters/eventsSyncTask.d.ts +0 -8
  167. package/types/sync/submitters/impressionCountsSubmitterInRedis.d.ts +0 -5
  168. package/types/sync/submitters/impressionCountsSyncTask.d.ts +0 -13
  169. package/types/sync/submitters/impressionsSyncTask.d.ts +0 -14
  170. package/types/sync/submitters/metricsSyncTask.d.ts +0 -12
  171. package/types/sync/submitters/submitterSyncTask.d.ts +0 -10
  172. package/types/sync/submitters/uniqueKeysSubmitterInRedis.d.ts +0 -5
  173. package/types/sync/syncTaskComposite.d.ts +0 -5
  174. package/types/trackers/filter/bloomFilter.d.ts +0 -10
  175. package/types/trackers/filter/dictionaryFilter.d.ts +0 -8
  176. package/types/trackers/filter/types.d.ts +0 -5
  177. package/types/utils/timeTracker/index.d.ts +0 -70
@@ -1,8 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.UniqueKeysCacheInMemory = void 0;
3
+ exports.UniqueKeysCacheInMemory = exports.fromUniqueKeysCollector = void 0;
4
4
  var sets_1 = require("../../utils/lang/sets");
5
5
  var constants_1 = require("../inRedis/constants");
6
+ /**
7
+ * Converts `uniqueKeys` data from cache into request payload for SS.
8
+ */
9
+ function fromUniqueKeysCollector(uniqueKeys) {
10
+ var payload = [];
11
+ var featureNames = Object.keys(uniqueKeys);
12
+ for (var i = 0; i < featureNames.length; i++) {
13
+ var featureName = featureNames[i];
14
+ var userKeys = (0, sets_1.setToArray)(uniqueKeys[featureName]);
15
+ var uniqueKeysPayload = {
16
+ f: featureName,
17
+ ks: userKeys
18
+ };
19
+ payload.push(uniqueKeysPayload);
20
+ }
21
+ return { keys: payload };
22
+ }
23
+ exports.fromUniqueKeysCollector = fromUniqueKeysCollector;
6
24
  var UniqueKeysCacheInMemory = /** @class */ (function () {
7
25
  function UniqueKeysCacheInMemory(uniqueKeysQueueSize) {
8
26
  if (uniqueKeysQueueSize === void 0) { uniqueKeysQueueSize = constants_1.DEFAULT_CACHE_SIZE; }
@@ -14,16 +32,14 @@ var UniqueKeysCacheInMemory = /** @class */ (function () {
14
32
  this.onFullQueue = cb;
15
33
  };
16
34
  /**
17
- * Store unique keys in sequential order
18
- * key: string = feature name.
19
- * value: Set<string> = set of unique keys.
35
+ * Store unique keys per feature.
20
36
  */
21
- UniqueKeysCacheInMemory.prototype.track = function (key, featureName) {
37
+ UniqueKeysCacheInMemory.prototype.track = function (userKey, featureName) {
22
38
  if (!this.uniqueKeysTracker[featureName])
23
39
  this.uniqueKeysTracker[featureName] = new sets_1._Set();
24
40
  var tracker = this.uniqueKeysTracker[featureName];
25
- if (!tracker.has(key)) {
26
- tracker.add(key);
41
+ if (!tracker.has(userKey)) {
42
+ tracker.add(userKey);
27
43
  this.uniqueTrackerSize++;
28
44
  }
29
45
  if (this.uniqueTrackerSize >= this.maxStorage && this.onFullQueue) {
@@ -43,7 +59,7 @@ var UniqueKeysCacheInMemory = /** @class */ (function () {
43
59
  UniqueKeysCacheInMemory.prototype.pop = function () {
44
60
  var data = this.uniqueKeysTracker;
45
61
  this.uniqueKeysTracker = {};
46
- return this.fromUniqueKeysCollector(data);
62
+ return fromUniqueKeysCollector(data);
47
63
  };
48
64
  /**
49
65
  * Check if the cache is empty.
@@ -51,23 +67,6 @@ var UniqueKeysCacheInMemory = /** @class */ (function () {
51
67
  UniqueKeysCacheInMemory.prototype.isEmpty = function () {
52
68
  return Object.keys(this.uniqueKeysTracker).length === 0;
53
69
  };
54
- /**
55
- * Converts `uniqueKeys` data from cache into request payload for SS.
56
- */
57
- UniqueKeysCacheInMemory.prototype.fromUniqueKeysCollector = function (uniqueKeys) {
58
- var payload = [];
59
- var featureNames = Object.keys(uniqueKeys);
60
- for (var i = 0; i < featureNames.length; i++) {
61
- var featureName = featureNames[i];
62
- var featureKeys = (0, sets_1.setToArray)(uniqueKeys[featureName]);
63
- var uniqueKeysPayload = {
64
- f: featureName,
65
- ks: featureKeys
66
- };
67
- payload.push(uniqueKeysPayload);
68
- }
69
- return { keys: payload };
70
- };
71
70
  return UniqueKeysCacheInMemory;
72
71
  }());
73
72
  exports.UniqueKeysCacheInMemory = UniqueKeysCacheInMemory;
@@ -19,14 +19,12 @@ var UniqueKeysCacheInMemoryCS = /** @class */ (function () {
19
19
  this.onFullQueue = cb;
20
20
  };
21
21
  /**
22
- * Store unique keys in sequential order
23
- * key: string = key.
24
- * value: HashSet<string> = set of split names.
22
+ * Store unique keys per feature.
25
23
  */
26
- UniqueKeysCacheInMemoryCS.prototype.track = function (key, featureName) {
27
- if (!this.uniqueKeysTracker[key])
28
- this.uniqueKeysTracker[key] = new sets_1._Set();
29
- var tracker = this.uniqueKeysTracker[key];
24
+ UniqueKeysCacheInMemoryCS.prototype.track = function (userKey, featureName) {
25
+ if (!this.uniqueKeysTracker[userKey])
26
+ this.uniqueKeysTracker[userKey] = new sets_1._Set();
27
+ var tracker = this.uniqueKeysTracker[userKey];
30
28
  if (!tracker.has(featureName)) {
31
29
  tracker.add(featureName);
32
30
  this.uniqueTrackerSize++;
@@ -61,12 +59,12 @@ var UniqueKeysCacheInMemoryCS = /** @class */ (function () {
61
59
  */
62
60
  UniqueKeysCacheInMemoryCS.prototype.fromUniqueKeysCollector = function (uniqueKeys) {
63
61
  var payload = [];
64
- var featureKeys = Object.keys(uniqueKeys);
65
- for (var k = 0; k < featureKeys.length; k++) {
66
- var featureKey = featureKeys[k];
67
- var featureNames = (0, sets_1.setToArray)(uniqueKeys[featureKey]);
62
+ var userKeys = Object.keys(uniqueKeys);
63
+ for (var k = 0; k < userKeys.length; k++) {
64
+ var userKey = userKeys[k];
65
+ var featureNames = (0, sets_1.setToArray)(uniqueKeys[userKey]);
68
66
  var uniqueKeysPayload = {
69
- k: featureKey,
67
+ k: userKey,
70
68
  fs: featureNames
71
69
  };
72
70
  payload.push(uniqueKeysPayload);
@@ -42,7 +42,7 @@ var EventsCacheInRedis = /** @class */ (function () {
42
42
  };
43
43
  /**
44
44
  * Pop the given number of events from the storage.
45
- * The returned promise rejects if the wrapper operation fails.
45
+ * The returned promise rejects if the redis operation fails.
46
46
  *
47
47
  * NOTE: this method doesn't take into account MAX_EVENT_SIZE or MAX_QUEUE_BYTE_SIZE limits.
48
48
  * It is the submitter responsability to handle that.
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ImpressionCountsCacheInRedis = void 0;
4
4
  var tslib_1 = require("tslib");
5
+ var lang_1 = require("../../utils/lang");
5
6
  var ImpressionCountsCacheInMemory_1 = require("../inMemory/ImpressionCountsCacheInMemory");
6
7
  var constants_1 = require("./constants");
7
8
  var ImpressionCountsCacheInRedis = /** @class */ (function (_super) {
@@ -20,7 +21,7 @@ var ImpressionCountsCacheInRedis = /** @class */ (function (_super) {
20
21
  var _this = this;
21
22
  var counts = this.pop();
22
23
  var keys = Object.keys(counts);
23
- if (!keys)
24
+ if (!keys.length)
24
25
  return Promise.resolve(false);
25
26
  var pipeline = this.redis.pipeline();
26
27
  keys.forEach(function (key) {
@@ -35,7 +36,7 @@ var ImpressionCountsCacheInRedis = /** @class */ (function (_super) {
35
36
  })
36
37
  .catch(function (err) {
37
38
  _this.log.error(constants_1.LOG_PREFIX + "Error in impression counts pipeline: " + err + ".");
38
- return Promise.resolve(false);
39
+ return false;
39
40
  });
40
41
  };
41
42
  ImpressionCountsCacheInRedis.prototype.start = function () {
@@ -45,6 +46,40 @@ var ImpressionCountsCacheInRedis = /** @class */ (function (_super) {
45
46
  clearInterval(this.intervalId);
46
47
  return this.postImpressionCountsInRedis();
47
48
  };
49
+ // Async consumer API, used by synchronizer
50
+ ImpressionCountsCacheInRedis.prototype.getImpressionsCount = function () {
51
+ var _this = this;
52
+ return this.redis.hgetall(this.key)
53
+ .then(function (counts) {
54
+ if (!Object.keys(counts).length)
55
+ return undefined;
56
+ _this.redis.del(_this.key).catch(function () { });
57
+ var pf = [];
58
+ (0, lang_1.forOwn)(counts, function (count, key) {
59
+ var nameAndTime = key.split('::');
60
+ if (nameAndTime.length !== 2) {
61
+ _this.log.error(constants_1.LOG_PREFIX + "Error spliting key " + key);
62
+ return;
63
+ }
64
+ var timeFrame = parseInt(nameAndTime[1]);
65
+ if (isNaN(timeFrame)) {
66
+ _this.log.error(constants_1.LOG_PREFIX + "Error parsing time frame " + nameAndTime[1]);
67
+ return;
68
+ }
69
+ var rawCount = parseInt(count);
70
+ if (isNaN(rawCount)) {
71
+ _this.log.error(constants_1.LOG_PREFIX + "Error parsing raw count " + count);
72
+ return;
73
+ }
74
+ pf.push({
75
+ f: nameAndTime[0],
76
+ m: timeFrame,
77
+ rc: rawCount,
78
+ });
79
+ });
80
+ return { pf: pf };
81
+ });
82
+ };
48
83
  return ImpressionCountsCacheInRedis;
49
84
  }(ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory));
50
85
  exports.ImpressionCountsCacheInRedis = ImpressionCountsCacheInRedis;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ImpressionsCacheInRedis = void 0;
4
+ var utils_1 = require("../utils");
4
5
  var IMPRESSIONS_TTL_REFRESH = 3600; // 1 hr
5
6
  var ImpressionsCacheInRedis = /** @class */ (function () {
6
7
  function ImpressionsCacheInRedis(log, key, redis, metadata) {
@@ -11,31 +12,13 @@ var ImpressionsCacheInRedis = /** @class */ (function () {
11
12
  }
12
13
  ImpressionsCacheInRedis.prototype.track = function (impressions) {
13
14
  var _this = this;
14
- return this.redis.rpush(this.key, this._toJSON(impressions)).then(function (queuedCount) {
15
+ return this.redis.rpush(this.key, (0, utils_1.impressionsToJSON)(impressions, this.metadata)).then(function (queuedCount) {
15
16
  // If this is the creation of the key on Redis, set the expiration for it in 1hr.
16
17
  if (queuedCount === impressions.length) {
17
18
  return _this.redis.expire(_this.key, IMPRESSIONS_TTL_REFRESH);
18
19
  }
19
20
  });
20
21
  };
21
- ImpressionsCacheInRedis.prototype._toJSON = function (impressions) {
22
- var _this = this;
23
- return impressions.map(function (impression) {
24
- var keyName = impression.keyName, bucketingKey = impression.bucketingKey, feature = impression.feature, treatment = impression.treatment, label = impression.label, time = impression.time, changeNumber = impression.changeNumber;
25
- return JSON.stringify({
26
- m: _this.metadata,
27
- i: {
28
- k: keyName,
29
- b: bucketingKey,
30
- f: feature,
31
- t: treatment,
32
- r: label,
33
- c: changeNumber,
34
- m: time
35
- }
36
- });
37
- });
38
- };
39
22
  ImpressionsCacheInRedis.prototype.count = function () {
40
23
  return this.redis.llen(this.key).catch(function () { return 0; });
41
24
  };
@@ -4,6 +4,10 @@ exports.TelemetryCacheInRedis = void 0;
4
4
  var findLatencyIndex_1 = require("../findLatencyIndex");
5
5
  var telemetrySubmitter_1 = require("../../sync/submitters/telemetrySubmitter");
6
6
  var constants_1 = require("../../utils/constants");
7
+ var lang_1 = require("../../utils/lang");
8
+ var maps_1 = require("../../utils/lang/maps");
9
+ var TelemetryCacheInMemory_1 = require("../inMemory/TelemetryCacheInMemory");
10
+ var utils_1 = require("../utils");
7
11
  var TelemetryCacheInRedis = /** @class */ (function () {
8
12
  /**
9
13
  * Create a Telemetry cache that uses Redis as storage.
@@ -31,6 +35,102 @@ var TelemetryCacheInRedis = /** @class */ (function () {
31
35
  var value = JSON.stringify((0, telemetrySubmitter_1.getTelemetryConfigStats)(constants_1.CONSUMER_MODE, constants_1.STORAGE_REDIS));
32
36
  return this.redis.hset(key, field, value).catch(function () { });
33
37
  };
38
+ /**
39
+ * Pop telemetry latencies.
40
+ * The returned promise rejects if redis operations fail.
41
+ */
42
+ TelemetryCacheInRedis.prototype.popLatencies = function () {
43
+ var _this = this;
44
+ return this.redis.hgetall(this.keys.latencyPrefix).then(function (latencies) {
45
+ var result = new maps_1._Map();
46
+ Object.keys(latencies).forEach(function (field) {
47
+ var parsedField = (0, utils_1.parseLatencyField)(field);
48
+ if ((0, lang_1.isString)(parsedField)) {
49
+ _this.log.error("Ignoring invalid latency field: " + field + ": " + parsedField);
50
+ return;
51
+ }
52
+ var count = parseInt(latencies[field]);
53
+ if ((0, lang_1.isNaNNumber)(count)) {
54
+ _this.log.error("Ignoring latency with invalid count: " + latencies[field]);
55
+ return;
56
+ }
57
+ var metadata = parsedField[0], method = parsedField[1], bucket = parsedField[2];
58
+ if (bucket >= TelemetryCacheInMemory_1.MAX_LATENCY_BUCKET_COUNT) {
59
+ _this.log.error("Ignoring latency with invalid bucket: " + bucket);
60
+ return;
61
+ }
62
+ if (!result.has(metadata))
63
+ result.set(metadata, {
64
+ t: (0, TelemetryCacheInMemory_1.newBuckets)(),
65
+ ts: (0, TelemetryCacheInMemory_1.newBuckets)(),
66
+ tc: (0, TelemetryCacheInMemory_1.newBuckets)(),
67
+ tcs: (0, TelemetryCacheInMemory_1.newBuckets)(),
68
+ tr: (0, TelemetryCacheInMemory_1.newBuckets)(),
69
+ });
70
+ result.get(metadata)[method][bucket] = count;
71
+ });
72
+ return _this.redis.del(_this.keys.latencyPrefix).then(function () { return result; });
73
+ });
74
+ };
75
+ /**
76
+ * Pop telemetry exceptions.
77
+ * The returned promise rejects if redis operations fail.
78
+ */
79
+ TelemetryCacheInRedis.prototype.popExceptions = function () {
80
+ var _this = this;
81
+ return this.redis.hgetall(this.keys.exceptionPrefix).then(function (exceptions) {
82
+ var result = new maps_1._Map();
83
+ Object.keys(exceptions).forEach(function (field) {
84
+ var parsedField = (0, utils_1.parseExceptionField)(field);
85
+ if ((0, lang_1.isString)(parsedField)) {
86
+ _this.log.error("Ignoring invalid exception field: " + field + ": " + parsedField);
87
+ return;
88
+ }
89
+ var count = parseInt(exceptions[field]);
90
+ if ((0, lang_1.isNaNNumber)(count)) {
91
+ _this.log.error("Ignoring exception with invalid count: " + exceptions[field]);
92
+ return;
93
+ }
94
+ var metadata = parsedField[0], method = parsedField[1];
95
+ if (!result.has(metadata))
96
+ result.set(metadata, {
97
+ t: 0,
98
+ ts: 0,
99
+ tc: 0,
100
+ tcs: 0,
101
+ tr: 0,
102
+ });
103
+ result.get(metadata)[method] = count;
104
+ });
105
+ return _this.redis.del(_this.keys.exceptionPrefix).then(function () { return result; });
106
+ });
107
+ };
108
+ /**
109
+ * Pop telemetry configs.
110
+ * The returned promise rejects if redis operations fail.
111
+ */
112
+ TelemetryCacheInRedis.prototype.popConfigs = function () {
113
+ var _this = this;
114
+ return this.redis.hgetall(this.keys.initPrefix).then(function (configs) {
115
+ var result = new maps_1._Map();
116
+ Object.keys(configs).forEach(function (field) {
117
+ var parsedField = (0, utils_1.parseMetadata)(field);
118
+ if ((0, lang_1.isString)(parsedField)) {
119
+ _this.log.error("Ignoring invalid config field: " + field + ": " + parsedField);
120
+ return;
121
+ }
122
+ var metadata = parsedField[0];
123
+ try {
124
+ var config = JSON.parse(configs[field]);
125
+ result.set(metadata, config);
126
+ }
127
+ catch (e) {
128
+ _this.log.error("Ignoring invalid config: " + configs[field]);
129
+ }
130
+ });
131
+ return _this.redis.del(_this.keys.initPrefix).then(function () { return result; });
132
+ });
133
+ };
34
134
  return TelemetryCacheInRedis;
35
135
  }());
36
136
  exports.TelemetryCacheInRedis = TelemetryCacheInRedis;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UniqueKeysCacheInRedis = void 0;
4
4
  var tslib_1 = require("tslib");
5
- var uniqueKeysCacheInMemory_1 = require("../inMemory/uniqueKeysCacheInMemory");
5
+ var UniqueKeysCacheInMemory_1 = require("../inMemory/UniqueKeysCacheInMemory");
6
6
  var sets_1 = require("../../utils/lang/sets");
7
7
  var constants_1 = require("./constants");
8
8
  var constants_2 = require("./constants");
@@ -22,7 +22,7 @@ var UniqueKeysCacheInRedis = /** @class */ (function (_super) {
22
22
  UniqueKeysCacheInRedis.prototype.postUniqueKeysInRedis = function () {
23
23
  var _this = this;
24
24
  var featureNames = Object.keys(this.uniqueKeysTracker);
25
- if (!featureNames)
25
+ if (!featureNames.length)
26
26
  return Promise.resolve(false);
27
27
  var pipeline = this.redis.pipeline();
28
28
  for (var i = 0; i < featureNames.length; i++) {
@@ -44,7 +44,7 @@ var UniqueKeysCacheInRedis = /** @class */ (function (_super) {
44
44
  })
45
45
  .catch(function (err) {
46
46
  _this.log.error(constants_2.LOG_PREFIX + "Error in uniqueKeys pipeline: " + err + ".");
47
- return Promise.resolve(false);
47
+ return false;
48
48
  });
49
49
  };
50
50
  UniqueKeysCacheInRedis.prototype.start = function () {
@@ -54,6 +54,18 @@ var UniqueKeysCacheInRedis = /** @class */ (function (_super) {
54
54
  clearInterval(this.intervalId);
55
55
  return this.postUniqueKeysInRedis();
56
56
  };
57
+ /**
58
+ * Async consumer API, used by synchronizer.
59
+ * @param count number of items to pop from the queue. If not provided or equal 0, all items will be popped.
60
+ */
61
+ UniqueKeysCacheInRedis.prototype.popNRaw = function (count) {
62
+ var _this = this;
63
+ if (count === void 0) { count = 0; }
64
+ return this.redis.lrange(this.key, 0, count - 1).then(function (uniqueKeyItems) {
65
+ return _this.redis.ltrim(_this.key, uniqueKeyItems.length, -1)
66
+ .then(function () { return uniqueKeyItems.map(function (uniqueKeyItem) { return JSON.parse(uniqueKeyItem); }); });
67
+ });
68
+ };
57
69
  return UniqueKeysCacheInRedis;
58
- }(uniqueKeysCacheInMemory_1.UniqueKeysCacheInMemory));
70
+ }(UniqueKeysCacheInMemory_1.UniqueKeysCacheInMemory));
59
71
  exports.UniqueKeysCacheInRedis = UniqueKeysCacheInRedis;
@@ -10,8 +10,9 @@ var ImpressionsCacheInRedis_1 = require("./ImpressionsCacheInRedis");
10
10
  var EventsCacheInRedis_1 = require("./EventsCacheInRedis");
11
11
  var constants_1 = require("../../utils/constants");
12
12
  var TelemetryCacheInRedis_1 = require("./TelemetryCacheInRedis");
13
- var uniqueKeysCacheInRedis_1 = require("./uniqueKeysCacheInRedis");
13
+ var UniqueKeysCacheInRedis_1 = require("./UniqueKeysCacheInRedis");
14
14
  var ImpressionCountsCacheInRedis_1 = require("./ImpressionCountsCacheInRedis");
15
+ var utils_1 = require("../utils");
15
16
  /**
16
17
  * InRedis storage factory for consumer server-side SplitFactory, that uses `Ioredis` Redis client for Node.
17
18
  * @see {@link https://www.npmjs.com/package/ioredis}
@@ -19,13 +20,14 @@ var ImpressionCountsCacheInRedis_1 = require("./ImpressionCountsCacheInRedis");
19
20
  function InRedisStorage(options) {
20
21
  if (options === void 0) { options = {}; }
21
22
  var prefix = (0, KeyBuilder_1.validatePrefix)(options.prefix);
22
- function InRedisStorageFactory(_a) {
23
- var log = _a.log, metadata = _a.metadata, onReadyCb = _a.onReadyCb, impressionsMode = _a.impressionsMode;
23
+ function InRedisStorageFactory(params) {
24
+ var onReadyCb = params.onReadyCb, settings = params.settings, _a = params.settings, log = _a.log, impressionsMode = _a.sync.impressionsMode;
25
+ var metadata = (0, utils_1.metadataBuilder)(settings);
24
26
  var keys = new KeyBuilderSS_1.KeyBuilderSS(prefix, metadata);
25
27
  var redisClient = new RedisAdapter_1.RedisAdapter(log, options.options || {});
26
28
  var telemetry = new TelemetryCacheInRedis_1.TelemetryCacheInRedis(log, keys, redisClient);
27
29
  var impressionCountsCache = impressionsMode !== constants_1.DEBUG ? new ImpressionCountsCacheInRedis_1.ImpressionCountsCacheInRedis(log, keys.buildImpressionsCountKey(), redisClient) : undefined;
28
- var uniqueKeysCache = impressionsMode === constants_1.NONE ? new uniqueKeysCacheInRedis_1.UniqueKeysCacheInRedis(log, keys.buildUniqueKeysKey(), redisClient) : undefined;
30
+ var uniqueKeysCache = impressionsMode === constants_1.NONE ? new UniqueKeysCacheInRedis_1.UniqueKeysCacheInRedis(log, keys.buildUniqueKeysKey(), redisClient) : undefined;
29
31
  // subscription to Redis connect event in order to emit SDK_READY event on consumer mode
30
32
  redisClient.on('connect', function () {
31
33
  onReadyCb();
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImpressionCountsCachePluggable = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var ImpressionCountsCacheInMemory_1 = require("../inMemory/ImpressionCountsCacheInMemory");
6
+ var constants_1 = require("../inRedis/constants");
7
+ var constants_2 = require("./constants");
8
+ var ImpressionCountsCachePluggable = /** @class */ (function (_super) {
9
+ (0, tslib_1.__extends)(ImpressionCountsCachePluggable, _super);
10
+ function ImpressionCountsCachePluggable(log, key, wrapper, impressionCountsCacheSize, refreshRate) {
11
+ if (refreshRate === void 0) { refreshRate = constants_1.REFRESH_RATE; }
12
+ var _this = _super.call(this, impressionCountsCacheSize) || this;
13
+ _this.log = log;
14
+ _this.key = key;
15
+ _this.wrapper = wrapper;
16
+ _this.refreshRate = refreshRate;
17
+ _this.onFullQueue = function () { _this.storeImpressionCounts(); };
18
+ return _this;
19
+ }
20
+ ImpressionCountsCachePluggable.prototype.storeImpressionCounts = function () {
21
+ var _this = this;
22
+ var counts = this.pop();
23
+ var keys = Object.keys(counts);
24
+ if (!keys.length)
25
+ return Promise.resolve(false);
26
+ var pipeline = keys.reduce(function (pipeline, key) {
27
+ return pipeline.then(function () { return _this.wrapper.incr(_this.key + "::" + key, counts[key]); });
28
+ }, Promise.resolve());
29
+ return pipeline.catch(function (err) {
30
+ _this.log.error(constants_2.LOG_PREFIX + "Error in impression counts pipeline: " + err + ".");
31
+ return false;
32
+ });
33
+ };
34
+ ImpressionCountsCachePluggable.prototype.start = function () {
35
+ this.intervalId = setInterval(this.storeImpressionCounts.bind(this), this.refreshRate);
36
+ };
37
+ ImpressionCountsCachePluggable.prototype.stop = function () {
38
+ clearInterval(this.intervalId);
39
+ return this.storeImpressionCounts();
40
+ };
41
+ // Async consumer API, used by synchronizer
42
+ ImpressionCountsCachePluggable.prototype.getImpressionsCount = function () {
43
+ var _this = this;
44
+ return this.wrapper.getKeysByPrefix(this.key)
45
+ .then(function (keys) {
46
+ return keys.length ? Promise.all(keys.map(function (key) { return _this.wrapper.get(key); }))
47
+ .then(function (counts) {
48
+ keys.forEach(function (key) { return _this.wrapper.del(key).catch(function () { }); });
49
+ var pf = [];
50
+ for (var i = 0; i < keys.length; i++) {
51
+ var key = keys[i];
52
+ var count = counts[i];
53
+ var keyFeatureNameAndTime = key.split('::');
54
+ if (keyFeatureNameAndTime.length !== 3) {
55
+ _this.log.error(constants_2.LOG_PREFIX + "Error spliting key " + key);
56
+ continue;
57
+ }
58
+ var timeFrame = parseInt(keyFeatureNameAndTime[2]);
59
+ if (isNaN(timeFrame)) {
60
+ _this.log.error(constants_2.LOG_PREFIX + "Error parsing time frame " + keyFeatureNameAndTime[2]);
61
+ continue;
62
+ }
63
+ // @ts-ignore
64
+ var rawCount = parseInt(count);
65
+ if (isNaN(rawCount)) {
66
+ _this.log.error(constants_2.LOG_PREFIX + "Error parsing raw count " + count);
67
+ continue;
68
+ }
69
+ pf.push({
70
+ f: keyFeatureNameAndTime[1],
71
+ m: timeFrame,
72
+ rc: rawCount,
73
+ });
74
+ }
75
+ return { pf: pf };
76
+ }) : undefined;
77
+ });
78
+ };
79
+ return ImpressionCountsCachePluggable;
80
+ }(ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory));
81
+ exports.ImpressionCountsCachePluggable = ImpressionCountsCachePluggable;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ImpressionsCachePluggable = void 0;
4
+ var utils_1 = require("../utils");
4
5
  var ImpressionsCachePluggable = /** @class */ (function () {
5
6
  function ImpressionsCachePluggable(log, key, wrapper, metadata) {
6
7
  this.log = log;
@@ -15,25 +16,7 @@ var ImpressionsCachePluggable = /** @class */ (function () {
15
16
  * or rejected if the wrapper operation fails.
16
17
  */
17
18
  ImpressionsCachePluggable.prototype.track = function (impressions) {
18
- return this.wrapper.pushItems(this.key, this._toJSON(impressions));
19
- };
20
- ImpressionsCachePluggable.prototype._toJSON = function (impressions) {
21
- var _this = this;
22
- return impressions.map(function (impression) {
23
- var keyName = impression.keyName, bucketingKey = impression.bucketingKey, feature = impression.feature, treatment = impression.treatment, label = impression.label, time = impression.time, changeNumber = impression.changeNumber;
24
- return JSON.stringify({
25
- m: _this.metadata,
26
- i: {
27
- k: keyName,
28
- b: bucketingKey,
29
- f: feature,
30
- t: treatment,
31
- r: label,
32
- c: changeNumber,
33
- m: time
34
- }
35
- });
36
- });
19
+ return this.wrapper.pushItems(this.key, (0, utils_1.impressionsToJSON)(impressions, this.metadata));
37
20
  };
38
21
  /**
39
22
  * Returns a promise that resolves with the count of stored impressions, or 0 if there was some error.