@splitsoftware/splitio-commons 1.6.2-rc.1 → 1.6.2-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/CHANGES.txt +4 -0
  2. package/cjs/consent/sdkUserConsent.js +2 -2
  3. package/cjs/evaluator/index.js +15 -16
  4. package/cjs/integrations/ga/GaToSplit.js +8 -5
  5. package/cjs/sdkClient/client.js +19 -7
  6. package/cjs/sdkClient/sdkClient.js +3 -1
  7. package/cjs/sdkFactory/index.js +15 -6
  8. package/cjs/sdkManager/index.js +3 -11
  9. package/cjs/services/splitApi.js +6 -6
  10. package/cjs/storages/AbstractSplitsCacheAsync.js +8 -10
  11. package/cjs/storages/AbstractSplitsCacheSync.js +8 -10
  12. package/cjs/storages/KeyBuilderSS.js +54 -9
  13. package/cjs/storages/dataLoader.js +1 -1
  14. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +5 -7
  15. package/cjs/storages/inLocalStorage/index.js +5 -1
  16. package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +12 -1
  17. package/cjs/storages/inMemory/InMemoryStorage.js +6 -2
  18. package/cjs/storages/inMemory/InMemoryStorageCS.js +6 -2
  19. package/cjs/storages/inMemory/SplitsCacheInMemory.js +7 -10
  20. package/cjs/storages/inMemory/TelemetryCacheInMemory.js +10 -5
  21. package/cjs/storages/inMemory/UniqueKeysCacheInMemory.js +73 -0
  22. package/cjs/storages/inMemory/UniqueKeysCacheInMemoryCS.js +78 -0
  23. package/cjs/storages/inRedis/EventsCacheInRedis.js +1 -1
  24. package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +50 -0
  25. package/cjs/storages/inRedis/SplitsCacheInRedis.js +15 -9
  26. package/cjs/storages/inRedis/TelemetryCacheInRedis.js +100 -0
  27. package/cjs/storages/inRedis/UniqueKeysCacheInRedis.js +59 -0
  28. package/cjs/storages/inRedis/constants.js +4 -1
  29. package/cjs/storages/inRedis/index.js +17 -2
  30. package/cjs/storages/pluggable/ImpressionCountsCachePluggable.js +43 -0
  31. package/cjs/storages/pluggable/SplitsCachePluggable.js +14 -9
  32. package/cjs/storages/pluggable/TelemetryCachePluggable.js +126 -0
  33. package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +50 -0
  34. package/cjs/storages/pluggable/index.js +42 -17
  35. package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
  36. package/cjs/sync/polling/updaters/splitChangesUpdater.js +1 -1
  37. package/cjs/sync/submitters/telemetrySubmitter.js +8 -4
  38. package/cjs/sync/submitters/uniqueKeysSubmitter.js +16 -59
  39. package/cjs/trackers/impressionsTracker.js +17 -15
  40. package/cjs/trackers/strategy/strategyNone.js +1 -1
  41. package/cjs/trackers/strategy/strategyOptimized.js +2 -1
  42. package/cjs/trackers/telemetryTracker.js +6 -0
  43. package/cjs/trackers/uniqueKeysTracker.js +11 -42
  44. package/cjs/utils/constants/index.js +3 -2
  45. package/cjs/utils/lang/maps.js +15 -7
  46. package/cjs/utils/redis/RedisMock.js +31 -0
  47. package/cjs/utils/settingsValidation/index.js +0 -3
  48. package/esm/consent/sdkUserConsent.js +2 -2
  49. package/esm/evaluator/index.js +15 -16
  50. package/esm/integrations/ga/GaToSplit.js +8 -5
  51. package/esm/sdkClient/client.js +19 -7
  52. package/esm/sdkClient/sdkClient.js +3 -1
  53. package/esm/sdkFactory/index.js +16 -7
  54. package/esm/sdkManager/index.js +3 -11
  55. package/esm/services/splitApi.js +6 -6
  56. package/esm/storages/AbstractSplitsCacheAsync.js +8 -10
  57. package/esm/storages/AbstractSplitsCacheSync.js +8 -10
  58. package/esm/storages/KeyBuilderSS.js +50 -8
  59. package/esm/storages/dataLoader.js +1 -1
  60. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +5 -7
  61. package/esm/storages/inLocalStorage/index.js +6 -2
  62. package/esm/storages/inMemory/ImpressionCountsCacheInMemory.js +12 -1
  63. package/esm/storages/inMemory/InMemoryStorage.js +8 -4
  64. package/esm/storages/inMemory/InMemoryStorageCS.js +7 -3
  65. package/esm/storages/inMemory/SplitsCacheInMemory.js +7 -10
  66. package/esm/storages/inMemory/TelemetryCacheInMemory.js +9 -5
  67. package/esm/storages/inMemory/UniqueKeysCacheInMemory.js +70 -0
  68. package/esm/storages/inMemory/UniqueKeysCacheInMemoryCS.js +75 -0
  69. package/esm/storages/inRedis/EventsCacheInRedis.js +1 -1
  70. package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +47 -0
  71. package/esm/storages/inRedis/SplitsCacheInRedis.js +15 -9
  72. package/esm/storages/inRedis/TelemetryCacheInRedis.js +100 -0
  73. package/esm/storages/inRedis/UniqueKeysCacheInRedis.js +56 -0
  74. package/esm/storages/inRedis/constants.js +3 -0
  75. package/esm/storages/inRedis/index.js +18 -3
  76. package/esm/storages/pluggable/ImpressionCountsCachePluggable.js +40 -0
  77. package/esm/storages/pluggable/SplitsCachePluggable.js +14 -9
  78. package/esm/storages/pluggable/TelemetryCachePluggable.js +126 -0
  79. package/esm/storages/pluggable/UniqueKeysCachePluggable.js +47 -0
  80. package/esm/storages/pluggable/index.js +43 -18
  81. package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +2 -3
  82. package/esm/sync/polling/updaters/splitChangesUpdater.js +1 -1
  83. package/esm/sync/submitters/telemetrySubmitter.js +9 -5
  84. package/esm/sync/submitters/uniqueKeysSubmitter.js +15 -56
  85. package/esm/trackers/impressionsTracker.js +17 -15
  86. package/esm/trackers/strategy/strategyNone.js +1 -1
  87. package/esm/trackers/strategy/strategyOptimized.js +2 -1
  88. package/esm/trackers/telemetryTracker.js +6 -0
  89. package/esm/trackers/uniqueKeysTracker.js +11 -42
  90. package/esm/utils/constants/index.js +1 -0
  91. package/esm/utils/lang/maps.js +15 -7
  92. package/esm/utils/redis/RedisMock.js +28 -0
  93. package/esm/utils/settingsValidation/index.js +0 -3
  94. package/package.json +1 -2
  95. package/src/consent/sdkUserConsent.ts +2 -2
  96. package/src/evaluator/index.ts +14 -15
  97. package/src/integrations/ga/GaToSplit.ts +9 -5
  98. package/src/integrations/types.ts +2 -1
  99. package/src/logger/.DS_Store +0 -0
  100. package/src/sdkClient/client.ts +21 -8
  101. package/src/sdkClient/sdkClient.ts +3 -1
  102. package/src/sdkFactory/index.ts +17 -7
  103. package/src/sdkManager/index.ts +3 -12
  104. package/src/services/splitApi.ts +6 -6
  105. package/src/services/types.ts +2 -2
  106. package/src/storages/AbstractSplitsCacheAsync.ts +13 -15
  107. package/src/storages/AbstractSplitsCacheSync.ts +15 -17
  108. package/src/storages/KeyBuilderSS.ts +61 -9
  109. package/src/storages/dataLoader.ts +1 -1
  110. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +8 -11
  111. package/src/storages/inLocalStorage/index.ts +5 -2
  112. package/src/storages/inMemory/ImpressionCountsCacheInMemory.ts +16 -1
  113. package/src/storages/inMemory/InMemoryStorage.ts +7 -4
  114. package/src/storages/inMemory/InMemoryStorageCS.ts +6 -3
  115. package/src/storages/inMemory/SplitsCacheInMemory.ts +10 -14
  116. package/src/storages/inMemory/TelemetryCacheInMemory.ts +10 -6
  117. package/src/storages/inMemory/UniqueKeysCacheInMemory.ts +82 -0
  118. package/src/storages/inMemory/UniqueKeysCacheInMemoryCS.ts +88 -0
  119. package/src/storages/inRedis/EventsCacheInRedis.ts +1 -1
  120. package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +53 -0
  121. package/src/storages/inRedis/SplitsCacheInRedis.ts +21 -17
  122. package/src/storages/inRedis/TelemetryCacheInRedis.ts +122 -2
  123. package/src/storages/inRedis/UniqueKeysCacheInRedis.ts +65 -0
  124. package/src/storages/inRedis/constants.ts +3 -0
  125. package/src/storages/inRedis/index.ts +15 -5
  126. package/src/storages/pluggable/ImpressionCountsCachePluggable.ts +47 -0
  127. package/src/storages/pluggable/SplitsCachePluggable.ts +20 -17
  128. package/src/storages/pluggable/TelemetryCachePluggable.ts +147 -2
  129. package/src/storages/pluggable/UniqueKeysCachePluggable.ts +56 -0
  130. package/src/storages/pluggable/index.ts +44 -19
  131. package/src/storages/types.ts +38 -30
  132. package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +5 -6
  133. package/src/sync/polling/updaters/splitChangesUpdater.ts +2 -2
  134. package/src/sync/submitters/telemetrySubmitter.ts +15 -8
  135. package/src/sync/submitters/types.ts +18 -6
  136. package/src/sync/submitters/uniqueKeysSubmitter.ts +18 -61
  137. package/src/trackers/impressionsTracker.ts +16 -15
  138. package/src/trackers/strategy/strategyNone.ts +1 -1
  139. package/src/trackers/strategy/strategyOptimized.ts +1 -1
  140. package/src/trackers/telemetryTracker.ts +7 -2
  141. package/src/trackers/types.ts +9 -7
  142. package/src/trackers/uniqueKeysTracker.ts +15 -47
  143. package/src/types.ts +0 -1
  144. package/src/utils/constants/index.ts +1 -0
  145. package/src/utils/lang/maps.ts +20 -8
  146. package/src/utils/redis/RedisMock.ts +33 -0
  147. package/src/utils/settingsValidation/index.ts +1 -4
  148. package/types/integrations/types.d.ts +2 -1
  149. package/types/services/types.d.ts +2 -2
  150. package/types/storages/AbstractSplitsCacheAsync.d.ts +7 -6
  151. package/types/storages/AbstractSplitsCacheSync.d.ts +6 -6
  152. package/types/storages/KeyBuilderSS.d.ts +9 -2
  153. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +3 -4
  154. package/types/storages/inMemory/ImpressionCountsCacheInMemory.d.ts +5 -1
  155. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +3 -2
  156. package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +6 -3
  157. package/types/storages/inMemory/uniqueKeysCacheInMemory.d.ts +35 -0
  158. package/types/storages/inMemory/uniqueKeysCacheInMemoryCS.d.ts +37 -0
  159. package/types/storages/inRedis/EventsCacheInRedis.d.ts +1 -1
  160. package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +14 -0
  161. package/types/storages/inRedis/SplitsCacheInRedis.d.ts +6 -5
  162. package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +16 -1
  163. package/types/storages/inRedis/constants.d.ts +3 -0
  164. package/types/storages/inRedis/uniqueKeysCacheInRedis.d.ts +15 -0
  165. package/types/storages/pluggable/ImpressionCountsCachePluggable.d.ts +14 -0
  166. package/types/storages/pluggable/SplitsCachePluggable.d.ts +6 -5
  167. package/types/storages/pluggable/TelemetryCachePluggable.d.ts +17 -1
  168. package/types/storages/pluggable/UniqueKeysCachePluggable.d.ts +14 -0
  169. package/types/storages/types.d.ts +35 -35
  170. package/types/sync/polling/updaters/splitChangesUpdater.d.ts +1 -1
  171. package/types/sync/submitters/telemetrySubmitter.d.ts +1 -1
  172. package/types/sync/submitters/types.d.ts +12 -6
  173. package/types/sync/submitters/uniqueKeysSubmitter.d.ts +0 -14
  174. package/types/trackers/types.d.ts +9 -11
  175. package/types/trackers/uniqueKeysTracker.d.ts +3 -3
  176. package/types/types.d.ts +0 -1
  177. package/types/utils/constants/index.d.ts +1 -0
  178. package/types/utils/lang/maps.d.ts +6 -2
  179. package/types/utils/redis/RedisMock.d.ts +4 -0
  180. package/types/utils/settingsValidation/index.d.ts +0 -1
  181. package/types/sdkClient/types.d.ts +0 -18
  182. package/types/storages/inMemory/CountsCacheInMemory.d.ts +0 -20
  183. package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +0 -20
  184. package/types/storages/inRedis/CountsCacheInRedis.d.ts +0 -9
  185. package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +0 -9
  186. package/types/sync/offline/LocalhostFromFile.d.ts +0 -2
  187. package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +0 -2
  188. package/types/sync/submitters/eventsSyncTask.d.ts +0 -8
  189. package/types/sync/submitters/impressionCountsSyncTask.d.ts +0 -13
  190. package/types/sync/submitters/impressionsSyncTask.d.ts +0 -14
  191. package/types/sync/submitters/metricsSyncTask.d.ts +0 -12
  192. package/types/sync/submitters/submitterSyncTask.d.ts +0 -10
  193. package/types/sync/syncTaskComposite.d.ts +0 -5
  194. package/types/trackers/filter/bloomFilter.d.ts +0 -10
  195. package/types/trackers/filter/dictionaryFilter.d.ts +0 -8
  196. package/types/trackers/filter/types.d.ts +0 -5
  197. package/types/utils/timeTracker/index.d.ts +0 -70
@@ -0,0 +1,43 @@
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
+ return ImpressionCountsCachePluggable;
42
+ }(ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory));
43
+ exports.ImpressionCountsCachePluggable = ImpressionCountsCachePluggable;
@@ -49,17 +49,17 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
49
49
  var splitKey = this.keys.buildSplitKey(name);
50
50
  return this.wrapper.get(splitKey).then(function (splitFromStorage) {
51
51
  // handling parsing error
52
- var parsedPreviousSplit, parsedSplit;
52
+ var parsedPreviousSplit, stringifiedNewSplit;
53
53
  try {
54
54
  parsedPreviousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : undefined;
55
- parsedSplit = JSON.parse(split);
55
+ stringifiedNewSplit = JSON.stringify(split);
56
56
  }
57
57
  catch (e) {
58
58
  throw new Error('Error parsing split definition: ' + e);
59
59
  }
60
60
  return Promise.all([
61
- _this.wrapper.set(splitKey, split),
62
- _this._incrementCounts(parsedSplit),
61
+ _this.wrapper.set(splitKey, stringifiedNewSplit),
62
+ _this._incrementCounts(split),
63
63
  // If it's an update, we decrement the traffic type and segment count of the existing split,
64
64
  parsedPreviousSplit && _this._decrementCounts(parsedPreviousSplit)
65
65
  ]);
@@ -83,8 +83,7 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
83
83
  var _this = this;
84
84
  return this.getSplit(name).then(function (split) {
85
85
  if (split) {
86
- var parsedSplit = JSON.parse(split);
87
- _this._decrementCounts(parsedSplit);
86
+ _this._decrementCounts(split);
88
87
  }
89
88
  return _this.wrapper.del(_this.keys.buildSplitKey(name));
90
89
  });
@@ -104,7 +103,8 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
104
103
  * or rejected if wrapper operation fails.
105
104
  */
106
105
  SplitsCachePluggable.prototype.getSplit = function (name) {
107
- return this.wrapper.get(this.keys.buildSplitKey(name));
106
+ return this.wrapper.get(this.keys.buildSplitKey(name))
107
+ .then(function (maybeSplit) { return maybeSplit && JSON.parse(maybeSplit); });
108
108
  };
109
109
  /**
110
110
  * Get list of splits.
@@ -117,7 +117,8 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
117
117
  return this.wrapper.getMany(keys).then(function (splitDefinitions) {
118
118
  var splits = {};
119
119
  names.forEach(function (name, idx) {
120
- splits[name] = splitDefinitions[idx];
120
+ var split = splitDefinitions[idx];
121
+ splits[name] = split && JSON.parse(split);
121
122
  });
122
123
  return Promise.resolve(splits);
123
124
  });
@@ -129,7 +130,11 @@ var SplitsCachePluggable = /** @class */ (function (_super) {
129
130
  */
130
131
  SplitsCachePluggable.prototype.getAll = function () {
131
132
  var _this = this;
132
- return this.wrapper.getKeysByPrefix(this.keys.buildSplitKeyPrefix()).then(function (listOfKeys) { return Promise.all(listOfKeys.map(_this.wrapper.get)); });
133
+ return this.wrapper.getKeysByPrefix(this.keys.buildSplitKeyPrefix())
134
+ .then(function (listOfKeys) { return _this.wrapper.getMany(listOfKeys); })
135
+ .then(function (splitDefinitions) { return splitDefinitions.map(function (splitDefinition) {
136
+ return JSON.parse(splitDefinition);
137
+ }); });
133
138
  };
134
139
  /**
135
140
  * Get list of split names.
@@ -1,7 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TelemetryCachePluggable = void 0;
4
+ var KeyBuilderSS_1 = require("../KeyBuilderSS");
4
5
  var findLatencyIndex_1 = require("../findLatencyIndex");
6
+ var telemetrySubmitter_1 = require("../../sync/submitters/telemetrySubmitter");
7
+ var constants_1 = require("../../utils/constants");
8
+ var lang_1 = require("../../utils/lang");
9
+ var maps_1 = require("../../utils/lang/maps");
10
+ var TelemetryCacheInMemory_1 = require("../inMemory/TelemetryCacheInMemory");
5
11
  var TelemetryCachePluggable = /** @class */ (function () {
6
12
  /**
7
13
  * Create a Telemetry cache that uses a storage wrapper.
@@ -22,6 +28,126 @@ var TelemetryCachePluggable = /** @class */ (function () {
22
28
  return this.wrapper.incr(this.keys.buildExceptionKey(method))
23
29
  .catch(function () { });
24
30
  };
31
+ TelemetryCachePluggable.prototype.recordConfig = function () {
32
+ var value = JSON.stringify((0, telemetrySubmitter_1.getTelemetryConfigStats)(constants_1.CONSUMER_MODE, constants_1.STORAGE_PLUGGABLE));
33
+ return this.wrapper.set(this.keys.buildInitKey(), value).catch(function () { });
34
+ };
35
+ /**
36
+ * Pop telemetry latencies.
37
+ * The returned promise rejects if wrapper operations fail.
38
+ */
39
+ TelemetryCachePluggable.prototype.popLatencies = function () {
40
+ var _this = this;
41
+ return this.wrapper.getKeysByPrefix(this.keys.latencyPrefix).then(function (latencyKeys) {
42
+ return latencyKeys.length ?
43
+ _this.wrapper.getMany(latencyKeys).then(function (latencies) {
44
+ var result = new maps_1._Map();
45
+ for (var i = 0; i < latencyKeys.length; i++) {
46
+ var field = latencyKeys[i].split('::')[1];
47
+ var parsedField = (0, KeyBuilderSS_1.parseLatencyField)(field);
48
+ if ((0, lang_1.isString)(parsedField)) {
49
+ _this.log.error("Ignoring invalid latency field: " + field + ": " + parsedField);
50
+ continue;
51
+ }
52
+ // @ts-ignore
53
+ var count = parseInt(latencies[i]);
54
+ if ((0, lang_1.isNaNNumber)(count)) {
55
+ _this.log.error("Ignoring latency with invalid count: " + latencies[i]);
56
+ continue;
57
+ }
58
+ var metadata = parsedField[0], method = parsedField[1], bucket = parsedField[2];
59
+ if (bucket >= TelemetryCacheInMemory_1.MAX_LATENCY_BUCKET_COUNT) {
60
+ _this.log.error("Ignoring latency with invalid bucket: " + bucket);
61
+ continue;
62
+ }
63
+ if (!result.has(metadata))
64
+ result.set(metadata, {
65
+ t: (0, TelemetryCacheInMemory_1.newBuckets)(),
66
+ ts: (0, TelemetryCacheInMemory_1.newBuckets)(),
67
+ tc: (0, TelemetryCacheInMemory_1.newBuckets)(),
68
+ tcs: (0, TelemetryCacheInMemory_1.newBuckets)(),
69
+ tr: (0, TelemetryCacheInMemory_1.newBuckets)(),
70
+ });
71
+ result.get(metadata)[method][bucket] = count;
72
+ }
73
+ return Promise.all(latencyKeys.map(function (latencyKey) { return _this.wrapper.del(latencyKey); })).then(function () { return result; });
74
+ }) :
75
+ // If latencyKeys is empty, return an empty map.
76
+ new maps_1._Map();
77
+ });
78
+ };
79
+ /**
80
+ * Pop telemetry exceptions.
81
+ * The returned promise rejects if wrapper operations fail.
82
+ */
83
+ TelemetryCachePluggable.prototype.popExceptions = function () {
84
+ var _this = this;
85
+ return this.wrapper.getKeysByPrefix(this.keys.exceptionPrefix).then(function (exceptionKeys) {
86
+ return exceptionKeys.length ?
87
+ _this.wrapper.getMany(exceptionKeys).then(function (exceptions) {
88
+ var result = new maps_1._Map();
89
+ for (var i = 0; i < exceptionKeys.length; i++) {
90
+ var field = exceptionKeys[i].split('::')[1];
91
+ var parsedField = (0, KeyBuilderSS_1.parseExceptionField)(field);
92
+ if ((0, lang_1.isString)(parsedField)) {
93
+ _this.log.error("Ignoring invalid exception field: " + field + ": " + parsedField);
94
+ continue;
95
+ }
96
+ // @ts-ignore
97
+ var count = parseInt(exceptions[i]);
98
+ if ((0, lang_1.isNaNNumber)(count)) {
99
+ _this.log.error("Ignoring exception with invalid count: " + exceptions[i]);
100
+ continue;
101
+ }
102
+ var metadata = parsedField[0], method = parsedField[1];
103
+ if (!result.has(metadata))
104
+ result.set(metadata, {
105
+ t: 0,
106
+ ts: 0,
107
+ tc: 0,
108
+ tcs: 0,
109
+ tr: 0,
110
+ });
111
+ result.get(metadata)[method] = count;
112
+ }
113
+ return Promise.all(exceptionKeys.map(function (exceptionKey) { return _this.wrapper.del(exceptionKey); })).then(function () { return result; });
114
+ }) :
115
+ // If exceptionKeys is empty, return an empty map.
116
+ new maps_1._Map();
117
+ });
118
+ };
119
+ /**
120
+ * Pop telemetry configs.
121
+ * The returned promise rejects if wrapper operations fail.
122
+ */
123
+ TelemetryCachePluggable.prototype.popConfigs = function () {
124
+ var _this = this;
125
+ return this.wrapper.getKeysByPrefix(this.keys.initPrefix).then(function (configKeys) {
126
+ return configKeys.length ?
127
+ _this.wrapper.getMany(configKeys).then(function (configs) {
128
+ var result = new maps_1._Map();
129
+ for (var i = 0; i < configKeys.length; i++) {
130
+ var field = configKeys[i].split('::')[1];
131
+ var parsedField = (0, KeyBuilderSS_1.parseMetadata)(field);
132
+ if ((0, lang_1.isString)(parsedField)) {
133
+ _this.log.error("Ignoring invalid config field: " + field + ": " + parsedField);
134
+ continue;
135
+ }
136
+ var metadata = parsedField[0];
137
+ try { // @ts-ignore
138
+ var config = JSON.parse(configs[i]);
139
+ result.set(metadata, config);
140
+ }
141
+ catch (e) {
142
+ _this.log.error("Ignoring invalid config: " + configs[i]);
143
+ }
144
+ }
145
+ return Promise.all(configKeys.map(function (configKey) { return _this.wrapper.del(configKey); })).then(function () { return result; });
146
+ }) :
147
+ // If configKeys is empty, return an empty map.
148
+ new maps_1._Map();
149
+ });
150
+ };
25
151
  return TelemetryCachePluggable;
26
152
  }());
27
153
  exports.TelemetryCachePluggable = TelemetryCachePluggable;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UniqueKeysCachePluggable = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var UniqueKeysCacheInMemory_1 = require("../inMemory/UniqueKeysCacheInMemory");
6
+ var sets_1 = require("../../utils/lang/sets");
7
+ var constants_1 = require("../inRedis/constants");
8
+ var constants_2 = require("./constants");
9
+ var UniqueKeysCachePluggable = /** @class */ (function (_super) {
10
+ (0, tslib_1.__extends)(UniqueKeysCachePluggable, _super);
11
+ function UniqueKeysCachePluggable(log, key, wrapper, uniqueKeysQueueSize, refreshRate) {
12
+ if (uniqueKeysQueueSize === void 0) { uniqueKeysQueueSize = constants_1.DEFAULT_CACHE_SIZE; }
13
+ if (refreshRate === void 0) { refreshRate = constants_1.REFRESH_RATE; }
14
+ var _this = _super.call(this, uniqueKeysQueueSize) || this;
15
+ _this.log = log;
16
+ _this.key = key;
17
+ _this.wrapper = wrapper;
18
+ _this.refreshRate = refreshRate;
19
+ _this.onFullQueue = function () { _this.storeUniqueKeys(); };
20
+ return _this;
21
+ }
22
+ UniqueKeysCachePluggable.prototype.storeUniqueKeys = function () {
23
+ var _this = this;
24
+ var featureNames = Object.keys(this.uniqueKeysTracker);
25
+ if (!featureNames.length)
26
+ return Promise.resolve(false);
27
+ var pipeline = featureNames.reduce(function (pipeline, featureName) {
28
+ var featureKeys = (0, sets_1.setToArray)(_this.uniqueKeysTracker[featureName]);
29
+ var uniqueKeysPayload = {
30
+ f: featureName,
31
+ ks: featureKeys
32
+ };
33
+ return pipeline.then(function () { return _this.wrapper.pushItems(_this.key, [JSON.stringify(uniqueKeysPayload)]); });
34
+ }, Promise.resolve());
35
+ this.clear();
36
+ return pipeline.catch(function (err) {
37
+ _this.log.error(constants_2.LOG_PREFIX + "Error in uniqueKeys pipeline: " + err + ".");
38
+ return false;
39
+ });
40
+ };
41
+ UniqueKeysCachePluggable.prototype.start = function () {
42
+ this.intervalId = setInterval(this.storeUniqueKeys.bind(this), this.refreshRate);
43
+ };
44
+ UniqueKeysCachePluggable.prototype.stop = function () {
45
+ clearInterval(this.intervalId);
46
+ return this.storeUniqueKeys();
47
+ };
48
+ return UniqueKeysCachePluggable;
49
+ }(UniqueKeysCacheInMemory_1.UniqueKeysCacheInMemory));
50
+ exports.UniqueKeysCachePluggable = UniqueKeysCachePluggable;
@@ -14,6 +14,12 @@ var constants_1 = require("../../utils/constants");
14
14
  var ImpressionsCacheInMemory_1 = require("../inMemory/ImpressionsCacheInMemory");
15
15
  var EventsCacheInMemory_1 = require("../inMemory/EventsCacheInMemory");
16
16
  var ImpressionCountsCacheInMemory_1 = require("../inMemory/ImpressionCountsCacheInMemory");
17
+ var TelemetryCacheInMemory_1 = require("../inMemory/TelemetryCacheInMemory");
18
+ var TelemetryCachePluggable_1 = require("./TelemetryCachePluggable");
19
+ var ImpressionCountsCachePluggable_1 = require("./ImpressionCountsCachePluggable");
20
+ var UniqueKeysCachePluggable_1 = require("./UniqueKeysCachePluggable");
21
+ var UniqueKeysCacheInMemory_1 = require("../inMemory/UniqueKeysCacheInMemory");
22
+ var UniqueKeysCacheInMemoryCS_1 = require("../inMemory/UniqueKeysCacheInMemoryCS");
17
23
  var NO_VALID_WRAPPER = 'Expecting pluggable storage `wrapper` in options, but no valid wrapper instance was provided.';
18
24
  var NO_VALID_WRAPPER_INTERFACE = 'The provided wrapper instance doesn’t follow the expected interface. Check our docs.';
19
25
  /**
@@ -30,15 +36,6 @@ function validatePluggableStorageOptions(options) {
30
36
  if (missingMethods.length)
31
37
  throw new Error(NO_VALID_WRAPPER_INTERFACE + " The following methods are missing or invalid: " + missingMethods);
32
38
  }
33
- // subscription to wrapper connect event in order to emit SDK_READY event
34
- function wrapperConnect(wrapper, onReadyCb) {
35
- wrapper.connect().then(function () {
36
- onReadyCb();
37
- // At the moment, we don't synchronize config with pluggable storage
38
- }).catch(function (e) {
39
- onReadyCb(e || new Error('Error connecting wrapper'));
40
- });
41
- }
42
39
  // Async return type in `client.track` method on consumer partial mode
43
40
  // No need to promisify impressions cache
44
41
  function promisifyEventsTrack(events) {
@@ -54,28 +51,56 @@ function promisifyEventsTrack(events) {
54
51
  function PluggableStorage(options) {
55
52
  validatePluggableStorageOptions(options);
56
53
  var prefix = (0, KeyBuilder_1.validatePrefix)(options.prefix);
57
- function PluggableStorageFactory(_a) {
58
- var log = _a.log, metadata = _a.metadata, onReadyCb = _a.onReadyCb, mode = _a.mode, eventsQueueSize = _a.eventsQueueSize, impressionsQueueSize = _a.impressionsQueueSize, optimize = _a.optimize;
54
+ function PluggableStorageFactory(params) {
55
+ var log = params.log, metadata = params.metadata, onReadyCb = params.onReadyCb, mode = params.mode, eventsQueueSize = params.eventsQueueSize, impressionsQueueSize = params.impressionsQueueSize, impressionsMode = params.impressionsMode, matchingKey = params.matchingKey;
59
56
  var keys = new KeyBuilderSS_1.KeyBuilderSS(prefix, metadata);
60
57
  var wrapper = (0, wrapperAdapter_1.wrapperAdapter)(log, options.wrapper);
61
58
  var isPartialConsumer = mode === constants_1.CONSUMER_PARTIAL_MODE;
59
+ var telemetry = (0, TelemetryCacheInMemory_1.shouldRecordTelemetry)(params) ?
60
+ isPartialConsumer ? new TelemetryCacheInMemory_1.TelemetryCacheInMemory() : new TelemetryCachePluggable_1.TelemetryCachePluggable(log, keys, wrapper) :
61
+ undefined;
62
+ var impressionCountsCache = impressionsMode !== constants_1.DEBUG ?
63
+ isPartialConsumer ? new ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory() : new ImpressionCountsCachePluggable_1.ImpressionCountsCachePluggable(log, keys.buildImpressionsCountKey(), wrapper) :
64
+ undefined;
65
+ var uniqueKeysCache = impressionsMode === constants_1.NONE ?
66
+ isPartialConsumer ?
67
+ matchingKey === undefined ? new UniqueKeysCacheInMemory_1.UniqueKeysCacheInMemory() : new UniqueKeysCacheInMemoryCS_1.UniqueKeysCacheInMemoryCS() :
68
+ new UniqueKeysCachePluggable_1.UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper) :
69
+ undefined;
62
70
  // Connects to wrapper and emits SDK_READY event on main client
63
- wrapperConnect(wrapper, onReadyCb);
71
+ var connectPromise = wrapper.connect().then(function () {
72
+ onReadyCb();
73
+ // Start periodic flush of async storages
74
+ if (impressionCountsCache && impressionCountsCache.start)
75
+ impressionCountsCache.start();
76
+ if (uniqueKeysCache && uniqueKeysCache.start)
77
+ uniqueKeysCache.start();
78
+ // If mode is not defined, it means that the synchronizer is running and so we don't have to record telemetry
79
+ if (telemetry && telemetry.recordConfig && mode)
80
+ telemetry.recordConfig();
81
+ }).catch(function (e) {
82
+ e = e || new Error('Error connecting wrapper');
83
+ onReadyCb(e);
84
+ return e;
85
+ });
64
86
  return {
65
87
  splits: new SplitsCachePluggable_1.SplitsCachePluggable(log, keys, wrapper),
66
88
  segments: new SegmentsCachePluggable_1.SegmentsCachePluggable(log, keys, wrapper),
67
89
  impressions: isPartialConsumer ? new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable_1.ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
68
- impressionCounts: optimize ? new ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory() : undefined,
90
+ impressionCounts: impressionCountsCache,
69
91
  events: isPartialConsumer ? promisifyEventsTrack(new EventsCacheInMemory_1.EventsCacheInMemory(eventsQueueSize)) : new EventsCachePluggable_1.EventsCachePluggable(log, keys.buildEventsKey(), wrapper, metadata),
70
- // @TODO Not using TelemetryCachePluggable yet because it's not supported by the Split Synchronizer, and needs to drop or queue operations while the wrapper is not ready
71
- // telemetry: isPartialConsumer ? new TelemetryCacheInMemory() : new TelemetryCachePluggable(log, keys, wrapper),
92
+ telemetry: telemetry,
93
+ uniqueKeys: uniqueKeysCache,
72
94
  // Disconnect the underlying storage
73
95
  destroy: function () {
74
- return wrapper.disconnect();
96
+ return Promise.all([
97
+ impressionCountsCache && impressionCountsCache.stop && impressionCountsCache.stop(),
98
+ uniqueKeysCache && uniqueKeysCache.stop && uniqueKeysCache.stop(),
99
+ ]).then(function () { return wrapper.disconnect(); });
75
100
  },
76
101
  // emits SDK_READY event on shared clients and returns a reference to the storage
77
102
  shared: function (_, onReadyCb) {
78
- wrapperConnect(wrapper, onReadyCb);
103
+ connectPromise.then(onReadyCb);
79
104
  return (0, tslib_1.__assign)((0, tslib_1.__assign)({}, this), {
80
105
  // no-op destroy, to disconnect the wrapper only when the main client is destroyed
81
106
  destroy: function () { } });
@@ -27,8 +27,7 @@ function fromObjectUpdaterFactory(splitsParser, storage, readiness, settings) {
27
27
  log.debug(constants_3.SYNC_OFFLINE_DATA, [JSON.stringify(splitsMock)]);
28
28
  (0, lang_1.forOwn)(splitsMock, function (val, name) {
29
29
  splits.push([
30
- name,
31
- JSON.stringify({
30
+ name, {
32
31
  name: name,
33
32
  status: 'ACTIVE',
34
33
  killed: false,
@@ -37,7 +36,7 @@ function fromObjectUpdaterFactory(splitsParser, storage, readiness, settings) {
37
36
  conditions: val.conditions || [],
38
37
  configurations: val.configurations,
39
38
  trafficTypeName: val.trafficTypeName
40
- })
39
+ }
41
40
  ]);
42
41
  });
43
42
  return Promise.all([
@@ -41,7 +41,7 @@ function computeSplitsMutation(entries) {
41
41
  var segments = new sets_1._Set();
42
42
  var computed = entries.reduce(function (accum, split) {
43
43
  if (split.status === 'ACTIVE') {
44
- accum.added.push([split.name, JSON.stringify(split)]);
44
+ accum.added.push([split.name, split]);
45
45
  parseSegments(split).forEach(function (segmentName) {
46
46
  segments.add(segmentName);
47
47
  });
@@ -9,6 +9,7 @@ var settingsValidation_1 = require("../../utils/settingsValidation");
9
9
  var apiKey_1 = require("../../utils/inputValidation/apiKey");
10
10
  var timer_1 = require("../../utils/timeTracker/timer");
11
11
  var objectAssign_1 = require("../../utils/lang/objectAssign");
12
+ var utils_1 = require("../../trackers/impressionObserver/utils");
12
13
  /**
13
14
  * Converts data from telemetry cache into /metrics/usage request payload.
14
15
  */
@@ -29,9 +30,9 @@ function telemetryCacheStatsAdapter(telemetry, splits, segments) {
29
30
  iQ: telemetry.getImpressionStats(constants_1.QUEUED),
30
31
  iDe: telemetry.getImpressionStats(constants_1.DEDUPED),
31
32
  iDr: telemetry.getImpressionStats(constants_1.DROPPED),
32
- spC: splits.getSplitNames().length,
33
- seC: segments.getRegisteredSegments().length,
34
- skC: segments.getKeysCount(),
33
+ spC: splits && splits.getSplitNames().length,
34
+ seC: segments && segments.getRegisteredSegments().length,
35
+ skC: segments && segments.getKeysCount(),
35
36
  sL: telemetry.getSessionLength(),
36
37
  eQ: telemetry.getEventStats(constants_1.QUEUED),
37
38
  eD: telemetry.getEventStats(constants_1.DROPPED),
@@ -50,6 +51,7 @@ var OPERATION_MODE_MAP = (_a = {},
50
51
  var IMPRESSIONS_MODE_MAP = (_b = {},
51
52
  _b[constants_1.OPTIMIZED] = constants_1.OPTIMIZED_ENUM,
52
53
  _b[constants_1.DEBUG] = constants_1.DEBUG_ENUM,
54
+ _b[constants_1.NONE] = constants_1.NONE_ENUM,
53
55
  _b);
54
56
  var USER_CONSENT_MAP = (_c = {},
55
57
  _c[constants_1.CONSENT_UNKNOWN] = 1,
@@ -125,7 +127,9 @@ function telemetrySubmitterFactory(params) {
125
127
  return; // No submitter created if telemetry cache is not defined
126
128
  var settings = params.settings, _b = params.settings, log = _b.log, telemetryRefreshRate = _b.scheduler.telemetryRefreshRate, splitApi = params.splitApi, readiness = params.readiness, sdkReadinessManager = params.sdkReadinessManager;
127
129
  var startTime = (0, timer_1.timer)(now);
128
- var submitter = (0, submitter_1.firstPushWindowDecorator)((0, submitter_1.submitterFactory)(log, splitApi.postMetricsUsage, telemetryCacheStatsAdapter(telemetry, splits, segments), telemetryRefreshRate, 'telemetry stats', undefined, 0, true), telemetryRefreshRate);
130
+ var submitter = (0, submitter_1.firstPushWindowDecorator)((0, submitter_1.submitterFactory)(log, splitApi.postMetricsUsage,
131
+ // @TODO cannot provide splits and segments cache if they are async, because `submitterFactory` expects a sync storage source
132
+ (0, utils_1.isStorageSync)(params.settings) ? telemetryCacheStatsAdapter(telemetry, splits, segments) : telemetryCacheStatsAdapter(telemetry), telemetryRefreshRate, 'telemetry stats', undefined, 0, true), telemetryRefreshRate);
129
133
  readiness.gate.once(constants_2.SDK_READY_FROM_CACHE, function () {
130
134
  telemetry.recordTimeUntilReadyFromCache(startTime());
131
135
  });
@@ -1,70 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uniqueKeysSubmitterFactory = exports.fromUniqueKeysCollectorSs = exports.fromUniqueKeysCollectorCs = void 0;
4
- var sets_1 = require("../../utils/lang/sets");
3
+ exports.uniqueKeysSubmitterFactory = void 0;
4
+ var constants_1 = require("../../logger/constants");
5
5
  var submitter_1 = require("./submitter");
6
- /**
7
- * Invert keys for feature to features for key
8
- */
9
- function invertUniqueKeys(uniqueKeys) {
10
- var featureNames = Object.keys(uniqueKeys);
11
- var inverted = {};
12
- for (var i = 0; i < featureNames.length; i++) {
13
- var featureName = featureNames[i];
14
- var featureKeys = (0, sets_1.setToArray)(uniqueKeys[featureName]);
15
- for (var j = 0; j < featureKeys.length; j++) {
16
- var featureKey = featureKeys[j];
17
- if (!inverted[featureKey])
18
- inverted[featureKey] = [];
19
- inverted[featureKey].push(featureName);
20
- }
21
- }
22
- return inverted;
23
- }
24
- /**
25
- * Converts `uniqueKeys` data from cache into request payload for CS.
26
- */
27
- function fromUniqueKeysCollectorCs(uniqueKeys) {
28
- var payload = [];
29
- var featuresPerKey = invertUniqueKeys(uniqueKeys);
30
- var keys = Object.keys(featuresPerKey);
31
- for (var k = 0; k < keys.length; k++) {
32
- var key = keys[k];
33
- var uniqueKeysPayload = {
34
- k: key,
35
- fs: featuresPerKey[key]
36
- };
37
- payload.push(uniqueKeysPayload);
38
- }
39
- return { keys: payload };
40
- }
41
- exports.fromUniqueKeysCollectorCs = fromUniqueKeysCollectorCs;
42
- /**
43
- * Converts `uniqueKeys` data from cache into request payload for SS.
44
- */
45
- function fromUniqueKeysCollectorSs(uniqueKeys) {
46
- var payload = [];
47
- var featureNames = Object.keys(uniqueKeys);
48
- for (var i = 0; i < featureNames.length; i++) {
49
- var featureName = featureNames[i];
50
- var featureKeys = (0, sets_1.setToArray)(uniqueKeys[featureName]);
51
- var uniqueKeysPayload = {
52
- f: featureName,
53
- ks: featureKeys
54
- };
55
- payload.push(uniqueKeysPayload);
56
- }
57
- return { keys: payload };
58
- }
59
- exports.fromUniqueKeysCollectorSs = fromUniqueKeysCollectorSs;
6
+ var DATA_NAME = 'unique keys';
7
+ var UNIQUE_KEYS_RATE = 900000; // 15 minutes
60
8
  /**
61
9
  * Submitter that periodically posts impression counts
62
10
  */
63
11
  function uniqueKeysSubmitterFactory(params) {
64
- var _a = params.settings, log = _a.log, uniqueKeysRefreshRate = _a.scheduler.uniqueKeysRefreshRate, key = _a.core.key, _b = params.splitApi, postUniqueKeysBulkCs = _b.postUniqueKeysBulkCs, postUniqueKeysBulkSs = _b.postUniqueKeysBulkSs, uniqueKeys = params.storage.uniqueKeys;
12
+ var _a = params.settings, log = _a.log, key = _a.core.key, _b = params.splitApi, postUniqueKeysBulkCs = _b.postUniqueKeysBulkCs, postUniqueKeysBulkSs = _b.postUniqueKeysBulkSs, uniqueKeys = params.storage.uniqueKeys;
65
13
  var isClientSide = key !== undefined;
66
14
  var postUniqueKeysBulk = isClientSide ? postUniqueKeysBulkCs : postUniqueKeysBulkSs;
67
- var fromUniqueKeysCollector = isClientSide ? fromUniqueKeysCollectorCs : fromUniqueKeysCollectorSs;
68
- return (0, submitter_1.submitterFactory)(log, postUniqueKeysBulk, uniqueKeys, uniqueKeysRefreshRate, 'unique keys', fromUniqueKeysCollector);
15
+ var syncTask = (0, submitter_1.submitterFactory)(log, postUniqueKeysBulk, uniqueKeys, UNIQUE_KEYS_RATE, DATA_NAME);
16
+ // register unique keys submitter to be executed when uniqueKeys cache is full
17
+ uniqueKeys.setOnFullQueueCb(function () {
18
+ if (syncTask.isRunning()) {
19
+ log.info(constants_1.SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
20
+ syncTask.execute();
21
+ }
22
+ // If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data.
23
+ // Data will be sent when submitter is resumed.
24
+ });
25
+ return syncTask;
69
26
  }
70
27
  exports.uniqueKeysSubmitterFactory = uniqueKeysSubmitterFactory;
@@ -23,21 +23,23 @@ function impressionsTrackerFactory(settings, impressionsCache, strategy, integra
23
23
  var impressionsCount = impressions.length;
24
24
  var _a = strategy.process(impressions), impressionsToStore = _a.impressionsToStore, impressionsToListener = _a.impressionsToListener, deduped = _a.deduped;
25
25
  var impressionsToListenerCount = impressionsToListener.length;
26
- var res = impressionsCache.track(impressionsToStore);
27
- // If we're on an async storage, handle error and log it.
28
- if ((0, thenable_1.thenable)(res)) {
29
- res.then(function () {
30
- log.info(constants_1.IMPRESSIONS_TRACKER_SUCCESS, [impressionsCount]);
31
- }).catch(function (err) {
32
- log.error(constants_1.ERROR_IMPRESSIONS_TRACKER, [impressionsCount, err]);
33
- });
34
- }
35
- else {
36
- // Record when impressionsCache is sync only (standalone mode)
37
- // @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
38
- if (telemetryCache) {
39
- telemetryCache.recordImpressionStats(constants_2.QUEUED, impressionsToStore.length);
40
- telemetryCache.recordImpressionStats(constants_2.DEDUPED, deduped);
26
+ if (impressionsToStore.length > 0) {
27
+ var res = impressionsCache.track(impressionsToStore);
28
+ // If we're on an async storage, handle error and log it.
29
+ if ((0, thenable_1.thenable)(res)) {
30
+ res.then(function () {
31
+ log.info(constants_1.IMPRESSIONS_TRACKER_SUCCESS, [impressionsCount]);
32
+ }).catch(function (err) {
33
+ log.error(constants_1.ERROR_IMPRESSIONS_TRACKER, [impressionsCount, err]);
34
+ });
35
+ }
36
+ else {
37
+ // Record when impressionsCache is sync only (standalone mode)
38
+ // @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
39
+ if (telemetryCache) {
40
+ telemetryCache.recordImpressionStats(constants_2.QUEUED, impressionsToStore.length);
41
+ telemetryCache.recordImpressionStats(constants_2.DEDUPED, deduped);
42
+ }
41
43
  }
42
44
  }
43
45
  // @TODO next block might be handled by the integration manager. In that case, the metadata object doesn't need to be passed in the constructor
@@ -16,7 +16,7 @@ function strategyNoneFactory(impressionsCounter, uniqueKeysTracker) {
16
16
  // Increments impression counter per featureName
17
17
  impressionsCounter.track(impression.feature, now, 1);
18
18
  // Keep track by unique key
19
- uniqueKeysTracker.track(impression.feature, impression.keyName);
19
+ uniqueKeysTracker.track(impression.keyName, impression.feature);
20
20
  });
21
21
  return {
22
22
  impressionsToStore: [],
@@ -17,7 +17,8 @@ function strategyOptimizedFactory(impressionsObserver, impressionsCounter) {
17
17
  impression.pt = impressionsObserver.testAndSet(impression);
18
18
  var now = Date.now();
19
19
  // Increments impression counter per featureName
20
- impressionsCounter.track(impression.feature, now, 1);
20
+ if (impression.pt)
21
+ impressionsCounter.track(impression.feature, now, 1);
21
22
  // Checks if the impression should be added in queue to be sent
22
23
  if (!impression.pt || impression.pt < (0, time_1.truncateTimeFrame)(now)) {
23
24
  impressionsToStore.push(impression);
@@ -49,6 +49,11 @@ function telemetryTrackerFactory(telemetryCache, now) {
49
49
  if (e === constants_1.TOKEN_REFRESH)
50
50
  telemetryCache.recordTokenRefreshes();
51
51
  }
52
+ },
53
+ addTag: function (tag) {
54
+ // @ts-ignore
55
+ if (telemetryCache.addTag)
56
+ telemetryCache.addTag(tag);
52
57
  }
53
58
  };
54
59
  }
@@ -59,6 +64,7 @@ function telemetryTrackerFactory(telemetryCache, now) {
59
64
  trackHttp: noopTrack,
60
65
  sessionLength: function () { },
61
66
  streamingEvent: function () { },
67
+ addTag: function () { }
62
68
  };
63
69
  }
64
70
  }