@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
@@ -19,10 +19,10 @@ export function uniqueKeysSubmitterFactory(params: ISdkFactoryContextSync) {
19
19
  const isClientSide = key !== undefined;
20
20
  const postUniqueKeysBulk = isClientSide ? postUniqueKeysBulkCs : postUniqueKeysBulkSs;
21
21
 
22
- const syncTask = submitterFactory(log, postUniqueKeysBulk, uniqueKeys!, UNIQUE_KEYS_RATE, DATA_NAME);
22
+ const syncTask = submitterFactory(log, postUniqueKeysBulk, uniqueKeys, UNIQUE_KEYS_RATE, DATA_NAME);
23
23
 
24
24
  // register unique keys submitter to be executed when uniqueKeys cache is full
25
- uniqueKeys!.setOnFullQueueCb(() => {
25
+ uniqueKeys.setOnFullQueueCb(() => {
26
26
  if (syncTask.isRunning()) {
27
27
  log.info(SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
28
28
  syncTask.execute();
@@ -33,4 +33,3 @@ export function uniqueKeysSubmitterFactory(params: ISdkFactoryContextSync) {
33
33
 
34
34
  return syncTask;
35
35
  }
36
-
@@ -1,7 +1,7 @@
1
1
  import { objectAssign } from '../utils/lang/objectAssign';
2
2
  import { thenable } from '../utils/promise/thenable';
3
3
  import { IImpressionsCacheBase, ITelemetryCacheSync, ITelemetryCacheAsync } from '../storages/types';
4
- import { IImpressionsHandler, IImpressionsTracker, IStrategy } from './types';
4
+ import { IImpressionsHandler, IImpressionsTracker, ImpressionDecorated, IStrategy } from './types';
5
5
  import { ISettings } from '../types';
6
6
  import { IMPRESSIONS_TRACKER_SUCCESS, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER } from '../logger/constants';
7
7
  import { CONSENT_DECLINED, DEDUPED, QUEUED } from '../utils/constants';
@@ -9,16 +9,11 @@ import SplitIO from '../../types/splitio';
9
9
 
10
10
  /**
11
11
  * Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided.
12
- *
13
- * @param impressionsCache - cache to save impressions
14
- * @param metadata - runtime metadata (ip, hostname and version)
15
- * @param impressionListener - optional impression listener
16
- * @param integrationsManager - optional integrations manager
17
- * @param strategy - strategy for impressions tracking.
18
12
  */
19
13
  export function impressionsTrackerFactory(
20
14
  settings: ISettings,
21
15
  impressionsCache: IImpressionsCacheBase,
16
+ noneStrategy: IStrategy,
22
17
  strategy: IStrategy,
23
18
  whenInit: (cb: () => void) => void,
24
19
  integrationsManager?: IImpressionsHandler,
@@ -28,40 +23,44 @@ export function impressionsTrackerFactory(
28
23
  const { log, impressionListener, runtime: { ip, hostname }, version } = settings;
29
24
 
30
25
  return {
31
- track(impressions: SplitIO.ImpressionDTO[], attributes?: SplitIO.Attributes) {
26
+ track(impressions: ImpressionDecorated[], attributes?: SplitIO.Attributes) {
32
27
  if (settings.userConsent === CONSENT_DECLINED) return;
33
28
 
34
- const impressionsCount = impressions.length;
35
- const { impressionsToStore, impressionsToListener, deduped } = strategy.process(impressions);
29
+ const impressionsToStore = impressions.filter(({ imp, disabled }) => {
30
+ return disabled ?
31
+ noneStrategy.process(imp) :
32
+ strategy.process(imp);
33
+ });
36
34
 
37
- const impressionsToListenerCount = impressionsToListener.length;
35
+ const impressionsLength = impressions.length;
36
+ const impressionsToStoreLength = impressionsToStore.length;
38
37
 
39
- if (impressionsToStore.length > 0) {
40
- const res = impressionsCache.track(impressionsToStore);
38
+ if (impressionsToStoreLength) {
39
+ const res = impressionsCache.track(impressionsToStore.map((item) => item.imp));
41
40
 
42
41
  // If we're on an async storage, handle error and log it.
43
42
  if (thenable(res)) {
44
43
  res.then(() => {
45
- log.info(IMPRESSIONS_TRACKER_SUCCESS, [impressionsCount]);
44
+ log.info(IMPRESSIONS_TRACKER_SUCCESS, [impressionsLength]);
46
45
  }).catch(err => {
47
- log.error(ERROR_IMPRESSIONS_TRACKER, [impressionsCount, err]);
46
+ log.error(ERROR_IMPRESSIONS_TRACKER, [impressionsLength, err]);
48
47
  });
49
48
  } else {
50
49
  // Record when impressionsCache is sync only (standalone mode)
51
50
  // @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
52
51
  if (telemetryCache) {
53
- (telemetryCache as ITelemetryCacheSync).recordImpressionStats(QUEUED, impressionsToStore.length);
54
- (telemetryCache as ITelemetryCacheSync).recordImpressionStats(DEDUPED, deduped);
52
+ (telemetryCache as ITelemetryCacheSync).recordImpressionStats(QUEUED, impressionsToStoreLength);
53
+ (telemetryCache as ITelemetryCacheSync).recordImpressionStats(DEDUPED, impressionsLength - impressionsToStoreLength);
55
54
  }
56
55
  }
57
56
  }
58
57
 
59
58
  // @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
60
59
  if (impressionListener || integrationsManager) {
61
- for (let i = 0; i < impressionsToListenerCount; i++) {
60
+ for (let i = 0; i < impressionsLength; i++) {
62
61
  const impressionData: SplitIO.ImpressionData = {
63
62
  // copy of impression, to avoid unexpected behavior if modified by integrations or impressionListener
64
- impression: objectAssign({}, impressionsToListener[i]),
63
+ impression: objectAssign({}, impressions[i].imp),
65
64
  attributes,
66
65
  ip,
67
66
  hostname,
@@ -6,23 +6,16 @@ import { IStrategy } from '../types';
6
6
  * Debug strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
7
7
  *
8
8
  * @param impressionsObserver - impression observer. Previous time (pt property) is included in impression instances
9
- * @returns IStrategyResult
9
+ * @returns Debug strategy
10
10
  */
11
11
  export function strategyDebugFactory(
12
12
  impressionsObserver: IImpressionObserver
13
13
  ): IStrategy {
14
14
 
15
15
  return {
16
- process(impressions: SplitIO.ImpressionDTO[]) {
17
- impressions.forEach((impression) => {
18
- // Adds previous time if it is enabled
19
- impression.pt = impressionsObserver.testAndSet(impression);
20
- });
21
- return {
22
- impressionsToStore: impressions,
23
- impressionsToListener: impressions,
24
- deduped: 0
25
- };
16
+ process(impression: SplitIO.ImpressionDTO) {
17
+ impression.pt = impressionsObserver.testAndSet(impression);
18
+ return true;
26
19
  }
27
20
  };
28
21
  }
@@ -5,30 +5,24 @@ import { IStrategy, IUniqueKeysTracker } from '../types';
5
5
  /**
6
6
  * None strategy for impressions tracker.
7
7
  *
8
- * @param impressionsCounter - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
8
+ * @param impressionCounts - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
9
9
  * @param uniqueKeysTracker - unique keys tracker in charge of tracking the unique keys per split.
10
- * @returns IStrategyResult
10
+ * @returns None strategy
11
11
  */
12
12
  export function strategyNoneFactory(
13
- impressionsCounter: IImpressionCountsCacheBase,
13
+ impressionCounts: IImpressionCountsCacheBase,
14
14
  uniqueKeysTracker: IUniqueKeysTracker
15
15
  ): IStrategy {
16
16
 
17
17
  return {
18
- process(impressions: SplitIO.ImpressionDTO[]) {
19
- impressions.forEach((impression) => {
20
- const now = Date.now();
21
- // Increments impression counter per featureName
22
- impressionsCounter.track(impression.feature, now, 1);
23
- // Keep track by unique key
24
- uniqueKeysTracker.track(impression.keyName, impression.feature);
25
- });
26
-
27
- return {
28
- impressionsToStore: [],
29
- impressionsToListener: impressions,
30
- deduped: 0
31
- };
18
+ process(impression: SplitIO.ImpressionDTO) {
19
+ const now = Date.now();
20
+ // Increments impression counter per featureName
21
+ impressionCounts.track(impression.feature, now, 1);
22
+ // Keep track by unique key
23
+ uniqueKeysTracker.track(impression.keyName, impression.feature);
24
+ // Do not store impressions
25
+ return false;
32
26
  }
33
27
  };
34
28
  }
@@ -8,35 +8,25 @@ import { IStrategy } from '../types';
8
8
  * Optimized strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
9
9
  *
10
10
  * @param impressionsObserver - impression observer. previous time (pt property) is included in impression instances
11
- * @param impressionsCounter - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
12
- * @returns IStrategyResult
11
+ * @param impressionCounts - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
12
+ * @returns Optimized strategy
13
13
  */
14
14
  export function strategyOptimizedFactory(
15
15
  impressionsObserver: IImpressionObserver,
16
- impressionsCounter: IImpressionCountsCacheBase,
16
+ impressionCounts: IImpressionCountsCacheBase,
17
17
  ): IStrategy {
18
18
 
19
19
  return {
20
- process(impressions: SplitIO.ImpressionDTO[]) {
21
- const impressionsToStore: SplitIO.ImpressionDTO[] = [];
22
- impressions.forEach((impression) => {
23
- impression.pt = impressionsObserver.testAndSet(impression);
20
+ process(impression: SplitIO.ImpressionDTO) {
21
+ impression.pt = impressionsObserver.testAndSet(impression);
24
22
 
25
- const now = Date.now();
23
+ const now = Date.now();
26
24
 
27
- // Increments impression counter per featureName
28
- if (impression.pt) impressionsCounter.track(impression.feature, now, 1);
25
+ // Increments impression counter per featureName
26
+ if (impression.pt) impressionCounts.track(impression.feature, now, 1);
29
27
 
30
- // Checks if the impression should be added in queue to be sent
31
- if (!impression.pt || impression.pt < truncateTimeFrame(now)) {
32
- impressionsToStore.push(impression);
33
- }
34
- });
35
- return {
36
- impressionsToStore: impressionsToStore,
37
- impressionsToListener: impressions,
38
- deduped: impressions.length - impressionsToStore.length
39
- };
28
+ // Checks if the impression should be added in queue to be sent
29
+ return (!impression.pt || impression.pt < truncateTimeFrame(now)) ? true : false;
40
30
  }
41
31
  };
42
32
  }
@@ -17,8 +17,19 @@ export interface IImpressionsHandler {
17
17
  handleImpression(impressionData: SplitIO.ImpressionData): any
18
18
  }
19
19
 
20
+ export type ImpressionDecorated = {
21
+ /**
22
+ * Impression DTO
23
+ */
24
+ imp: SplitIO.ImpressionDTO,
25
+ /**
26
+ * Whether the impression should be tracked or not
27
+ */
28
+ disabled?: boolean
29
+ };
30
+
20
31
  export interface IImpressionsTracker {
21
- track(impressions: SplitIO.ImpressionDTO[], attributes?: SplitIO.Attributes): void
32
+ track(impressions: ImpressionDecorated[], attributes?: SplitIO.Attributes): void
22
33
  }
23
34
 
24
35
  /** Telemetry tracker */
@@ -70,12 +81,6 @@ export interface IUniqueKeysTracker {
70
81
  track(key: string, featureName: string): void;
71
82
  }
72
83
 
73
- export interface IStrategyResult {
74
- impressionsToStore: SplitIO.ImpressionDTO[],
75
- impressionsToListener: SplitIO.ImpressionDTO[],
76
- deduped: number
77
- }
78
-
79
84
  export interface IStrategy {
80
- process(impressions: SplitIO.ImpressionDTO[]): IStrategyResult
85
+ process(impression: SplitIO.ImpressionDTO): boolean
81
86
  }
@@ -862,6 +862,10 @@ declare namespace SplitIO {
862
862
  * The default treatment of the feature flag.
863
863
  */
864
864
  defaultTreatment: string;
865
+ /**
866
+ * Whether the feature flag has impressions tracking disabled or not.
867
+ */
868
+ impressionsDisabled: boolean;
865
869
  };
866
870
  /**
867
871
  * A promise that resolves to a feature flag view or null if the feature flag is not found.