@splitsoftware/splitio-commons 1.16.1-rc.8 → 1.17.0-rc.1

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 (167) hide show
  1. package/CHANGES.txt +2 -1
  2. package/cjs/evaluator/matchers/index.js +1 -3
  3. package/cjs/evaluator/matchers/matcherTypes.js +0 -1
  4. package/cjs/evaluator/matchersTransform/index.js +1 -1
  5. package/cjs/logger/constants.js +4 -3
  6. package/cjs/logger/messages/info.js +2 -1
  7. package/cjs/readiness/readinessManager.js +10 -14
  8. package/cjs/readiness/sdkReadinessManager.js +6 -5
  9. package/cjs/sdkClient/sdkClientMethodCS.js +2 -2
  10. package/cjs/sdkClient/sdkClientMethodCSWithTT.js +2 -2
  11. package/cjs/sdkFactory/index.js +1 -1
  12. package/cjs/services/decorateHeaders.js +43 -0
  13. package/cjs/services/splitApi.js +0 -4
  14. package/cjs/services/splitHttpClient.js +5 -4
  15. package/cjs/storages/AbstractSplitsCacheAsync.js +2 -2
  16. package/cjs/storages/AbstractSplitsCacheSync.js +6 -5
  17. package/cjs/storages/KeyBuilder.js +0 -3
  18. package/cjs/storages/KeyBuilderCS.js +5 -17
  19. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +4 -16
  20. package/cjs/storages/inLocalStorage/index.js +2 -6
  21. package/cjs/storages/inMemory/InMemoryStorageCS.js +0 -5
  22. package/cjs/storages/inMemory/SplitsCacheInMemory.js +11 -20
  23. package/cjs/storages/inMemory/TelemetryCacheInMemory.js +10 -7
  24. package/cjs/storages/pluggable/inMemoryWrapper.js +1 -1
  25. package/cjs/sync/polling/fetchers/mySegmentsFetcher.js +1 -5
  26. package/cjs/sync/polling/pollingManagerCS.js +33 -51
  27. package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
  28. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +21 -20
  29. package/cjs/sync/streaming/SSEClient/index.js +9 -12
  30. package/cjs/sync/streaming/SSEHandler/index.js +0 -1
  31. package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +9 -23
  32. package/cjs/sync/streaming/constants.js +1 -2
  33. package/cjs/sync/streaming/parseUtils.js +8 -3
  34. package/cjs/sync/streaming/pushManager.js +69 -100
  35. package/cjs/sync/submitters/telemetrySubmitter.js +0 -4
  36. package/cjs/sync/syncManagerOnline.js +14 -24
  37. package/cjs/utils/constants/index.js +2 -4
  38. package/cjs/utils/settingsValidation/index.js +2 -7
  39. package/esm/evaluator/matchers/index.js +1 -3
  40. package/esm/evaluator/matchers/matcherTypes.js +0 -1
  41. package/esm/evaluator/matchersTransform/index.js +1 -1
  42. package/esm/logger/constants.js +1 -0
  43. package/esm/logger/messages/info.js +2 -1
  44. package/esm/readiness/readinessManager.js +10 -14
  45. package/esm/readiness/sdkReadinessManager.js +6 -5
  46. package/esm/sdkClient/sdkClientMethodCS.js +2 -2
  47. package/esm/sdkClient/sdkClientMethodCSWithTT.js +2 -2
  48. package/esm/sdkFactory/index.js +1 -1
  49. package/esm/services/decorateHeaders.js +39 -0
  50. package/esm/services/splitApi.js +1 -5
  51. package/esm/services/splitHttpClient.js +5 -4
  52. package/esm/storages/AbstractSplitsCacheAsync.js +2 -2
  53. package/esm/storages/AbstractSplitsCacheSync.js +4 -3
  54. package/esm/storages/KeyBuilder.js +0 -3
  55. package/esm/storages/KeyBuilderCS.js +4 -15
  56. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +5 -17
  57. package/esm/storages/inLocalStorage/index.js +3 -7
  58. package/esm/storages/inMemory/InMemoryStorageCS.js +0 -5
  59. package/esm/storages/inMemory/SplitsCacheInMemory.js +12 -21
  60. package/esm/storages/inMemory/TelemetryCacheInMemory.js +10 -7
  61. package/esm/storages/pluggable/inMemoryWrapper.js +1 -1
  62. package/esm/sync/polling/fetchers/mySegmentsFetcher.js +1 -5
  63. package/esm/sync/polling/pollingManagerCS.js +34 -52
  64. package/esm/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
  65. package/esm/sync/polling/updaters/mySegmentsUpdater.js +19 -18
  66. package/esm/sync/streaming/SSEClient/index.js +10 -13
  67. package/esm/sync/streaming/SSEHandler/index.js +1 -2
  68. package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +9 -23
  69. package/esm/sync/streaming/constants.js +0 -1
  70. package/esm/sync/streaming/parseUtils.js +8 -3
  71. package/esm/sync/streaming/pushManager.js +70 -100
  72. package/esm/sync/submitters/telemetrySubmitter.js +0 -4
  73. package/esm/sync/syncManagerOnline.js +15 -25
  74. package/esm/utils/constants/index.js +1 -3
  75. package/esm/utils/settingsValidation/index.js +2 -7
  76. package/package.json +1 -1
  77. package/src/dtos/types.ts +7 -17
  78. package/src/evaluator/matchers/index.ts +0 -2
  79. package/src/evaluator/matchers/matcherTypes.ts +0 -1
  80. package/src/evaluator/matchersTransform/index.ts +1 -1
  81. package/src/logger/constants.ts +1 -0
  82. package/src/logger/messages/info.ts +2 -1
  83. package/src/readiness/readinessManager.ts +9 -13
  84. package/src/readiness/sdkReadinessManager.ts +7 -7
  85. package/src/readiness/types.ts +2 -3
  86. package/src/sdkClient/sdkClientMethodCS.ts +2 -2
  87. package/src/sdkClient/sdkClientMethodCSWithTT.ts +2 -2
  88. package/src/sdkFactory/index.ts +1 -1
  89. package/src/services/decorateHeaders.ts +41 -0
  90. package/src/services/splitApi.ts +2 -7
  91. package/src/services/splitHttpClient.ts +6 -5
  92. package/src/services/types.ts +0 -1
  93. package/src/storages/AbstractSplitsCacheAsync.ts +2 -2
  94. package/src/storages/AbstractSplitsCacheSync.ts +5 -4
  95. package/src/storages/KeyBuilder.ts +0 -3
  96. package/src/storages/KeyBuilderCS.ts +5 -25
  97. package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +3 -3
  98. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +5 -20
  99. package/src/storages/inLocalStorage/index.ts +4 -8
  100. package/src/storages/inMemory/InMemoryStorageCS.ts +0 -5
  101. package/src/storages/inMemory/SplitsCacheInMemory.ts +10 -15
  102. package/src/storages/inMemory/TelemetryCacheInMemory.ts +11 -7
  103. package/src/storages/pluggable/inMemoryWrapper.ts +1 -1
  104. package/src/storages/types.ts +5 -7
  105. package/src/sync/polling/fetchers/mySegmentsFetcher.ts +2 -6
  106. package/src/sync/polling/pollingManagerCS.ts +29 -61
  107. package/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +10 -10
  108. package/src/sync/polling/types.ts +3 -4
  109. package/src/sync/polling/updaters/mySegmentsUpdater.ts +20 -17
  110. package/src/sync/streaming/SSEClient/index.ts +14 -20
  111. package/src/sync/streaming/SSEHandler/index.ts +1 -2
  112. package/src/sync/streaming/SSEHandler/types.ts +2 -14
  113. package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +10 -26
  114. package/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts +1 -1
  115. package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +1 -1
  116. package/src/sync/streaming/UpdateWorkers/types.ts +2 -2
  117. package/src/sync/streaming/constants.ts +0 -1
  118. package/src/sync/streaming/parseUtils.ts +10 -6
  119. package/src/sync/streaming/pushManager.ts +68 -104
  120. package/src/sync/streaming/types.ts +3 -5
  121. package/src/sync/submitters/telemetrySubmitter.ts +0 -4
  122. package/src/sync/submitters/types.ts +4 -11
  123. package/src/sync/syncManagerOnline.ts +11 -19
  124. package/src/types.ts +9 -28
  125. package/src/utils/constants/index.ts +1 -3
  126. package/src/utils/settingsValidation/index.ts +3 -8
  127. package/src/utils/settingsValidation/types.ts +1 -1
  128. package/types/dtos/types.d.ts +6 -14
  129. package/types/logger/constants.d.ts +1 -0
  130. package/types/readiness/readinessManager.d.ts +2 -2
  131. package/types/readiness/sdkReadinessManager.d.ts +3 -2
  132. package/types/readiness/types.d.ts +2 -3
  133. package/types/services/decorateHeaders.d.ts +2 -0
  134. package/types/services/splitApi.d.ts +1 -1
  135. package/types/services/splitHttpClient.d.ts +1 -1
  136. package/types/services/types.d.ts +0 -1
  137. package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
  138. package/types/storages/AbstractSplitsCacheSync.d.ts +3 -3
  139. package/types/storages/KeyBuilder.d.ts +0 -1
  140. package/types/storages/KeyBuilderCS.d.ts +2 -7
  141. package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +2 -2
  142. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +1 -1
  143. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +2 -3
  144. package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +6 -4
  145. package/types/storages/pluggable/inMemoryWrapper.d.ts +1 -1
  146. package/types/storages/types.d.ts +3 -4
  147. package/types/sync/polling/syncTasks/mySegmentsSyncTask.d.ts +3 -2
  148. package/types/sync/polling/types.d.ts +3 -10
  149. package/types/sync/polling/updaters/mySegmentsUpdater.d.ts +4 -4
  150. package/types/sync/streaming/SSEClient/index.d.ts +2 -5
  151. package/types/sync/streaming/SSEHandler/types.d.ts +2 -13
  152. package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +2 -3
  153. package/types/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.d.ts +1 -2
  154. package/types/sync/streaming/UpdateWorkers/SplitsUpdateWorker.d.ts +2 -3
  155. package/types/sync/streaming/UpdateWorkers/types.d.ts +2 -2
  156. package/types/sync/streaming/constants.d.ts +0 -1
  157. package/types/sync/streaming/parseUtils.d.ts +4 -2
  158. package/types/sync/streaming/pushManager.d.ts +0 -2
  159. package/types/sync/streaming/types.d.ts +4 -5
  160. package/types/sync/submitters/types.d.ts +3 -10
  161. package/types/types.d.ts +11 -26
  162. package/types/utils/constants/index.d.ts +1 -3
  163. package/types/utils/settingsValidation/index.d.ts +0 -2
  164. package/types/utils/settingsValidation/types.d.ts +1 -1
  165. package/cjs/evaluator/matchers/large_segment.js +0 -16
  166. package/esm/evaluator/matchers/large_segment.js +0 -12
  167. package/src/evaluator/matchers/large_segment.ts +0 -18
@@ -1,21 +1,19 @@
1
1
  import { IMySegmentsSyncTask, MySegmentsData } from '../../polling/types';
2
2
  import { Backoff } from '../../../utils/Backoff';
3
3
  import { IUpdateWorker } from './types';
4
+ import { MY_SEGMENT } from '../../../utils/constants';
4
5
  import { ITelemetryTracker } from '../../../trackers/types';
5
- import { UpdatesFromSSEEnum } from '../../submitters/types';
6
6
 
7
7
  /**
8
8
  * MySegmentsUpdateWorker factory
9
9
  */
10
- export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask, telemetryTracker: ITelemetryTracker, updateType: UpdatesFromSSEEnum): IUpdateWorker<[changeNumber: number, segmentsData?: MySegmentsData, delay?: number]> {
10
+ export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask, telemetryTracker: ITelemetryTracker): IUpdateWorker {
11
11
 
12
12
  let maxChangeNumber = 0; // keeps the maximum changeNumber among queued events
13
13
  let currentChangeNumber = -1;
14
14
  let handleNewEvent = false;
15
15
  let isHandlingEvent: boolean;
16
16
  let _segmentsData: MySegmentsData | undefined; // keeps the segmentsData (if included in notification payload) from the queued event with maximum changeNumber
17
- let _delay: undefined | number;
18
- let _delayTimeoutID: any;
19
17
  const backoff = new Backoff(__handleMySegmentsUpdateCall);
20
18
 
21
19
  function __handleMySegmentsUpdateCall() {
@@ -25,19 +23,10 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask,
25
23
  const currentMaxChangeNumber = maxChangeNumber;
26
24
 
27
25
  // fetch mySegments revalidating data if cached
28
- const syncTask = _delay ?
29
- new Promise(res => {
30
- _delayTimeoutID = setTimeout(() => {
31
- _delay = undefined;
32
- mySegmentsSyncTask.execute(_segmentsData, true).then(res);
33
- }, _delay);
34
- }) :
35
- mySegmentsSyncTask.execute(_segmentsData, true);
36
-
37
- syncTask.then((result) => {
26
+ mySegmentsSyncTask.execute(_segmentsData, true).then((result) => {
38
27
  if (!isHandlingEvent) return; // halt if `stop` has been called
39
- if (result !== false) { // Unlike `Splits|SegmentsUpdateWorker`, we cannot use `mySegmentsCache.getChangeNumber` since `/mySegments` endpoint doesn't provide this value.
40
- if (_segmentsData) telemetryTracker.trackUpdatesFromSSE(updateType);
28
+ if (result !== false) {// Unlike `Splits|SegmentsUpdateWorker`, we cannot use `mySegmentsCache.getChangeNumber` since `/mySegments` endpoint doesn't provide this value.
29
+ if (_segmentsData) telemetryTracker.trackUpdatesFromSSE(MY_SEGMENT);
41
30
  currentChangeNumber = Math.max(currentChangeNumber, currentMaxChangeNumber); // use `currentMaxChangeNumber`, in case that `maxChangeNumber` was updated during fetch.
42
31
  }
43
32
  if (handleNewEvent) {
@@ -53,28 +42,23 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask,
53
42
 
54
43
  return {
55
44
  /**
56
- * Invoked by NotificationProcessor on MY_(LARGE)_SEGMENTS_UPDATE notifications
45
+ * Invoked by NotificationProcessor on MY_SEGMENTS_UPDATE event
57
46
  *
58
- * @param changeNumber change number of the notification
59
- * @param segmentsData data for KeyList or SegmentRemoval instant updates
60
- * @param delay optional time to wait for BoundedFetchRequest or BoundedFetchRequest updates
47
+ * @param {number} changeNumber change number of the MY_SEGMENTS_UPDATE notification
48
+ * @param {SegmentsData | undefined} segmentsData might be undefined
61
49
  */
62
- put(changeNumber: number, segmentsData?: MySegmentsData, delay?: number) {
63
- // Ignore event if it is outdated or if there is a pending fetch request (_delay is set)
64
- if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber || _delay) return;
50
+ put(changeNumber: number, segmentsData?: MySegmentsData) {
51
+ if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber) return;
65
52
 
66
53
  maxChangeNumber = changeNumber;
67
54
  handleNewEvent = true;
68
55
  _segmentsData = segmentsData;
69
- _delay = delay;
70
56
 
71
57
  if (backoff.timeoutID || !isHandlingEvent) __handleMySegmentsUpdateCall();
72
58
  backoff.reset();
73
59
  },
74
60
 
75
61
  stop() {
76
- clearTimeout(_delayTimeoutID);
77
- _delay = undefined;
78
62
  isHandlingEvent = false;
79
63
  backoff.reset();
80
64
  }
@@ -9,7 +9,7 @@ import { IUpdateWorker } from './types';
9
9
  /**
10
10
  * SegmentsUpdateWorker factory
11
11
  */
12
- export function SegmentsUpdateWorker(log: ILogger, segmentsSyncTask: ISegmentsSyncTask, segmentsCache: ISegmentsCacheSync): IUpdateWorker<[ISegmentUpdateData]> {
12
+ export function SegmentsUpdateWorker(log: ILogger, segmentsSyncTask: ISegmentsSyncTask, segmentsCache: ISegmentsCacheSync): IUpdateWorker {
13
13
 
14
14
  // Handles retries with CDN bypass per segment name
15
15
  function SegmentUpdateWorker(segment: string) {
@@ -14,7 +14,7 @@ import { IUpdateWorker } from './types';
14
14
  /**
15
15
  * SplitsUpdateWorker factory
16
16
  */
17
- export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker<[updateData: ISplitUpdateData, payload?: ISplit]> & { killSplit(event: ISplitKillData): void } {
17
+ export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker & { killSplit(event: ISplitKillData): void } {
18
18
 
19
19
  let maxChangeNumber = 0;
20
20
  let handleNewEvent = false;
@@ -1,4 +1,4 @@
1
- export interface IUpdateWorker<T extends any[]> {
1
+ export interface IUpdateWorker {
2
2
  stop(): void // clear scheduled tasks (backoff)
3
- put(...args: T): void // handle new update event
3
+ put(...args: any[]): void // handle new update event
4
4
  }
@@ -30,7 +30,6 @@ export const MY_SEGMENTS_UPDATE_V2 = 'MY_SEGMENTS_UPDATE_V2';
30
30
  export const SEGMENT_UPDATE = 'SEGMENT_UPDATE';
31
31
  export const SPLIT_KILL = 'SPLIT_KILL';
32
32
  export const SPLIT_UPDATE = 'SPLIT_UPDATE';
33
- export const MY_LARGE_SEGMENTS_UPDATE = 'MY_LARGE_SEGMENTS_UPDATE';
34
33
 
35
34
  // Control-type push notifications, handled by NotificationKeeper
36
35
  export const CONTROL = 'CONTROL';
@@ -1,7 +1,6 @@
1
1
  import { algorithms } from '../../utils/decompress';
2
2
  import { decodeFromBase64 } from '../../utils/base64';
3
3
  import { Compression, KeyList } from './SSEHandler/types';
4
- import { ISplit } from '../../dtos/types';
5
4
 
6
5
  const GZIP = 1;
7
6
  const ZLIB = 2;
@@ -43,7 +42,7 @@ function decompress(data: string, compression: Compression) {
43
42
  * @returns {{a?: string[], r?: string[] }}
44
43
  * @throws if data string cannot be decoded, decompressed or parsed
45
44
  */
46
- export function parseKeyList(data: string, compression: Compression, avoidPrecisionLoss = true): KeyList {
45
+ export function parseKeyList(data: string, compression: Compression, avoidPrecisionLoss: boolean = true): KeyList {
47
46
  const binKeyList = decompress(data, compression);
48
47
  let strKeyList = Uint8ArrayToString(binKeyList);
49
48
  // replace numbers to strings, to avoid losing precision
@@ -81,9 +80,14 @@ export function isInBitmap(bitmap: Uint8Array, hash64hex: string) {
81
80
 
82
81
  /**
83
82
  * Parse feature flags notifications for instant feature flag updates
83
+ *
84
+ * @param {ISplitUpdateData} data
85
+ * @returns {KeyList}
84
86
  */
85
- export function parseFFUpdatePayload(compression: Compression, data: string): ISplit | undefined {
86
- return compression > 0 ?
87
- parseKeyList(data, compression, false) :
88
- JSON.parse(decodeFromBase64(data));
87
+ export function parseFFUpdatePayload(compression: Compression, data: string): KeyList | undefined {
88
+ const avoidPrecisionLoss = false;
89
+ if (compression > 0)
90
+ return parseKeyList(data, compression, avoidPrecisionLoss);
91
+ else
92
+ return JSON.parse(decodeFromBase64(data));
89
93
  }
@@ -11,25 +11,16 @@ import { authenticateFactory, hashUserKey } from './AuthClient';
11
11
  import { forOwn } from '../../utils/lang';
12
12
  import { SSEClient } from './SSEClient';
13
13
  import { getMatching } from '../../utils/key';
14
- import { MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType, MY_LARGE_SEGMENTS_UPDATE } from './constants';
14
+ import { MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
15
15
  import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, STREAMING_PARSING_SPLIT_UPDATE } from '../../logger/constants';
16
- import { IMyLargeSegmentsUpdateData, IMySegmentsUpdateV2Data, KeyList, UpdateStrategy } from './SSEHandler/types';
16
+ import { KeyList, UpdateStrategy } from './SSEHandler/types';
17
17
  import { isInBitmap, parseBitmap, parseFFUpdatePayload, parseKeyList } from './parseUtils';
18
18
  import { ISet, _Set } from '../../utils/lang/sets';
19
- import { hash } from '../../utils/murmur3/murmur3';
20
19
  import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
21
20
  import { IAuthTokenPushEnabled } from './AuthClient/types';
22
- import { TOKEN_REFRESH, AUTH_REJECTION, MY_LARGE_SEGMENT, MY_SEGMENT } from '../../utils/constants';
21
+ import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
23
22
  import { ISdkFactoryContextSync } from '../../sdkFactory/types';
24
-
25
- export function getDelay(parsedData: Pick<IMyLargeSegmentsUpdateData, 'i' | 'h' | 's'>, matchingKey: string) {
26
- if (parsedData.h === 0) return 0;
27
-
28
- const interval = parsedData.i || 60000;
29
- const seed = parsedData.s || 0;
30
-
31
- return hash(matchingKey, seed) % interval;
32
- }
23
+ import { IUpdateWorker } from './UpdateWorkers/types';
33
24
 
34
25
  /**
35
26
  * PushManager factory:
@@ -51,7 +42,7 @@ export function pushManagerFactory(
51
42
  let sseClient: ISSEClient;
52
43
  try {
53
44
  // `useHeaders` false for client-side, even if the platform EventSource supports headers (e.g., React Native).
54
- sseClient = new SSEClient(settings, userKey ? false : true, platform);
45
+ sseClient = new SSEClient(settings, platform);
55
46
  } catch (e) {
56
47
  log.warn(STREAMING_FALLBACK, [e]);
57
48
  return;
@@ -73,7 +64,7 @@ export function pushManagerFactory(
73
64
  const userKeyHashes: Record<string, string> = {};
74
65
  // [Only for client-side] map of user keys to their corresponding hash64 and MySegmentsUpdateWorkers.
75
66
  // Hash64 is used to process MY_SEGMENTS_UPDATE_V2 events and dispatch actions to the corresponding MySegmentsUpdateWorker.
76
- const clients: Record<string, { hash64: Hash64, worker: ReturnType<typeof MySegmentsUpdateWorker>, workerLarge?: ReturnType<typeof MySegmentsUpdateWorker> }> = {};
67
+ const clients: Record<string, { hash64: Hash64, worker: IUpdateWorker }> = {};
77
68
 
78
69
  // [Only for client-side] variable to flag that a new client was added. It is needed to reconnect streaming.
79
70
  let connectForNewClient = false;
@@ -180,10 +171,7 @@ export function pushManagerFactory(
180
171
  // cancel scheduled fetch retries of Splits, Segments, and MySegments Update Workers
181
172
  function stopWorkers() {
182
173
  splitsUpdateWorker.stop();
183
- if (userKey) forOwn(clients, ({ worker, workerLarge }) => {
184
- worker.stop();
185
- workerLarge && workerLarge.stop();
186
- });
174
+ if (userKey) forOwn(clients, ({ worker }) => worker.stop());
187
175
  else segmentsUpdateWorker!.stop();
188
176
  }
189
177
 
@@ -248,96 +236,76 @@ export function pushManagerFactory(
248
236
  splitsUpdateWorker.put(parsedData);
249
237
  });
250
238
 
251
- function handleMySegmentsUpdate(parsedData: IMySegmentsUpdateV2Data | IMyLargeSegmentsUpdateData) {
252
- const isLS = parsedData.type === MY_LARGE_SEGMENTS_UPDATE;
253
-
254
- switch (parsedData.u) {
255
- case UpdateStrategy.BoundedFetchRequest: {
256
- let bitmap: Uint8Array;
257
- try {
258
- bitmap = parseBitmap(parsedData.d, parsedData.c);
259
- } catch (e) {
260
- log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['BoundedFetchRequest', e]);
261
- break;
262
- }
263
-
264
- forOwn(clients, ({ hash64, worker, workerLarge }, matchingKey) => {
265
- if (isInBitmap(bitmap, hash64.hex)) {
266
- isLS ?
267
- workerLarge && workerLarge.put(parsedData.changeNumber, undefined, getDelay(parsedData, matchingKey)) :
268
- worker.put(parsedData.changeNumber);
269
- }
270
- });
271
- return;
239
+ if (userKey) {
240
+ pushEmitter.on(MY_SEGMENTS_UPDATE, function handleMySegmentsUpdate(parsedData, channel) {
241
+ const userKeyHash = channel.split('_')[2];
242
+ const userKey = userKeyHashes[userKeyHash];
243
+ if (userKey && clients[userKey]) { // check existence since it can be undefined if client has been destroyed
244
+ clients[userKey].worker.put(
245
+ parsedData.changeNumber,
246
+ parsedData.includesPayload ? parsedData.segmentList ? parsedData.segmentList : [] : undefined);
272
247
  }
273
- case UpdateStrategy.KeyList: {
274
- let keyList: KeyList, added: ISet<string>, removed: ISet<string>;
275
- try {
276
- keyList = parseKeyList(parsedData.d, parsedData.c);
277
- added = new _Set(keyList.a);
278
- removed = new _Set(keyList.r);
279
- } catch (e) {
280
- log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['KeyList', e]);
281
- break;
248
+ });
249
+ pushEmitter.on(MY_SEGMENTS_UPDATE_V2, function handleMySegmentsUpdate(parsedData) {
250
+ switch (parsedData.u) {
251
+ case UpdateStrategy.BoundedFetchRequest: {
252
+ let bitmap: Uint8Array;
253
+ try {
254
+ bitmap = parseBitmap(parsedData.d, parsedData.c);
255
+ } catch (e) {
256
+ log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['BoundedFetchRequest', e]);
257
+ break;
258
+ }
259
+
260
+ forOwn(clients, ({ hash64, worker }) => {
261
+ if (isInBitmap(bitmap, hash64.hex)) {
262
+ worker.put(parsedData.changeNumber); // fetch mySegments
263
+ }
264
+ });
265
+ return;
282
266
  }
267
+ case UpdateStrategy.KeyList: {
268
+ let keyList: KeyList, added: ISet<string>, removed: ISet<string>;
269
+ try {
270
+ keyList = parseKeyList(parsedData.d, parsedData.c);
271
+ added = new _Set(keyList.a);
272
+ removed = new _Set(keyList.r);
273
+ } catch (e) {
274
+ log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['KeyList', e]);
275
+ break;
276
+ }
283
277
 
284
- forOwn(clients, ({ hash64, worker, workerLarge }) => {
285
- const add = added.has(hash64.dec) ? true : removed.has(hash64.dec) ? false : undefined;
286
- if (add !== undefined) {
287
- isLS ?
288
- workerLarge && workerLarge.put(parsedData.changeNumber, [{
289
- name: parsedData.largeSegments[0],
290
- add
291
- }]) :
292
- worker.put(parsedData.changeNumber, [{
278
+ forOwn(clients, ({ hash64, worker }) => {
279
+ const add = added.has(hash64.dec) ? true : removed.has(hash64.dec) ? false : undefined;
280
+ if (add !== undefined) {
281
+ worker.put(parsedData.changeNumber, {
293
282
  name: parsedData.segmentName,
294
283
  add
295
- }]);
296
- }
297
- });
298
- return;
299
- }
300
- case UpdateStrategy.SegmentRemoval:
301
- if ((isLS && parsedData.largeSegments.length === 0) || (!isLS && !parsedData.segmentName)) {
302
- log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['SegmentRemoval', 'No segment name was provided']);
303
- break;
284
+ });
285
+ }
286
+ });
287
+ return;
304
288
  }
289
+ case UpdateStrategy.SegmentRemoval:
290
+ if (!parsedData.segmentName) {
291
+ log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['SegmentRemoval', 'No segment name was provided']);
292
+ break;
293
+ }
305
294
 
306
- forOwn(clients, ({ worker, workerLarge }) => {
307
- isLS ?
308
- workerLarge && workerLarge.put(parsedData.changeNumber, parsedData.largeSegments.map(largeSegment => ({
309
- name: largeSegment,
310
- add: false
311
- }))) :
312
- worker.put(parsedData.changeNumber, [{
295
+ forOwn(clients, ({ worker }) =>
296
+ worker.put(parsedData.changeNumber, {
313
297
  name: parsedData.segmentName,
314
298
  add: false
315
- }]);
316
- });
317
- return;
318
- }
299
+ })
300
+ );
301
+ return;
302
+ }
319
303
 
320
- // `UpdateStrategy.UnboundedFetchRequest` and fallbacks of other cases
321
- forOwn(clients, ({ worker, workerLarge }, matchingKey) => {
322
- isLS ?
323
- workerLarge && workerLarge.put(parsedData.changeNumber, undefined, getDelay(parsedData, matchingKey)) :
304
+ // `UpdateStrategy.UnboundedFetchRequest` and fallbacks of other cases
305
+ forOwn(clients, ({ worker }) => {
324
306
  worker.put(parsedData.changeNumber);
307
+ });
325
308
  });
326
- }
327
-
328
- if (userKey) {
329
- pushEmitter.on(MY_SEGMENTS_UPDATE, function handleMySegmentsUpdate(parsedData, channel) {
330
- const userKeyHash = channel.split('_')[2];
331
- const userKey = userKeyHashes[userKeyHash];
332
- if (userKey && clients[userKey]) { // check existence since it can be undefined if client has been destroyed
333
- clients[userKey].worker.put(
334
- parsedData.changeNumber,
335
- parsedData.includesPayload ? parsedData.segmentList ? parsedData.segmentList : [] : undefined);
336
- }
337
- });
338
-
339
- pushEmitter.on(MY_SEGMENTS_UPDATE_V2, handleMySegmentsUpdate);
340
- pushEmitter.on(MY_LARGE_SEGMENTS_UPDATE, handleMySegmentsUpdate);
341
309
  } else {
342
310
  pushEmitter.on(SEGMENT_UPDATE, segmentsUpdateWorker!.put);
343
311
  }
@@ -360,7 +328,7 @@ export function pushManagerFactory(
360
328
  if (disabled || disconnected === false) return;
361
329
  disconnected = false;
362
330
 
363
- if (userKey) this.add(userKey, pollingManager.segmentsSyncTask, pollingManager.largeSegmentsSyncTask!); // client-side
331
+ if (userKey) this.add(userKey, pollingManager.segmentsSyncTask as IMySegmentsSyncTask); // client-side
364
332
  else setTimeout(connectPush); // server-side runs in next cycle as in client-side, for consistency with client-side
365
333
  },
366
334
 
@@ -370,16 +338,12 @@ export function pushManagerFactory(
370
338
  },
371
339
 
372
340
  // [Only for client-side]
373
- add(userKey: string, mySegmentsSyncTask: IMySegmentsSyncTask, myLargeSegmentsSyncTask?: IMySegmentsSyncTask) {
341
+ add(userKey: string, mySegmentsSyncTask: IMySegmentsSyncTask) {
374
342
  const hash = hashUserKey(userKey);
375
343
 
376
344
  if (!userKeyHashes[hash]) {
377
345
  userKeyHashes[hash] = userKey;
378
- clients[userKey] = {
379
- hash64: hash64(userKey),
380
- worker: MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, MY_SEGMENT),
381
- workerLarge: myLargeSegmentsSyncTask ? MySegmentsUpdateWorker(myLargeSegmentsSyncTask, telemetryTracker, MY_LARGE_SEGMENT) : undefined
382
- };
346
+ clients[userKey] = { hash64: hash64(userKey), worker: MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker) };
383
347
  connectForNewClient = true; // we must reconnect on start, to listen the channel for the new user key
384
348
 
385
349
  // Reconnects in case of a new client.
@@ -1,4 +1,4 @@
1
- import { IMySegmentsUpdateData, IMySegmentsUpdateV2Data, ISegmentUpdateData, ISplitUpdateData, ISplitKillData, IMyLargeSegmentsUpdateData } from './SSEHandler/types';
1
+ import { IMySegmentsUpdateData, IMySegmentsUpdateV2Data, ISegmentUpdateData, ISplitUpdateData, ISplitKillData } from './SSEHandler/types';
2
2
  import { ITask } from '../types';
3
3
  import { IMySegmentsSyncTask } from '../polling/types';
4
4
  import { IEventEmitter } from '../../types';
@@ -16,18 +16,16 @@ export type MY_SEGMENTS_UPDATE_V2 = 'MY_SEGMENTS_UPDATE_V2';
16
16
  export type SEGMENT_UPDATE = 'SEGMENT_UPDATE';
17
17
  export type SPLIT_KILL = 'SPLIT_KILL';
18
18
  export type SPLIT_UPDATE = 'SPLIT_UPDATE';
19
- export type MY_LARGE_SEGMENTS_UPDATE = 'MY_LARGE_SEGMENTS_UPDATE';
20
19
 
21
20
  // Control-type push notifications, handled by NotificationKeeper
22
21
  export type CONTROL = 'CONTROL';
23
22
  export type OCCUPANCY = 'OCCUPANCY';
24
23
 
25
- export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NONRETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MY_SEGMENTS_UPDATE | MY_SEGMENTS_UPDATE_V2 | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | MY_LARGE_SEGMENTS_UPDATE | ControlType.STREAMING_RESET
24
+ export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NONRETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MY_SEGMENTS_UPDATE | MY_SEGMENTS_UPDATE_V2 | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | ControlType.STREAMING_RESET
26
25
 
27
26
  type IParsedData<T extends IPushEvent> =
28
27
  T extends MY_SEGMENTS_UPDATE ? IMySegmentsUpdateData :
29
28
  T extends MY_SEGMENTS_UPDATE_V2 ? IMySegmentsUpdateV2Data :
30
- T extends MY_LARGE_SEGMENTS_UPDATE ? IMyLargeSegmentsUpdateData :
31
29
  T extends SEGMENT_UPDATE ? ISegmentUpdateData :
32
30
  T extends SPLIT_UPDATE ? ISplitUpdateData :
33
31
  T extends SPLIT_KILL ? ISplitKillData : undefined;
@@ -47,6 +45,6 @@ export interface IPushEventEmitter extends IEventEmitter {
47
45
  */
48
46
  export interface IPushManager extends ITask, IPushEventEmitter {
49
47
  // Methods used in client-side, to support multiple clients
50
- add(userKey: string, mySegmentsSyncTask: IMySegmentsSyncTask, myLargeSegmentsSyncTask?: IMySegmentsSyncTask): void,
48
+ add(userKey: string, mySegmentsSyncTask: IMySegmentsSyncTask): void,
51
49
  remove(userKey: string): void
52
50
  }
@@ -71,19 +71,15 @@ export function telemetryCacheConfigAdapter(telemetry: ITelemetryCacheSync, sett
71
71
  pop(): TelemetryConfigStatsPayload {
72
72
  const { urls, scheduler } = settings;
73
73
  const isClientSide = settings.core.key !== undefined;
74
- const largeSegmentsEnabled = isClientSide && settings.sync.largeSegmentsEnabled;
75
74
 
76
75
  const { flagSetsTotal, flagSetsIgnored } = getTelemetryFlagSetsStats(settings.sync.__splitFiltersValidation);
77
76
 
78
77
  return objectAssign(getTelemetryConfigStats(settings.mode, settings.storage.type), {
79
78
  sE: settings.streamingEnabled,
80
- lsE: largeSegmentsEnabled ? largeSegmentsEnabled : undefined,
81
- wls: largeSegmentsEnabled ? settings.startup.waitForLargeSegments : undefined,
82
79
  rR: {
83
80
  sp: scheduler.featuresRefreshRate / 1000,
84
81
  se: isClientSide ? undefined : scheduler.segmentsRefreshRate / 1000,
85
82
  ms: isClientSide ? scheduler.segmentsRefreshRate / 1000 : undefined,
86
- mls: largeSegmentsEnabled ? scheduler.largeSegmentsRefreshRate / 1000 : undefined,
87
83
  im: scheduler.impressionsRefreshRate / 1000,
88
84
  ev: scheduler.eventsPushRate / 1000,
89
85
  te: scheduler.telemetryRefreshRate / 1000,
@@ -103,7 +103,7 @@ export type DROPPED = 1;
103
103
  export type DEDUPED = 2;
104
104
  export type ImpressionDataType = QUEUED | DROPPED | DEDUPED
105
105
  export type EventDataType = QUEUED | DROPPED;
106
- export type UpdatesFromSSEEnum = SPLITS | MY_SEGMENT | MY_LARGE_SEGMENT;
106
+ export type UpdatesFromSSEEnum = SPLITS | MY_SEGMENT;
107
107
 
108
108
  export type SPLITS = 'sp';
109
109
  export type IMPRESSIONS = 'im';
@@ -113,8 +113,7 @@ export type TELEMETRY = 'te';
113
113
  export type TOKEN = 'to';
114
114
  export type SEGMENT = 'se';
115
115
  export type MY_SEGMENT = 'ms';
116
- export type MY_LARGE_SEGMENT = 'mls';
117
- export type OperationType = SPLITS | IMPRESSIONS | IMPRESSIONS_COUNT | EVENTS | TELEMETRY | TOKEN | SEGMENT | MY_SEGMENT | MY_LARGE_SEGMENT;
116
+ export type OperationType = SPLITS | IMPRESSIONS | IMPRESSIONS_COUNT | EVENTS | TELEMETRY | TOKEN | SEGMENT | MY_SEGMENT;
118
117
 
119
118
  export type LastSync = Partial<Record<OperationType, number | undefined>>
120
119
  export type HttpErrors = Partial<Record<OperationType, { [statusCode: string]: number }>>
@@ -159,9 +158,8 @@ export type TelemetryUsageStats = {
159
158
 
160
159
  // amount of instant updates that we are doing by avoiding fetching to Split servers
161
160
  export type UpdatesFromSSE = {
162
- sp?: number, // splits
161
+ sp: number, // splits
163
162
  ms?: number, // my segments
164
- mls?: number // my large segments
165
163
  }
166
164
 
167
165
  // 'metrics/usage' JSON request body
@@ -177,14 +175,12 @@ export type TelemetryUsageStatsPayload = TelemetryUsageStats & {
177
175
  spC?: number, // splitCount
178
176
  seC?: number, // segmentCount
179
177
  skC?: number, // segmentKeyCount
180
- lseC?: number, // largeSegmentCount
181
- lskC?: number, // largeSegmentKeyCount
182
178
  sL?: number, // sessionLengthMs
183
179
  eQ: number, // eventsQueued
184
180
  eD: number, // eventsDropped
185
181
  sE: Array<StreamingEvent>, // streamingEvents
186
182
  t?: Array<string>, // tags
187
- ufs?: UpdatesFromSSE, // instant updates
183
+ ufs?: UpdatesFromSSE, //UpdatesFromSSE
188
184
  }
189
185
 
190
186
  /**
@@ -205,7 +201,6 @@ export type RefreshRates = {
205
201
  sp: number, // splits
206
202
  se?: number, // segments
207
203
  ms?: number, // mySegments
208
- mls?: number, // myLargeSegments
209
204
  im: number, // impressions
210
205
  ev: number, // events
211
206
  te: number, // telemetry
@@ -231,8 +226,6 @@ export type TelemetryConfigStats = {
231
226
  // 'metrics/config' JSON request body
232
227
  export type TelemetryConfigStatsPayload = TelemetryConfigStats & {
233
228
  sE: boolean, // streamingEnabled
234
- lsE?: boolean, // largeSegmentsEnabled
235
- wls?: boolean, // waitForLargeSegments
236
229
  rR: RefreshRates, // refreshRates
237
230
  uO: UrlOverrides, // urlOverrides
238
231
  iQ: number, // impressionsQueueSize
@@ -7,7 +7,7 @@ import { IPollingManager, IPollingManagerCS } from './polling/types';
7
7
  import { PUSH_SUBSYSTEM_UP, PUSH_SUBSYSTEM_DOWN } from './streaming/constants';
8
8
  import { SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING } from '../logger/constants';
9
9
  import { isConsentGranted } from '../consent';
10
- import { IN_LARGE_SEGMENT, IN_SEGMENT, POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
10
+ import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
11
11
  import { ISdkFactoryContextSync } from '../sdkFactory/types';
12
12
 
13
13
  /**
@@ -141,44 +141,36 @@ export function syncManagerOnlineFactory(
141
141
  shared(matchingKey: string, readinessManager: IReadinessManager, storage: IStorageSync) {
142
142
  if (!pollingManager) return;
143
143
 
144
- const { msSyncTask, mlsSyncTask } = (pollingManager as IPollingManagerCS).add(matchingKey, readinessManager, storage);
144
+ const mySegmentsSyncTask = (pollingManager as IPollingManagerCS).add(matchingKey, readinessManager, storage);
145
145
 
146
146
  return {
147
- isRunning: msSyncTask.isRunning,
147
+ isRunning: mySegmentsSyncTask.isRunning,
148
148
  start() {
149
149
  if (syncEnabled) {
150
150
  if (pushManager) {
151
151
  if (pollingManager!.isRunning()) {
152
152
  // if doing polling, we must start the periodic fetch of data
153
- if (storage.splits.usesMatcher(IN_SEGMENT)) msSyncTask.start();
154
- if (mlsSyncTask && storage.splits.usesMatcher(IN_LARGE_SEGMENT)) mlsSyncTask.start();
153
+ if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
155
154
  } else {
156
155
  // if not polling, we must execute the sync task for the initial fetch
157
156
  // of segments since `syncAll` was already executed when starting the main client
158
- msSyncTask.execute();
159
- mlsSyncTask && mlsSyncTask.execute();
157
+ mySegmentsSyncTask.execute();
160
158
  }
161
- pushManager.add(matchingKey, msSyncTask, mlsSyncTask);
159
+ pushManager.add(matchingKey, mySegmentsSyncTask);
162
160
  } else {
163
- if (storage.splits.usesMatcher(IN_SEGMENT)) msSyncTask.start();
164
- if (mlsSyncTask && storage.splits.usesMatcher(IN_LARGE_SEGMENT)) mlsSyncTask.start();
161
+ if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
165
162
  }
166
163
  } else {
167
- if (!readinessManager.isReady()) {
168
- msSyncTask.execute();
169
- mlsSyncTask && mlsSyncTask.execute();
170
- }
164
+ if (!readinessManager.isReady()) mySegmentsSyncTask.execute();
171
165
  }
172
166
  },
173
167
  stop() {
174
168
  // check in case `client.destroy()` has been invoked more than once for the same client
175
- const syncTasks = (pollingManager as IPollingManagerCS).get(matchingKey);
176
- if (syncTasks) {
177
- const { msSyncTask, mlsSyncTask } = syncTasks;
169
+ const mySegmentsSyncTask = (pollingManager as IPollingManagerCS).get(matchingKey);
170
+ if (mySegmentsSyncTask) {
178
171
  // stop syncing
179
172
  if (pushManager) pushManager.remove(matchingKey);
180
- if (msSyncTask.isRunning()) msSyncTask.stop();
181
- if (mlsSyncTask && mlsSyncTask.isRunning()) mlsSyncTask.stop();
173
+ if (mySegmentsSyncTask.isRunning()) mySegmentsSyncTask.stop();
182
174
 
183
175
  (pollingManager as IPollingManagerCS).remove(matchingKey);
184
176
  }