@splitsoftware/splitio-commons 2.1.0-rc.1 → 2.1.0-rc.2

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 (61) hide show
  1. package/CHANGES.txt +5 -1
  2. package/LICENSE +1 -1
  3. package/cjs/evaluator/index.js +2 -0
  4. package/cjs/listeners/browser.js +4 -6
  5. package/cjs/sdkClient/client.js +14 -11
  6. package/cjs/sdkClient/sdkClient.js +1 -1
  7. package/cjs/sdkFactory/index.js +9 -14
  8. package/cjs/sdkManager/index.js +2 -1
  9. package/cjs/storages/inLocalStorage/index.js +4 -3
  10. package/cjs/storages/inMemory/InMemoryStorage.js +5 -7
  11. package/cjs/storages/inMemory/InMemoryStorageCS.js +6 -7
  12. package/cjs/storages/inRedis/index.js +9 -13
  13. package/cjs/storages/pluggable/index.js +15 -19
  14. package/cjs/sync/submitters/impressionCountsSubmitter.js +2 -4
  15. package/cjs/sync/submitters/submitterManager.js +3 -6
  16. package/cjs/trackers/impressionsTracker.js +17 -18
  17. package/cjs/trackers/strategy/strategyDebug.js +4 -11
  18. package/cjs/trackers/strategy/strategyNone.js +11 -16
  19. package/cjs/trackers/strategy/strategyOptimized.js +11 -21
  20. package/esm/evaluator/index.js +2 -0
  21. package/esm/listeners/browser.js +1 -3
  22. package/esm/sdkClient/client.js +14 -11
  23. package/esm/sdkClient/sdkClient.js +1 -1
  24. package/esm/sdkFactory/index.js +10 -15
  25. package/esm/sdkManager/index.js +2 -1
  26. package/esm/storages/inLocalStorage/index.js +5 -4
  27. package/esm/storages/inMemory/InMemoryStorage.js +6 -8
  28. package/esm/storages/inMemory/InMemoryStorageCS.js +7 -8
  29. package/esm/storages/inRedis/index.js +10 -14
  30. package/esm/storages/pluggable/index.js +16 -20
  31. package/esm/sync/submitters/impressionCountsSubmitter.js +2 -4
  32. package/esm/sync/submitters/submitterManager.js +3 -6
  33. package/esm/trackers/impressionsTracker.js +17 -18
  34. package/esm/trackers/strategy/strategyDebug.js +4 -11
  35. package/esm/trackers/strategy/strategyNone.js +11 -16
  36. package/esm/trackers/strategy/strategyOptimized.js +11 -21
  37. package/package.json +1 -1
  38. package/src/dtos/types.ts +2 -1
  39. package/src/evaluator/index.ts +2 -0
  40. package/src/evaluator/types.ts +1 -1
  41. package/src/listeners/browser.ts +1 -3
  42. package/src/sdkClient/client.ts +19 -15
  43. package/src/sdkClient/sdkClient.ts +1 -1
  44. package/src/sdkFactory/index.ts +11 -16
  45. package/src/sdkFactory/types.ts +1 -1
  46. package/src/sdkManager/index.ts +2 -1
  47. package/src/storages/inLocalStorage/index.ts +5 -4
  48. package/src/storages/inMemory/InMemoryStorage.ts +6 -6
  49. package/src/storages/inMemory/InMemoryStorageCS.ts +7 -6
  50. package/src/storages/inRedis/index.ts +10 -10
  51. package/src/storages/pluggable/index.ts +16 -20
  52. package/src/storages/types.ts +2 -2
  53. package/src/sync/submitters/impressionCountsSubmitter.ts +2 -4
  54. package/src/sync/submitters/submitterManager.ts +3 -4
  55. package/src/sync/submitters/uniqueKeysSubmitter.ts +2 -3
  56. package/src/trackers/impressionsTracker.ts +18 -19
  57. package/src/trackers/strategy/strategyDebug.ts +4 -11
  58. package/src/trackers/strategy/strategyNone.ts +11 -17
  59. package/src/trackers/strategy/strategyOptimized.ts +10 -20
  60. package/src/trackers/types.ts +13 -8
  61. package/types/splitio.d.ts +4 -0
@@ -1,25 +1,20 @@
1
1
  /**
2
2
  * None strategy for impressions tracker.
3
3
  *
4
- * @param impressionsCounter - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
4
+ * @param impressionCounts - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
5
5
  * @param uniqueKeysTracker - unique keys tracker in charge of tracking the unique keys per split.
6
- * @returns IStrategyResult
6
+ * @returns None strategy
7
7
  */
8
- export function strategyNoneFactory(impressionsCounter, uniqueKeysTracker) {
8
+ export function strategyNoneFactory(impressionCounts, uniqueKeysTracker) {
9
9
  return {
10
- process: function (impressions) {
11
- impressions.forEach(function (impression) {
12
- var now = Date.now();
13
- // Increments impression counter per featureName
14
- impressionsCounter.track(impression.feature, now, 1);
15
- // Keep track by unique key
16
- uniqueKeysTracker.track(impression.keyName, impression.feature);
17
- });
18
- return {
19
- impressionsToStore: [],
20
- impressionsToListener: impressions,
21
- deduped: 0
22
- };
10
+ process: function (impression) {
11
+ var now = Date.now();
12
+ // Increments impression counter per featureName
13
+ impressionCounts.track(impression.feature, now, 1);
14
+ // Keep track by unique key
15
+ uniqueKeysTracker.track(impression.keyName, impression.feature);
16
+ // Do not store impressions
17
+ return false;
23
18
  }
24
19
  };
25
20
  }
@@ -3,29 +3,19 @@ import { truncateTimeFrame } from '../../utils/time';
3
3
  * Optimized strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
4
4
  *
5
5
  * @param impressionsObserver - impression observer. previous time (pt property) is included in impression instances
6
- * @param impressionsCounter - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
7
- * @returns IStrategyResult
6
+ * @param impressionCounts - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
7
+ * @returns Optimized strategy
8
8
  */
9
- export function strategyOptimizedFactory(impressionsObserver, impressionsCounter) {
9
+ export function strategyOptimizedFactory(impressionsObserver, impressionCounts) {
10
10
  return {
11
- process: function (impressions) {
12
- var impressionsToStore = [];
13
- impressions.forEach(function (impression) {
14
- impression.pt = impressionsObserver.testAndSet(impression);
15
- var now = Date.now();
16
- // Increments impression counter per featureName
17
- if (impression.pt)
18
- impressionsCounter.track(impression.feature, now, 1);
19
- // Checks if the impression should be added in queue to be sent
20
- if (!impression.pt || impression.pt < truncateTimeFrame(now)) {
21
- impressionsToStore.push(impression);
22
- }
23
- });
24
- return {
25
- impressionsToStore: impressionsToStore,
26
- impressionsToListener: impressions,
27
- deduped: impressions.length - impressionsToStore.length
28
- };
11
+ process: function (impression) {
12
+ impression.pt = impressionsObserver.testAndSet(impression);
13
+ var now = Date.now();
14
+ // Increments impression counter per featureName
15
+ if (impression.pt)
16
+ impressionCounts.track(impression.feature, now, 1);
17
+ // Checks if the impression should be added in queue to be sent
18
+ return (!impression.pt || impression.pt < truncateTimeFrame(now)) ? true : false;
29
19
  }
30
20
  };
31
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "2.1.0-rc.1",
3
+ "version": "2.1.0-rc.2",
4
4
  "description": "Split JavaScript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
package/src/dtos/types.ts CHANGED
@@ -208,7 +208,8 @@ export interface ISplit {
208
208
  configurations?: {
209
209
  [treatmentName: string]: string
210
210
  },
211
- sets?: string[]
211
+ sets?: string[],
212
+ impressionsDisabled?: boolean
212
213
  }
213
214
 
214
215
  // Split definition used in offline mode
@@ -156,12 +156,14 @@ function getEvaluation(
156
156
  return evaluation.then(result => {
157
157
  result.changeNumber = split.getChangeNumber();
158
158
  result.config = splitJSON.configurations && splitJSON.configurations[result.treatment] || null;
159
+ result.impressionsDisabled = splitJSON.impressionsDisabled;
159
160
 
160
161
  return result;
161
162
  });
162
163
  } else {
163
164
  evaluation.changeNumber = split.getChangeNumber(); // Always sync and optional
164
165
  evaluation.config = splitJSON.configurations && splitJSON.configurations[evaluation.treatment] || null;
166
+ evaluation.impressionsDisabled = splitJSON.impressionsDisabled;
165
167
  }
166
168
  }
167
169
 
@@ -25,7 +25,7 @@ export interface IEvaluation {
25
25
  config?: string | null
26
26
  }
27
27
 
28
- export type IEvaluationResult = IEvaluation & { treatment: string }
28
+ export type IEvaluationResult = IEvaluation & { treatment: string; impressionsDisabled?: boolean }
29
29
 
30
30
  export type ISplitEvaluator = (log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync) => MaybeThenable<IEvaluation>
31
31
 
@@ -8,7 +8,6 @@ import { IResponse, ISplitApi } from '../services/types';
8
8
  import { ISettings } from '../types';
9
9
  import SplitIO from '../../types/splitio';
10
10
  import { ImpressionsPayload } from '../sync/submitters/types';
11
- import { OPTIMIZED, DEBUG, NONE } from '../utils/constants';
12
11
  import { objectAssign } from '../utils/lang/objectAssign';
13
12
  import { CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants';
14
13
  import { ISyncManager } from '../sync/types';
@@ -78,10 +77,9 @@ export class BrowserSignalListener implements ISignalListener {
78
77
 
79
78
  // Flush impressions & events data if there is user consent
80
79
  if (isConsentGranted(this.settings)) {
81
- const sim = this.settings.sync.impressionsMode;
82
80
  const extraMetadata = {
83
81
  // sim stands for Sync/Split Impressions Mode
84
- sim: sim === OPTIMIZED ? OPTIMIZED : sim === DEBUG ? DEBUG : NONE
82
+ sim: this.settings.sync.impressionsMode
85
83
  };
86
84
 
87
85
  this._flushData(events + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
@@ -11,6 +11,7 @@ import { IMPRESSION, IMPRESSION_QUEUEING } from '../logger/constants';
11
11
  import { ISdkFactoryContext } from '../sdkFactory/types';
12
12
  import { isConsumerMode } from '../utils/settingsValidation/mode';
13
13
  import { Method } from '../sync/submitters/types';
14
+ import { ImpressionDecorated } from '../trackers/types';
14
15
 
15
16
  const treatmentNotReady = { treatment: CONTROL, label: SDK_NOT_READY };
16
17
 
@@ -34,11 +35,11 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
34
35
  const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENT_WITH_CONFIG : TREATMENT);
35
36
 
36
37
  const wrapUp = (evaluationResult: IEvaluationResult) => {
37
- const queue: SplitIO.ImpressionDTO[] = [];
38
+ const queue: ImpressionDecorated[] = [];
38
39
  const treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig, methodName, queue);
39
40
  impressionsTracker.track(queue, attributes);
40
41
 
41
- stopTelemetryTracker(queue[0] && queue[0].label);
42
+ stopTelemetryTracker(queue[0] && queue[0].imp.label);
42
43
  return treatment;
43
44
  };
44
45
 
@@ -59,14 +60,14 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
59
60
  const stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? TREATMENTS_WITH_CONFIG : TREATMENTS);
60
61
 
61
62
  const wrapUp = (evaluationResults: Record<string, IEvaluationResult>) => {
62
- const queue: SplitIO.ImpressionDTO[] = [];
63
+ const queue: ImpressionDecorated[] = [];
63
64
  const treatments: Record<string, SplitIO.Treatment | SplitIO.TreatmentWithConfig> = {};
64
65
  Object.keys(evaluationResults).forEach(featureFlagName => {
65
66
  treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
66
67
  });
67
68
  impressionsTracker.track(queue, attributes);
68
69
 
69
- stopTelemetryTracker(queue[0] && queue[0].label);
70
+ stopTelemetryTracker(queue[0] && queue[0].imp.label);
70
71
  return treatments;
71
72
  };
72
73
 
@@ -87,7 +88,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
87
88
  const stopTelemetryTracker = telemetryTracker.trackEval(method);
88
89
 
89
90
  const wrapUp = (evaluationResults: Record<string, IEvaluationResult>) => {
90
- const queue: SplitIO.ImpressionDTO[] = [];
91
+ const queue: ImpressionDecorated[] = [];
91
92
  const treatments: Record<string, SplitIO.Treatment | SplitIO.TreatmentWithConfig> = {};
92
93
  const evaluations = evaluationResults;
93
94
  Object.keys(evaluations).forEach(featureFlagName => {
@@ -95,7 +96,7 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
95
96
  });
96
97
  impressionsTracker.track(queue, attributes);
97
98
 
98
- stopTelemetryTracker(queue[0] && queue[0].label);
99
+ stopTelemetryTracker(queue[0] && queue[0].imp.label);
99
100
  return treatments;
100
101
  };
101
102
 
@@ -128,24 +129,27 @@ export function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | Spl
128
129
  attributes: SplitIO.Attributes | undefined,
129
130
  withConfig: boolean,
130
131
  invokingMethodName: string,
131
- queue: SplitIO.ImpressionDTO[]
132
+ queue: ImpressionDecorated[]
132
133
  ): SplitIO.Treatment | SplitIO.TreatmentWithConfig {
133
134
  const matchingKey = getMatching(key);
134
135
  const bucketingKey = getBucketing(key);
135
136
 
136
- const { treatment, label, changeNumber, config = null } = evaluation;
137
+ const { treatment, label, changeNumber, config = null, impressionsDisabled } = evaluation;
137
138
  log.info(IMPRESSION, [featureFlagName, matchingKey, treatment, label]);
138
139
 
139
140
  if (validateSplitExistence(log, readinessManager, featureFlagName, label, invokingMethodName)) {
140
141
  log.info(IMPRESSION_QUEUEING);
141
142
  queue.push({
142
- feature: featureFlagName,
143
- keyName: matchingKey,
144
- treatment,
145
- time: Date.now(),
146
- bucketingKey,
147
- label,
148
- changeNumber: changeNumber as number
143
+ imp: {
144
+ feature: featureFlagName,
145
+ keyName: matchingKey,
146
+ treatment,
147
+ time: Date.now(),
148
+ bucketingKey,
149
+ label,
150
+ changeNumber: changeNumber as number,
151
+ },
152
+ disabled: impressionsDisabled
149
153
  });
150
154
  }
151
155
 
@@ -61,7 +61,7 @@ export function sdkClientFactory(params: ISdkFactoryContext, isSharedClient?: bo
61
61
  releaseApiKey(settings.core.authorizationKey);
62
62
  telemetryTracker.sessionLength();
63
63
  signalListener && signalListener.stop();
64
- uniqueKeysTracker && uniqueKeysTracker.stop();
64
+ uniqueKeysTracker.stop();
65
65
  }
66
66
 
67
67
  // Stop background jobs
@@ -13,7 +13,7 @@ import { strategyDebugFactory } from '../trackers/strategy/strategyDebug';
13
13
  import { strategyOptimizedFactory } from '../trackers/strategy/strategyOptimized';
14
14
  import { strategyNoneFactory } from '../trackers/strategy/strategyNone';
15
15
  import { uniqueKeysTrackerFactory } from '../trackers/uniqueKeysTracker';
16
- import { NONE, OPTIMIZED } from '../utils/constants';
16
+ import { DEBUG, OPTIMIZED } from '../utils/constants';
17
17
 
18
18
  /**
19
19
  * Modular SDK factory
@@ -59,21 +59,16 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ISDK | SplitIO.IA
59
59
  const integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings, storage, telemetryTracker });
60
60
 
61
61
  const observer = impressionsObserverFactory();
62
- const uniqueKeysTracker = impressionsMode === NONE ? uniqueKeysTrackerFactory(log, storage.uniqueKeys!, filterAdapterFactory && filterAdapterFactory()) : undefined;
63
-
64
- let strategy;
65
- switch (impressionsMode) {
66
- case OPTIMIZED:
67
- strategy = strategyOptimizedFactory(observer, storage.impressionCounts!);
68
- break;
69
- case NONE:
70
- strategy = strategyNoneFactory(storage.impressionCounts!, uniqueKeysTracker!);
71
- break;
72
- default:
73
- strategy = strategyDebugFactory(observer);
74
- }
62
+ const uniqueKeysTracker = uniqueKeysTrackerFactory(log, storage.uniqueKeys, filterAdapterFactory && filterAdapterFactory());
63
+
64
+ const noneStrategy = strategyNoneFactory(storage.impressionCounts, uniqueKeysTracker);
65
+ const strategy = impressionsMode === OPTIMIZED ?
66
+ strategyOptimizedFactory(observer, storage.impressionCounts) :
67
+ impressionsMode === DEBUG ?
68
+ strategyDebugFactory(observer) :
69
+ noneStrategy;
75
70
 
76
- const impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, strategy, whenInit, integrationsManager, storage.telemetry);
71
+ const impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, noneStrategy, strategy, whenInit, integrationsManager, storage.telemetry);
77
72
  const eventTracker = eventTrackerFactory(settings, storage.events, whenInit, integrationsManager, storage.telemetry);
78
73
 
79
74
  // splitApi is used by SyncManager and Browser signal listener
@@ -99,7 +94,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ISDK | SplitIO.IA
99
94
  // We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
100
95
  validateAndTrackApiKey(log, settings.core.authorizationKey);
101
96
  readiness.init();
102
- uniqueKeysTracker && uniqueKeysTracker.start();
97
+ uniqueKeysTracker.start();
103
98
  syncManager && syncManager.start();
104
99
  signalListener && signalListener.start();
105
100
 
@@ -46,7 +46,7 @@ export interface ISdkFactoryContext {
46
46
  eventTracker: IEventTracker,
47
47
  telemetryTracker: ITelemetryTracker,
48
48
  storage: IStorageSync | IStorageAsync,
49
- uniqueKeysTracker?: IUniqueKeysTracker,
49
+ uniqueKeysTracker: IUniqueKeysTracker,
50
50
  signalListener?: ISignalListener
51
51
  splitApi?: ISplitApi
52
52
  syncManager?: ISyncManager,
@@ -31,7 +31,8 @@ function objectToView(splitObject: ISplit | null): SplitIO.SplitView | null {
31
31
  treatments: collectTreatments(splitObject),
32
32
  configs: splitObject.configurations || {},
33
33
  sets: splitObject.sets || [],
34
- defaultTreatment: splitObject.defaultTreatment
34
+ defaultTreatment: splitObject.defaultTreatment,
35
+ impressionsDisabled: splitObject.impressionsDisabled === true
35
36
  };
36
37
  }
37
38
 
@@ -9,7 +9,7 @@ import { SplitsCacheInLocal } from './SplitsCacheInLocal';
9
9
  import { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
10
10
  import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
11
11
  import { LOG_PREFIX } from './constants';
12
- import { DEBUG, NONE, STORAGE_LOCALSTORAGE } from '../../utils/constants';
12
+ import { STORAGE_LOCALSTORAGE } from '../../utils/constants';
13
13
  import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
14
14
  import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
15
15
  import { getMatching } from '../../utils/key';
@@ -31,7 +31,7 @@ export function InLocalStorage(options: SplitIO.InLocalStorageOptions = {}): ISt
31
31
  return InMemoryStorageCSFactory(params);
32
32
  }
33
33
 
34
- const { settings, settings: { log, scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode } } } = params;
34
+ const { settings, settings: { log, scheduler: { impressionsQueueSize, eventsQueueSize } } } = params;
35
35
  const matchingKey = getMatching(settings.core.key);
36
36
  const keys = new KeyBuilderCS(prefix, matchingKey);
37
37
 
@@ -44,10 +44,10 @@ export function InLocalStorage(options: SplitIO.InLocalStorageOptions = {}): ISt
44
44
  segments,
45
45
  largeSegments,
46
46
  impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
47
- impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
47
+ impressionCounts: new ImpressionCountsCacheInMemory(),
48
48
  events: new EventsCacheInMemory(eventsQueueSize),
49
49
  telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
50
- uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
50
+ uniqueKeys: new UniqueKeysCacheInMemoryCS(),
51
51
 
52
52
  validateCache() {
53
53
  return validateCache(options, settings, keys, splits, segments, largeSegments);
@@ -66,6 +66,7 @@ export function InLocalStorage(options: SplitIO.InLocalStorageOptions = {}): ISt
66
66
  impressionCounts: this.impressionCounts,
67
67
  events: this.events,
68
68
  telemetry: this.telemetry,
69
+ uniqueKeys: this.uniqueKeys,
69
70
 
70
71
  destroy() { }
71
72
  };
@@ -4,7 +4,7 @@ import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
4
4
  import { EventsCacheInMemory } from './EventsCacheInMemory';
5
5
  import { IStorageFactoryParams, IStorageSync } from '../types';
6
6
  import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
7
- import { DEBUG, LOCALHOST_MODE, NONE, STORAGE_MEMORY } from '../../utils/constants';
7
+ import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
8
8
  import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
9
9
  import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
10
10
 
@@ -14,7 +14,7 @@ import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
14
14
  * @param params - parameters required by EventsCacheSync
15
15
  */
16
16
  export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageSync {
17
- const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation } } } = params;
17
+ const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { __splitFiltersValidation } } } = params;
18
18
 
19
19
  const splits = new SplitsCacheInMemory(__splitFiltersValidation);
20
20
  const segments = new SegmentsCacheInMemory();
@@ -23,10 +23,10 @@ export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageS
23
23
  splits,
24
24
  segments,
25
25
  impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
26
- impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
26
+ impressionCounts: new ImpressionCountsCacheInMemory(),
27
27
  events: new EventsCacheInMemory(eventsQueueSize),
28
28
  telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
29
- uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemory() : undefined,
29
+ uniqueKeys: new UniqueKeysCacheInMemory(),
30
30
 
31
31
  destroy() { }
32
32
  };
@@ -37,8 +37,8 @@ export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageS
37
37
  const noopTrack = () => true;
38
38
  storage.impressions.track = noopTrack;
39
39
  storage.events.track = noopTrack;
40
- if (storage.impressionCounts) storage.impressionCounts.track = noopTrack;
41
- if (storage.uniqueKeys) storage.uniqueKeys.track = noopTrack;
40
+ storage.impressionCounts.track = noopTrack;
41
+ storage.uniqueKeys.track = noopTrack;
42
42
  }
43
43
 
44
44
  return storage;
@@ -4,7 +4,7 @@ import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
4
4
  import { EventsCacheInMemory } from './EventsCacheInMemory';
5
5
  import { IStorageSync, IStorageFactoryParams } from '../types';
6
6
  import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
7
- import { DEBUG, LOCALHOST_MODE, NONE, STORAGE_MEMORY } from '../../utils/constants';
7
+ import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
8
8
  import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
9
9
  import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
10
10
 
@@ -14,7 +14,7 @@ import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
14
14
  * @param params - parameters required by EventsCacheSync
15
15
  */
16
16
  export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorageSync {
17
- const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation } } } = params;
17
+ const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize }, sync: { __splitFiltersValidation } } } = params;
18
18
 
19
19
  const splits = new SplitsCacheInMemory(__splitFiltersValidation);
20
20
  const segments = new MySegmentsCacheInMemory();
@@ -25,10 +25,10 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
25
25
  segments,
26
26
  largeSegments,
27
27
  impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
28
- impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
28
+ impressionCounts: new ImpressionCountsCacheInMemory(),
29
29
  events: new EventsCacheInMemory(eventsQueueSize),
30
30
  telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
31
- uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
31
+ uniqueKeys: new UniqueKeysCacheInMemoryCS(),
32
32
 
33
33
  destroy() { },
34
34
 
@@ -42,6 +42,7 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
42
42
  impressionCounts: this.impressionCounts,
43
43
  events: this.events,
44
44
  telemetry: this.telemetry,
45
+ uniqueKeys: this.uniqueKeys,
45
46
 
46
47
  destroy() { }
47
48
  };
@@ -54,8 +55,8 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
54
55
  const noopTrack = () => true;
55
56
  storage.impressions.track = noopTrack;
56
57
  storage.events.track = noopTrack;
57
- if (storage.impressionCounts) storage.impressionCounts.track = noopTrack;
58
- if (storage.uniqueKeys) storage.uniqueKeys.track = noopTrack;
58
+ storage.impressionCounts.track = noopTrack;
59
+ storage.uniqueKeys.track = noopTrack;
59
60
  }
60
61
 
61
62
  return storage;
@@ -6,7 +6,7 @@ import { SplitsCacheInRedis } from './SplitsCacheInRedis';
6
6
  import { SegmentsCacheInRedis } from './SegmentsCacheInRedis';
7
7
  import { ImpressionsCacheInRedis } from './ImpressionsCacheInRedis';
8
8
  import { EventsCacheInRedis } from './EventsCacheInRedis';
9
- import { DEBUG, NONE, STORAGE_REDIS } from '../../utils/constants';
9
+ import { STORAGE_REDIS } from '../../utils/constants';
10
10
  import { TelemetryCacheInRedis } from './TelemetryCacheInRedis';
11
11
  import { UniqueKeysCacheInRedis } from './UniqueKeysCacheInRedis';
12
12
  import { ImpressionCountsCacheInRedis } from './ImpressionCountsCacheInRedis';
@@ -30,19 +30,19 @@ export function InRedisStorage(options: InRedisStorageOptions = {}): IStorageAsy
30
30
  const prefix = validatePrefix(options.prefix);
31
31
 
32
32
  function InRedisStorageFactory(params: IStorageFactoryParams): IStorageAsync {
33
- const { onReadyCb, settings, settings: { log, sync: { impressionsMode } } } = params;
33
+ const { onReadyCb, settings, settings: { log } } = params;
34
34
  const metadata = metadataBuilder(settings);
35
35
  const keys = new KeyBuilderSS(prefix, metadata);
36
36
  const redisClient: RedisAdapter = new RD(log, options.options || {});
37
37
  const telemetry = new TelemetryCacheInRedis(log, keys, redisClient);
38
- const impressionCountsCache = impressionsMode !== DEBUG ? new ImpressionCountsCacheInRedis(log, keys.buildImpressionsCountKey(), redisClient) : undefined;
39
- const uniqueKeysCache = impressionsMode === NONE ? new UniqueKeysCacheInRedis(log, keys.buildUniqueKeysKey(), redisClient) : undefined;
38
+ const impressionCountsCache = new ImpressionCountsCacheInRedis(log, keys.buildImpressionsCountKey(), redisClient);
39
+ const uniqueKeysCache = new UniqueKeysCacheInRedis(log, keys.buildUniqueKeysKey(), redisClient);
40
40
 
41
41
  // subscription to Redis connect event in order to emit SDK_READY event on consumer mode
42
42
  redisClient.on('connect', () => {
43
43
  onReadyCb();
44
- if (impressionCountsCache) impressionCountsCache.start();
45
- if (uniqueKeysCache) uniqueKeysCache.start();
44
+ impressionCountsCache.start();
45
+ uniqueKeysCache.start();
46
46
 
47
47
  // Synchronize config
48
48
  telemetry.recordConfig();
@@ -60,10 +60,10 @@ export function InRedisStorage(options: InRedisStorageOptions = {}): IStorageAsy
60
60
  // When using REDIS we should:
61
61
  // 1- Disconnect from the storage
62
62
  destroy(): Promise<void> {
63
- let promises = [];
64
- if (impressionCountsCache) promises.push(impressionCountsCache.stop());
65
- if (uniqueKeysCache) promises.push(uniqueKeysCache.stop());
66
- return Promise.all(promises).then(() => { redisClient.disconnect(); });
63
+ return Promise.all([
64
+ impressionCountsCache.stop(),
65
+ uniqueKeysCache.stop()
66
+ ]).then(() => { redisClient.disconnect(); });
67
67
  // @TODO check that caches works as expected when redisClient is disconnected
68
68
  }
69
69
  };
@@ -8,7 +8,7 @@ import { EventsCachePluggable } from './EventsCachePluggable';
8
8
  import { wrapperAdapter, METHODS_TO_PROMISE_WRAP } from './wrapperAdapter';
9
9
  import { isObject } from '../../utils/lang';
10
10
  import { getStorageHash, validatePrefix } from '../KeyBuilder';
11
- import { CONSUMER_PARTIAL_MODE, DEBUG, NONE, STORAGE_PLUGGABLE } from '../../utils/constants';
11
+ import { CONSUMER_PARTIAL_MODE, STORAGE_PLUGGABLE } from '../../utils/constants';
12
12
  import { ImpressionsCacheInMemory } from '../inMemory/ImpressionsCacheInMemory';
13
13
  import { EventsCacheInMemory } from '../inMemory/EventsCacheInMemory';
14
14
  import { ImpressionCountsCacheInMemory } from '../inMemory/ImpressionCountsCacheInMemory';
@@ -63,35 +63,31 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
63
63
  const prefix = validatePrefix(options.prefix);
64
64
 
65
65
  function PluggableStorageFactory(params: IStorageFactoryParams): IStorageAsync {
66
- const { onReadyCb, settings, settings: { log, mode, sync: { impressionsMode }, scheduler: { impressionsQueueSize, eventsQueueSize } } } = params;
66
+ const { onReadyCb, settings, settings: { log, mode, scheduler: { impressionsQueueSize, eventsQueueSize } } } = params;
67
67
  const metadata = metadataBuilder(settings);
68
68
  const keys = new KeyBuilderSS(prefix, metadata);
69
69
  const wrapper = wrapperAdapter(log, options.wrapper);
70
70
 
71
- const isSyncronizer = mode === undefined; // If mode is not defined, the synchronizer is running
71
+ const isSynchronizer = mode === undefined; // If mode is not defined, the synchronizer is running
72
72
  const isPartialConsumer = mode === CONSUMER_PARTIAL_MODE;
73
73
 
74
- const telemetry = shouldRecordTelemetry(params) || isSyncronizer ?
74
+ const telemetry = shouldRecordTelemetry(params) || isSynchronizer ?
75
75
  isPartialConsumer ?
76
76
  new TelemetryCacheInMemory() :
77
77
  new TelemetryCachePluggable(log, keys, wrapper) :
78
78
  undefined;
79
79
 
80
- const impressionCountsCache = impressionsMode !== DEBUG || isSyncronizer ?
81
- isPartialConsumer ?
82
- new ImpressionCountsCacheInMemory() :
83
- new ImpressionCountsCachePluggable(log, keys.buildImpressionsCountKey(), wrapper) :
84
- undefined;
80
+ const impressionCountsCache = isPartialConsumer ?
81
+ new ImpressionCountsCacheInMemory() :
82
+ new ImpressionCountsCachePluggable(log, keys.buildImpressionsCountKey(), wrapper);
85
83
 
86
- const uniqueKeysCache = impressionsMode === NONE || isSyncronizer ?
87
- isPartialConsumer ?
88
- settings.core.key === undefined ? new UniqueKeysCacheInMemory() : new UniqueKeysCacheInMemoryCS() :
89
- new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper) :
90
- undefined;
84
+ const uniqueKeysCache = isPartialConsumer ?
85
+ settings.core.key === undefined ? new UniqueKeysCacheInMemory() : new UniqueKeysCacheInMemoryCS() :
86
+ new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper);
91
87
 
92
88
  // Connects to wrapper and emits SDK_READY event on main client
93
89
  const connectPromise = wrapper.connect().then(() => {
94
- if (isSyncronizer) {
90
+ if (isSynchronizer) {
95
91
  // @TODO reuse InLocalStorage::validateCache logic
96
92
  // In standalone or producer mode, clear storage if SDK key, flags filter criteria or flags spec version was modified
97
93
  return wrapper.get(keys.buildHashKey()).then((hash) => {
@@ -107,8 +103,8 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
107
103
  });
108
104
  } else {
109
105
  // Start periodic flush of async storages if not running synchronizer (producer mode)
110
- if (impressionCountsCache && (impressionCountsCache as ImpressionCountsCachePluggable).start) (impressionCountsCache as ImpressionCountsCachePluggable).start();
111
- if (uniqueKeysCache && (uniqueKeysCache as UniqueKeysCachePluggable).start) (uniqueKeysCache as UniqueKeysCachePluggable).start();
106
+ if ((impressionCountsCache as ImpressionCountsCachePluggable).start) (impressionCountsCache as ImpressionCountsCachePluggable).start();
107
+ if ((uniqueKeysCache as UniqueKeysCachePluggable).start) (uniqueKeysCache as UniqueKeysCachePluggable).start();
112
108
  if (telemetry && (telemetry as ITelemetryCacheAsync).recordConfig) (telemetry as ITelemetryCacheAsync).recordConfig();
113
109
 
114
110
  onReadyCb();
@@ -130,9 +126,9 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
130
126
 
131
127
  // Stop periodic flush and disconnect the underlying storage
132
128
  destroy() {
133
- return Promise.all(isSyncronizer ? [] : [
134
- impressionCountsCache && (impressionCountsCache as ImpressionCountsCachePluggable).stop && (impressionCountsCache as ImpressionCountsCachePluggable).stop(),
135
- uniqueKeysCache && (uniqueKeysCache as UniqueKeysCachePluggable).stop && (uniqueKeysCache as UniqueKeysCachePluggable).stop(),
129
+ return Promise.all(isSynchronizer ? [] : [
130
+ (impressionCountsCache as ImpressionCountsCachePluggable).stop && (impressionCountsCache as ImpressionCountsCachePluggable).stop(),
131
+ (uniqueKeysCache as UniqueKeysCachePluggable).stop && (uniqueKeysCache as UniqueKeysCachePluggable).stop(),
136
132
  ]).then(() => wrapper.disconnect());
137
133
  },
138
134
 
@@ -435,10 +435,10 @@ export interface IStorageBase<
435
435
  splits: TSplitsCache,
436
436
  segments: TSegmentsCache,
437
437
  impressions: TImpressionsCache,
438
- impressionCounts?: TImpressionsCountCache,
438
+ impressionCounts: TImpressionsCountCache,
439
439
  events: TEventsCache,
440
440
  telemetry?: TTelemetryCache,
441
- uniqueKeys?: TUniqueKeysCache,
441
+ uniqueKeys: TUniqueKeysCache,
442
442
  destroy(): void | Promise<void>,
443
443
  shared?: (matchingKey: string, onReadyCb: (error?: any) => void) => this
444
444
  }
@@ -39,8 +39,6 @@ export function impressionCountsSubmitterFactory(params: ISdkFactoryContextSync)
39
39
  storage: { impressionCounts }
40
40
  } = params;
41
41
 
42
- if (impressionCounts) {
43
- // retry impressions counts only once.
44
- return submitterFactory(log, postTestImpressionsCount, impressionCounts, IMPRESSIONS_COUNT_RATE, 'impression counts', fromImpressionCountsCollector, 1);
45
- }
42
+ // retry impressions counts only once.
43
+ return submitterFactory(log, postTestImpressionsCount, impressionCounts, IMPRESSIONS_COUNT_RATE, 'impression counts', fromImpressionCountsCollector, 1);
46
44
  }
@@ -10,13 +10,12 @@ export function submitterManagerFactory(params: ISdkFactoryContextSync): ISubmit
10
10
 
11
11
  const submitters = [
12
12
  impressionsSubmitterFactory(params),
13
- eventsSubmitterFactory(params)
13
+ eventsSubmitterFactory(params),
14
+ impressionCountsSubmitterFactory(params),
15
+ uniqueKeysSubmitterFactory(params)
14
16
  ];
15
17
 
16
- const impressionCountsSubmitter = impressionCountsSubmitterFactory(params);
17
- if (impressionCountsSubmitter) submitters.push(impressionCountsSubmitter);
18
18
  const telemetrySubmitter = telemetrySubmitterFactory(params);
19
- if (params.storage.uniqueKeys) submitters.push(uniqueKeysSubmitterFactory(params));
20
19
 
21
20
  return {
22
21
  // `onlyTelemetry` true if SDK is created with userConsent not GRANTED