@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
@@ -37,13 +37,6 @@ var MapPoly = /** @class */ (function () {
37
37
  this.__mapKeysData__.length = 0;
38
38
  this.__mapValuesData__.length = 0;
39
39
  };
40
- MapPoly.prototype.set = function (key, value) {
41
- var index = this.__mapKeysData__.indexOf(key);
42
- if (index === -1)
43
- index = this.__mapKeysData__.push(key) - 1;
44
- this.__mapValuesData__[index] = value;
45
- return this;
46
- };
47
40
  MapPoly.prototype.delete = function (key) {
48
41
  var index = this.__mapKeysData__.indexOf(key);
49
42
  if (index === -1)
@@ -52,12 +45,27 @@ var MapPoly = /** @class */ (function () {
52
45
  this.__mapValuesData__.splice(index, 1);
53
46
  return true;
54
47
  };
48
+ MapPoly.prototype.forEach = function (callbackfn, thisArg) {
49
+ for (var i = 0; i < this.__mapKeysData__.length; i++) {
50
+ callbackfn.call(thisArg, this.__mapValuesData__[i], this.__mapKeysData__[i], this);
51
+ }
52
+ };
55
53
  MapPoly.prototype.get = function (key) {
56
54
  var index = this.__mapKeysData__.indexOf(key);
57
55
  if (index === -1)
58
56
  return;
59
57
  return this.__mapValuesData__[index];
60
58
  };
59
+ MapPoly.prototype.has = function (key) {
60
+ return this.__mapKeysData__.indexOf(key) !== -1;
61
+ };
62
+ MapPoly.prototype.set = function (key, value) {
63
+ var index = this.__mapKeysData__.indexOf(key);
64
+ if (index === -1)
65
+ index = this.__mapKeysData__.push(key) - 1;
66
+ this.__mapValuesData__[index] = value;
67
+ return this;
68
+ };
61
69
  Object.defineProperty(MapPoly.prototype, "size", {
62
70
  get: function () {
63
71
  return this.__mapKeysData__.length;
@@ -0,0 +1,28 @@
1
+ //@ts-nocheck
2
+ function identityFunction(data) {
3
+ return data;
4
+ }
5
+ function asyncFunction(data) {
6
+ return Promise.resolve(data);
7
+ }
8
+ var IDENTITY_METHODS = [];
9
+ var ASYNC_METHODS = ['rpush', 'hincrby'];
10
+ var PIPELINE_METHODS = ['rpush', 'hincrby'];
11
+ var RedisMock = /** @class */ (function () {
12
+ function RedisMock() {
13
+ var _this = this;
14
+ this.pipelineMethods = { exec: jest.fn(asyncFunction) };
15
+ IDENTITY_METHODS.forEach(function (method) {
16
+ _this[method] = jest.fn(identityFunction);
17
+ });
18
+ ASYNC_METHODS.forEach(function (method) {
19
+ _this[method] = jest.fn(asyncFunction);
20
+ });
21
+ PIPELINE_METHODS.forEach(function (method) {
22
+ _this.pipelineMethods[method] = _this[method];
23
+ });
24
+ this.pipeline = jest.fn(function () { return _this.pipelineMethods; });
25
+ }
26
+ return RedisMock;
27
+ }());
28
+ export { RedisMock };
@@ -31,8 +31,6 @@ export var base = {
31
31
  telemetryRefreshRate: 3600,
32
32
  // publish evaluations each 300 sec (default value for OPTIMIZED impressions mode)
33
33
  impressionsRefreshRate: 300,
34
- // publish unique Keys each 900 sec (15 min)
35
- uniqueKeysRefreshRate: 900,
36
34
  // fetch offline changes each 15 sec
37
35
  offlineRefreshRate: 15,
38
36
  // publish events every 60 seconds after the first flush
@@ -111,7 +109,6 @@ export function settingsValidation(config, validationParams) {
111
109
  scheduler.segmentsRefreshRate = fromSecondsToMillis(scheduler.segmentsRefreshRate);
112
110
  scheduler.offlineRefreshRate = fromSecondsToMillis(scheduler.offlineRefreshRate);
113
111
  scheduler.eventsPushRate = fromSecondsToMillis(scheduler.eventsPushRate);
114
- scheduler.uniqueKeysRefreshRate = fromSecondsToMillis(scheduler.uniqueKeysRefreshRate);
115
112
  scheduler.telemetryRefreshRate = fromSecondsToMillis(validateMinValue('telemetryRefreshRate', scheduler.telemetryRefreshRate, 60));
116
113
  // Default impressionsRefreshRate for DEBUG mode is 60 secs
117
114
  if (get(config, 'scheduler.impressionsRefreshRate') === undefined && withDefaults.sync.impressionsMode === DEBUG)
@@ -132,8 +129,8 @@ export function settingsValidation(config, validationParams) {
132
129
  if (storage)
133
130
  withDefaults.storage = storage(withDefaults);
134
131
  // Validate key and TT (for client-side)
132
+ var maybeKey = withDefaults.core.key;
135
133
  if (validationParams.acceptKey) {
136
- var maybeKey = withDefaults.core.key;
137
134
  // Although `key` is required in client-side, it can be omitted in LOCALHOST mode. In that case, the value `localhost_key` is used.
138
135
  if (withDefaults.mode === LOCALHOST_MODE && maybeKey === undefined) {
139
136
  withDefaults.core.key = 'localhost_key';
@@ -151,6 +148,12 @@ export function settingsValidation(config, validationParams) {
151
148
  }
152
149
  }
153
150
  }
151
+ else {
152
+ // On server-side, key is undefined and used to distinguish from client-side
153
+ if (maybeKey !== undefined)
154
+ log.warn('Provided `key` is ignored in server-side SDK.'); // @ts-ignore
155
+ withDefaults.core.key = undefined;
156
+ }
154
157
  // Current ip/hostname information
155
158
  // @ts-ignore, modify readonly prop
156
159
  withDefaults.runtime = runtime(withDefaults);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.6.2-rc.8",
3
+ "version": "1.7.0",
4
4
  "description": "Split Javascript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -24,6 +24,7 @@
24
24
  "build:cjs": "rimraf cjs && tsc -m CommonJS --outDir cjs",
25
25
  "test": "jest",
26
26
  "test:coverage": "jest --coverage",
27
+ "all": "npm run check && npm run build && npm run test",
27
28
  "publish:rc": "npm run check && npm run test && npm run build && npm publish --tag rc",
28
29
  "publish:stable": "npm run check && npm run test && npm run build && npm publish"
29
30
  },
@@ -70,7 +71,6 @@
70
71
  "ioredis": "^4.28.0",
71
72
  "jest": "^27.2.3",
72
73
  "jest-localstorage-mock": "^2.4.3",
73
- "js-yaml": "^3.13.1",
74
74
  "lodash": "^4.17.21",
75
75
  "node-fetch": "^2.6.7",
76
76
  "redis-server": "1.2.2",
@@ -40,7 +40,7 @@ export function createUserConsentAPI(params: ISdkFactoryContext) {
40
40
 
41
41
  // @ts-ignore, clear method is present in storage for standalone and partial consumer mode
42
42
  if (events.clear) events.clear(); // @ts-ignore
43
- if (impressions.clear) impressions.clear();// @ts-ignore
43
+ if (impressions.clear) impressions.clear(); // @ts-ignore
44
44
  if (impressionCounts && impressionCounts.clear) impressionCounts.clear();
45
45
  }
46
46
  } else {
@@ -29,19 +29,19 @@ export function evaluateFeature(
29
29
  attributes: SplitIO.Attributes | undefined,
30
30
  storage: IStorageSync | IStorageAsync,
31
31
  ): MaybeThenable<IEvaluationResult> {
32
- let stringifiedSplit;
32
+ let parsedSplit;
33
33
 
34
34
  try {
35
- stringifiedSplit = storage.splits.getSplit(splitName);
35
+ parsedSplit = storage.splits.getSplit(splitName);
36
36
  } catch (e) {
37
37
  // Exception on sync `getSplit` storage. Not possible ATM with InMemory and InLocal storages.
38
38
  return treatmentException;
39
39
  }
40
40
 
41
- if (thenable(stringifiedSplit)) {
42
- return stringifiedSplit.then((result) => getEvaluation(
41
+ if (thenable(parsedSplit)) {
42
+ return parsedSplit.then((split) => getEvaluation(
43
43
  log,
44
- result,
44
+ split,
45
45
  key,
46
46
  attributes,
47
47
  storage,
@@ -54,7 +54,7 @@ export function evaluateFeature(
54
54
 
55
55
  return getEvaluation(
56
56
  log,
57
- stringifiedSplit,
57
+ parsedSplit,
58
58
  key,
59
59
  attributes,
60
60
  storage,
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable no-undef */
2
2
  // @TODO eventually migrate to JS-Browser-SDK package.
3
3
  import { ISignalListener } from './types';
4
- import { IRecorderCacheProducerSync, IStorageSync } from '../storages/types';
4
+ import { IRecorderCacheSync, IStorageSync } from '../storages/types';
5
5
  import { fromImpressionsCollector } from '../sync/submitters/impressionsSubmitter';
6
6
  import { fromImpressionCountsCollector } from '../sync/submitters/impressionCountsSubmitter';
7
7
  import { IResponse, ISplitApi } from '../services/types';
@@ -12,7 +12,6 @@ import { objectAssign } from '../utils/lang/objectAssign';
12
12
  import { CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants';
13
13
  import { ISyncManager } from '../sync/types';
14
14
  import { isConsentGranted } from '../consent';
15
- import { telemetryCacheStatsAdapter } from '../sync/submitters/telemetrySubmitter';
16
15
 
17
16
  const VISIBILITYCHANGE_EVENT = 'visibilitychange';
18
17
  const PAGEHIDE_EVENT = 'pagehide';
@@ -84,27 +83,25 @@ export class BrowserSignalListener implements ISignalListener {
84
83
  */
85
84
  flushData() {
86
85
  if (!this.syncManager) return; // In consumer mode there is not sync manager and data to flush
86
+ const { events, telemetry } = this.settings.urls;
87
87
 
88
88
  // Flush impressions & events data if there is user consent
89
89
  if (isConsentGranted(this.settings)) {
90
- const eventsUrl = this.settings.urls.events;
91
90
  const sim = this.settings.sync.impressionsMode;
92
91
  const extraMetadata = {
93
92
  // sim stands for Sync/Split Impressions Mode
94
93
  sim: sim === OPTIMIZED ? OPTIMIZED : sim === DEBUG ? DEBUG : NONE
95
94
  };
96
95
 
97
- this._flushData(eventsUrl + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
98
- this._flushData(eventsUrl + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
99
- if (this.storage.impressionCounts) this._flushData(eventsUrl + '/testImpressions/count/beacon', this.storage.impressionCounts, this.serviceApi.postTestImpressionsCount, fromImpressionCountsCollector);
96
+ this._flushData(events + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
97
+ this._flushData(events + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
98
+ if (this.storage.impressionCounts) this._flushData(events + '/testImpressions/count/beacon', this.storage.impressionCounts, this.serviceApi.postTestImpressionsCount, fromImpressionCountsCollector);
99
+ // @ts-ignore
100
+ if (this.storage.uniqueKeys) this._flushData(telemetry + '/v1/keys/cs/beacon', this.storage.uniqueKeys, this.serviceApi.postUniqueKeysBulkCs);
100
101
  }
101
102
 
102
103
  // Flush telemetry data
103
- if (this.storage.telemetry) {
104
- const telemetryUrl = this.settings.urls.telemetry;
105
- const telemetryCacheAdapter = telemetryCacheStatsAdapter(this.storage.telemetry, this.storage.splits, this.storage.segments);
106
- this._flushData(telemetryUrl + '/v1/metrics/usage/beacon', telemetryCacheAdapter, this.serviceApi.postMetricsUsage);
107
- }
104
+ if (this.storage.telemetry) this._flushData(telemetry + '/v1/metrics/usage/beacon', this.storage.telemetry, this.serviceApi.postMetricsUsage);
108
105
  }
109
106
 
110
107
  flushDataIfHidden() {
@@ -112,14 +109,13 @@ export class BrowserSignalListener implements ISignalListener {
112
109
  if (document.visibilityState === 'hidden') this.flushData(); // On a 'visibilitychange' event, flush data if state is hidden
113
110
  }
114
111
 
115
- private _flushData<T>(url: string, cache: IRecorderCacheProducerSync<T>, postService: (body: string) => Promise<IResponse>, fromCacheToPayload?: (cacheData: T) => any, extraMetadata?: {}) {
112
+ private _flushData<T>(url: string, cache: IRecorderCacheSync<T>, postService: (body: string) => Promise<IResponse>, fromCacheToPayload?: (cacheData: T) => any, extraMetadata?: {}) {
116
113
  // if there is data in cache, send it to backend
117
114
  if (!cache.isEmpty()) {
118
115
  const dataPayload = fromCacheToPayload ? fromCacheToPayload(cache.pop()) : cache.pop();
119
116
  if (!this._sendBeacon(url, dataPayload, extraMetadata)) {
120
117
  postService(JSON.stringify(dataPayload)).catch(() => { }); // no-op just to catch a possible exception
121
118
  }
122
- cache.clear();
123
119
  }
124
120
  }
125
121
 
Binary file
@@ -9,6 +9,17 @@ import { IEvaluationResult } from '../evaluator/types';
9
9
  import { SplitIO, ImpressionDTO } from '../types';
10
10
  import { IMPRESSION, IMPRESSION_QUEUEING } from '../logger/constants';
11
11
  import { ISdkFactoryContext } from '../sdkFactory/types';
12
+ import { isStorageSync } from '../trackers/impressionObserver/utils';
13
+
14
+ const treatmentNotReady = { treatment: CONTROL, label: SDK_NOT_READY };
15
+
16
+ function treatmentsNotReady(splitNames: string[]) {
17
+ const evaluations: Record<string, IEvaluationResult> = {};
18
+ splitNames.forEach(splitName => {
19
+ evaluations[splitName] = treatmentNotReady;
20
+ });
21
+ return evaluations;
22
+ }
12
23
 
13
24
  /**
14
25
  * Creator of base client with getTreatments and track methods.
@@ -29,7 +40,11 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
29
40
  return treatment;
30
41
  };
31
42
 
32
- const evaluation = evaluateFeature(log, key, splitName, attributes, storage);
43
+ const evaluation = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
44
+ evaluateFeature(log, key, splitName, attributes, storage) :
45
+ isStorageSync(settings) ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
46
+ treatmentNotReady :
47
+ Promise.resolve(treatmentNotReady); // Promisify if async
33
48
 
34
49
  return thenable(evaluation) ? evaluation.then((res) => wrapUp(res)) : wrapUp(evaluation);
35
50
  }
@@ -53,7 +68,11 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
53
68
  return treatments;
54
69
  };
55
70
 
56
- const evaluations = evaluateFeatures(log, key, splitNames, attributes, storage);
71
+ const evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
72
+ evaluateFeatures(log, key, splitNames, attributes, storage) :
73
+ isStorageSync(settings) ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected
74
+ treatmentsNotReady(splitNames) :
75
+ Promise.resolve(treatmentsNotReady(splitNames)); // Promisify if async
57
76
 
58
77
  return thenable(evaluations) ? evaluations.then((res) => wrapUp(res)) : wrapUp(evaluations);
59
78
  }
@@ -72,15 +91,9 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
72
91
  invokingMethodName: string,
73
92
  queue: ImpressionDTO[]
74
93
  ): SplitIO.Treatment | SplitIO.TreatmentWithConfig {
75
- const isSdkReady = readinessManager.isReady() || readinessManager.isReadyFromCache();
76
94
  const matchingKey = getMatching(key);
77
95
  const bucketingKey = getBucketing(key);
78
96
 
79
- // If the SDK was not ready, treatment may be incorrect due to having Splits but not segments data.
80
- if (!isSdkReady) {
81
- evaluation = { treatment: CONTROL, label: SDK_NOT_READY };
82
- }
83
-
84
97
  const { treatment, label, changeNumber, config = null } = evaluation;
85
98
  log.info(IMPRESSION, [splitName, matchingKey, treatment, label]);
86
99
 
@@ -39,7 +39,7 @@ export function sdkClientFactory(params: ISdkFactoryContext, isSharedClient?: bo
39
39
 
40
40
  // Release the API Key if it is the main client
41
41
  if (!isSharedClient) releaseApiKey(settings.core.authorizationKey);
42
-
42
+
43
43
  if (uniqueKeysTracker) uniqueKeysTracker.stop();
44
44
 
45
45
  // Cleanup storage
@@ -3,14 +3,10 @@ import { sdkReadinessManagerFactory } from '../readiness/sdkReadinessManager';
3
3
  import { impressionsTrackerFactory } from '../trackers/impressionsTracker';
4
4
  import { eventTrackerFactory } from '../trackers/eventTracker';
5
5
  import { telemetryTrackerFactory } from '../trackers/telemetryTracker';
6
- import { IStorageFactoryParams } from '../storages/types';
7
6
  import { SplitIO } from '../types';
8
- import { getMatching } from '../utils/key';
9
- import { shouldBeOptimized } from '../trackers/impressionObserver/utils';
10
7
  import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey';
11
8
  import { createLoggerAPI } from '../logger/sdkLogger';
12
9
  import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
13
- import { metadataBuilder } from '../storages/metadataBuilder';
14
10
  import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
15
11
  import { objectAssign } from '../utils/lang/objectAssign';
16
12
  import { strategyDebugFactory } from '../trackers/strategy/strategyDebug';
@@ -28,7 +24,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
28
24
  syncManagerFactory, SignalListener, impressionsObserverFactory,
29
25
  integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory,
30
26
  filterAdapterFactory } = params;
31
- const log = settings.log;
27
+ const { log, sync: { impressionsMode } } = settings;
32
28
 
33
29
  // @TODO handle non-recoverable errors, such as, global `fetch` not available, invalid API Key, etc.
34
30
  // On non-recoverable errors, we should mark the SDK as destroyed and not start synchronization.
@@ -39,50 +35,31 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
39
35
  const sdkReadinessManager = sdkReadinessManagerFactory(log, platform.EventEmitter, settings.startup.readyTimeout);
40
36
  const readiness = sdkReadinessManager.readinessManager;
41
37
 
42
- // @TODO consider passing the settings object, so that each storage access only what it needs
43
- const storageFactoryParams: IStorageFactoryParams = {
44
- impressionsQueueSize: settings.scheduler.impressionsQueueSize,
45
- eventsQueueSize: settings.scheduler.eventsQueueSize,
46
- uniqueKeysCacheSize: settings.scheduler.uniqueKeysCacheSize,
47
- optimize: shouldBeOptimized(settings),
48
-
49
- // ATM, only used by InLocalStorage
50
- matchingKey: getMatching(settings.core.key),
51
- splitFiltersValidation: settings.sync.__splitFiltersValidation,
52
-
53
- // ATM, only used by PluggableStorage
54
- mode: settings.mode,
55
- impressionsMode: settings.sync.impressionsMode,
56
-
57
- // Callback used to emit SDK_READY in consumer mode, where `syncManagerFactory` is undefined,
58
- // or partial consumer mode, where it only has submitters, and therefore it doesn't emit readiness events.
38
+ const storage = storageFactory({
39
+ settings,
59
40
  onReadyCb: (error) => {
60
41
  if (error) return; // Don't emit SDK_READY if storage failed to connect. Error message is logged by wrapperAdapter
61
42
  readiness.splits.emit(SDK_SPLITS_ARRIVED);
62
43
  readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
63
44
  },
64
- metadata: metadataBuilder(settings),
65
- log
66
- };
67
-
68
- const storage = storageFactory(storageFactoryParams);
45
+ });
69
46
  // @TODO add support for dataloader: `if (params.dataLoader) params.dataLoader(storage);`
70
47
 
71
48
  const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
72
49
  const integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings, storage, telemetryTracker });
73
50
 
74
51
  const observer = impressionsObserverFactory();
75
- const uniqueKeysTracker = storageFactoryParams.impressionsMode === NONE ? uniqueKeysTrackerFactory(log, storage.uniqueKeys!, filterAdapterFactory && filterAdapterFactory()) : undefined;
52
+ const uniqueKeysTracker = impressionsMode === NONE ? uniqueKeysTrackerFactory(log, storage.uniqueKeys!, filterAdapterFactory && filterAdapterFactory()) : undefined;
76
53
 
77
54
  let strategy;
78
- switch (storageFactoryParams.impressionsMode) {
79
- case OPTIMIZED:
55
+ switch (impressionsMode) {
56
+ case OPTIMIZED:
80
57
  strategy = strategyOptimizedFactory(observer, storage.impressionCounts!);
81
58
  break;
82
- case NONE:
59
+ case NONE:
83
60
  strategy = strategyNoneFactory(storage.impressionCounts!, uniqueKeysTracker!);
84
61
  break;
85
- default:
62
+ default:
86
63
  strategy = strategyDebugFactory(observer);
87
64
  }
88
65
 
@@ -121,7 +98,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
121
98
  },
122
99
 
123
100
  // Logger wrapper API
124
- Logger: createLoggerAPI(settings.log),
101
+ Logger: createLoggerAPI(log),
125
102
 
126
103
  settings,
127
104
  }, extraProps && extraProps(ctx));
@@ -97,9 +97,9 @@ export interface ISdkFactoryParams {
97
97
  // It Allows to distinguish SDK clients with the client-side API (`ICsSDK`) or server-side API (`ISDK` or `IAsyncSDK`).
98
98
  sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient))
99
99
 
100
- // Impression observer factory. If provided, will be used for impressions dedupe
100
+ // Impression observer factory.
101
101
  impressionsObserverFactory: () => IImpressionObserver
102
-
102
+
103
103
  filterAdapterFactory?: () => IFilterAdapter
104
104
 
105
105
  // Optional signal listener constructor. Used to handle special app states, like shutdown, app paused or resumed.
@@ -106,7 +106,7 @@ export function splitApiFactory(
106
106
  const url = `${urls.events}/testImpressions/count`;
107
107
  return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(IMPRESSIONS_COUNT));
108
108
  },
109
-
109
+
110
110
  /**
111
111
  * Post unique keys for client side.
112
112
  *
@@ -117,7 +117,7 @@ export function splitApiFactory(
117
117
  const url = `${urls.telemetry}/v1/keys/cs`;
118
118
  return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY));
119
119
  },
120
-
120
+
121
121
  /**
122
122
  * Post unique keys for server side.
123
123
  *
@@ -129,14 +129,14 @@ export function splitApiFactory(
129
129
  return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY));
130
130
  },
131
131
 
132
- postMetricsConfig(body: string) {
132
+ postMetricsConfig(body: string, headers?: Record<string, string>) {
133
133
  const url = `${urls.telemetry}/v1/metrics/config`;
134
- return splitHttpClient(url, { method: 'POST', body }, telemetryTracker.trackHttp(TELEMETRY), true);
134
+ return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY), true);
135
135
  },
136
136
 
137
- postMetricsUsage(body: string) {
137
+ postMetricsUsage(body: string, headers?: Record<string, string>) {
138
138
  const url = `${urls.telemetry}/v1/metrics/usage`;
139
- return splitHttpClient(url, { method: 'POST', body }, telemetryTracker.trackHttp(TELEMETRY), true);
139
+ return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY), true);
140
140
  }
141
141
  };
142
142
  }
@@ -51,9 +51,9 @@ export type IPostTestImpressionsBulk = (body: string, headers?: Record<string, s
51
51
 
52
52
  export type IPostTestImpressionsCount = (body: string, headers?: Record<string, string>) => Promise<IResponse>
53
53
 
54
- export type IPostMetricsConfig = (body: string) => Promise<IResponse>
54
+ export type IPostMetricsConfig = (body: string, headers?: Record<string, string>) => Promise<IResponse>
55
55
 
56
- export type IPostMetricsUsage = (body: string) => Promise<IResponse>
56
+ export type IPostMetricsUsage = (body: string, headers?: Record<string, string>) => Promise<IResponse>
57
57
 
58
58
  export interface ISplitApi {
59
59
  getSdkAPIHealthCheck: IHealthCheckAPI
@@ -41,7 +41,7 @@ export abstract class AbstractSplitsCacheAsync implements ISplitsCacheAsync {
41
41
  * @param {string} name
42
42
  * @param {string} defaultTreatment
43
43
  * @param {number} changeNumber
44
- * @returns {Promise} a promise that is resolved once the split kill operation is performed. The fulfillment value is a boolean: `true` if the kill success updating the split or `false` if no split is updated,
44
+ * @returns {Promise} 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,
45
45
  * 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.
46
46
  * The promise will never be rejected.
47
47
  */
@@ -61,7 +61,7 @@ export abstract class AbstractSplitsCacheSync implements ISplitsCacheSync {
61
61
  * @param {string} name
62
62
  * @param {string} defaultTreatment
63
63
  * @param {number} changeNumber
64
- * @returns {Promise} a promise that is resolved once the split kill is performed. The fulfillment value is a boolean: `true` if the kill success updating the split or `false` if no split is updated,
64
+ * @returns {boolean} `true` if the operation successed updating the split, or `false` if no split is updated,
65
65
  * 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.
66
66
  */
67
67
  killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean {
@@ -2,7 +2,7 @@ import { KeyBuilder } from './KeyBuilder';
2
2
  import { IMetadata } from '../dtos/types';
3
3
  import { Method } from '../sync/submitters/types';
4
4
 
5
- const methodNames: Record<Method, string> = {
5
+ export const METHOD_NAMES: Record<Method, string> = {
6
6
  t: 'treatment',
7
7
  ts: 'treatments',
8
8
  tc: 'treatmentWithConfig',
@@ -12,11 +12,17 @@ const methodNames: Record<Method, string> = {
12
12
 
13
13
  export class KeyBuilderSS extends KeyBuilder {
14
14
 
15
- protected readonly metadata: IMetadata;
15
+ latencyPrefix: string;
16
+ exceptionPrefix: string;
17
+ initPrefix: string;
18
+ private versionablePrefix: string;
16
19
 
17
20
  constructor(prefix: string, metadata: IMetadata) {
18
21
  super(prefix);
19
- this.metadata = metadata;
22
+ this.latencyPrefix = `${this.prefix}.telemetry.latencies`;
23
+ this.exceptionPrefix = `${this.prefix}.telemetry.exceptions`;
24
+ this.initPrefix = `${this.prefix}.telemetry.init`;
25
+ this.versionablePrefix = `${metadata.s}/${metadata.n}/${metadata.i}`;
20
26
  }
21
27
 
22
28
  buildRegisteredSegmentsKey() {
@@ -30,7 +36,7 @@ export class KeyBuilderSS extends KeyBuilder {
30
36
  buildImpressionsCountKey() {
31
37
  return `${this.prefix}.impressions.count`;
32
38
  }
33
-
39
+
34
40
  buildUniqueKeysKey() {
35
41
  return `${this.prefix}.uniquekeys`;
36
42
  }
@@ -46,19 +52,15 @@ export class KeyBuilderSS extends KeyBuilder {
46
52
  /* Telemetry keys */
47
53
 
48
54
  buildLatencyKey(method: Method, bucket: number) {
49
- return `${this.prefix}.telemetry.latencies::${this.buildVersionablePrefix()}/${methodNames[method]}/${bucket}`;
55
+ return `${this.latencyPrefix}::${this.versionablePrefix}/${METHOD_NAMES[method]}/${bucket}`;
50
56
  }
51
57
 
52
58
  buildExceptionKey(method: Method) {
53
- return `${this.prefix}.telemetry.exceptions::${this.buildVersionablePrefix()}/${methodNames[method]}`;
59
+ return `${this.exceptionPrefix}::${this.versionablePrefix}/${METHOD_NAMES[method]}`;
54
60
  }
55
61
 
56
62
  buildInitKey() {
57
- return `${this.prefix}.telemetry.init::${this.buildVersionablePrefix()}`;
58
- }
59
-
60
- private buildVersionablePrefix() {
61
- return `${this.metadata.s}/${this.metadata.n}/${this.metadata.i}`;
63
+ return `${this.initPrefix}::${this.versionablePrefix}`;
62
64
  }
63
65
 
64
66
  }
@@ -229,7 +229,6 @@ export class SplitsCacheInLocal extends AbstractSplitsCacheSync {
229
229
 
230
230
  /**
231
231
  * Clean Splits cache if its `lastUpdated` timestamp is older than the given `expirationTimestamp`,
232
- * Clean operation (clear) also updates `lastUpdated` timestamp with current time.
233
232
  *
234
233
  * @param {number | undefined} expirationTimestamp if the value is not a number, data will not be cleaned
235
234
  */
@@ -12,9 +12,10 @@ import { SplitsCacheInMemory } from '../inMemory/SplitsCacheInMemory';
12
12
  import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
13
13
  import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
14
14
  import { LOG_PREFIX } from './constants';
15
- import { LOCALHOST_MODE, NONE, STORAGE_LOCALSTORAGE } from '../../utils/constants';
15
+ import { DEBUG, NONE, STORAGE_LOCALSTORAGE } from '../../utils/constants';
16
16
  import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
17
- import { UniqueKeysCacheInMemoryCS } from '../inMemory/uniqueKeysCacheInMemoryCS';
17
+ import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
18
+ import { getMatching } from '../../utils/key';
18
19
 
19
20
  export interface InLocalStorageOptions {
20
21
  prefix?: string
@@ -31,22 +32,26 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
31
32
 
32
33
  // Fallback to InMemoryStorage if LocalStorage API is not available
33
34
  if (!isLocalStorageAvailable()) {
34
- params.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
35
+ params.settings.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
35
36
  return InMemoryStorageCSFactory(params);
36
37
  }
37
38
 
38
- const log = params.log;
39
- const keys = new KeyBuilderCS(prefix, params.matchingKey as string);
39
+ const { settings, settings: { log, scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation } } } = params;
40
+ const matchingKey = getMatching(settings.core.key);
41
+ const keys = new KeyBuilderCS(prefix, matchingKey as string);
40
42
  const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
41
43
 
44
+ const splits = new SplitsCacheInLocal(log, keys, expirationTimestamp, __splitFiltersValidation);
45
+ const segments = new MySegmentsCacheInLocal(log, keys);
46
+
42
47
  return {
43
- splits: new SplitsCacheInLocal(log, keys, expirationTimestamp, params.splitFiltersValidation),
44
- segments: new MySegmentsCacheInLocal(log, keys),
45
- impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
46
- impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
47
- events: new EventsCacheInMemory(params.eventsQueueSize),
48
- telemetry: params.mode !== LOCALHOST_MODE && shouldRecordTelemetry() ? new TelemetryCacheInMemory() : undefined,
49
- uniqueKeys: params.impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
48
+ splits,
49
+ segments,
50
+ impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
51
+ impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
52
+ events: new EventsCacheInMemory(eventsQueueSize),
53
+ telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
54
+ uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
50
55
 
51
56
  destroy() {
52
57
  this.splits = new SplitsCacheInMemory();