@splitsoftware/splitio-commons 2.2.1-rc.1 → 2.2.1-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 (140) hide show
  1. package/CHANGES.txt +2 -2
  2. package/README.md +0 -1
  3. package/cjs/evaluator/combiners/and.js +6 -2
  4. package/cjs/evaluator/combiners/ifelseif.js +6 -6
  5. package/cjs/evaluator/condition/index.js +5 -6
  6. package/cjs/evaluator/index.js +7 -7
  7. package/cjs/evaluator/matchers/index.js +1 -3
  8. package/cjs/evaluator/matchers/matcherTypes.js +0 -1
  9. package/cjs/evaluator/matchersTransform/index.js +0 -4
  10. package/cjs/evaluator/parser/index.js +2 -2
  11. package/cjs/evaluator/value/sanitize.js +0 -1
  12. package/cjs/logger/constants.js +3 -4
  13. package/cjs/logger/messages/debug.js +2 -3
  14. package/cjs/logger/messages/warn.js +1 -1
  15. package/cjs/services/splitApi.js +4 -3
  16. package/cjs/storages/AbstractSplitsCacheSync.js +2 -5
  17. package/cjs/storages/KeyBuilder.js +0 -9
  18. package/cjs/storages/KeyBuilderCS.js +0 -3
  19. package/cjs/storages/KeyBuilderSS.js +0 -3
  20. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +14 -9
  21. package/cjs/storages/inLocalStorage/index.js +1 -5
  22. package/cjs/storages/inLocalStorage/validateCache.js +1 -2
  23. package/cjs/storages/inMemory/InMemoryStorage.js +0 -3
  24. package/cjs/storages/inMemory/InMemoryStorageCS.js +0 -4
  25. package/cjs/storages/inRedis/index.js +9 -5
  26. package/cjs/storages/pluggable/index.js +0 -2
  27. package/cjs/sync/polling/fetchers/splitChangesFetcher.js +4 -51
  28. package/cjs/sync/polling/pollingManagerCS.js +7 -7
  29. package/cjs/sync/polling/syncTasks/splitsSyncTask.js +1 -1
  30. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +2 -2
  31. package/cjs/sync/polling/updaters/segmentChangesUpdater.js +1 -1
  32. package/cjs/sync/polling/updaters/splitChangesUpdater.js +33 -51
  33. package/cjs/sync/streaming/SSEHandler/index.js +0 -1
  34. package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +77 -106
  35. package/cjs/sync/streaming/constants.js +1 -2
  36. package/cjs/sync/streaming/pushManager.js +16 -3
  37. package/cjs/sync/syncManagerOnline.js +2 -2
  38. package/cjs/utils/constants/index.js +2 -3
  39. package/esm/evaluator/combiners/and.js +6 -2
  40. package/esm/evaluator/combiners/ifelseif.js +7 -7
  41. package/esm/evaluator/condition/index.js +5 -6
  42. package/esm/evaluator/index.js +7 -7
  43. package/esm/evaluator/matchers/index.js +1 -3
  44. package/esm/evaluator/matchers/matcherTypes.js +0 -1
  45. package/esm/evaluator/matchersTransform/index.js +0 -4
  46. package/esm/evaluator/parser/index.js +2 -2
  47. package/esm/evaluator/value/sanitize.js +0 -1
  48. package/esm/logger/constants.js +0 -1
  49. package/esm/logger/messages/debug.js +2 -3
  50. package/esm/logger/messages/warn.js +1 -1
  51. package/esm/services/splitApi.js +4 -3
  52. package/esm/storages/AbstractSplitsCacheSync.js +2 -5
  53. package/esm/storages/KeyBuilder.js +0 -9
  54. package/esm/storages/KeyBuilderCS.js +0 -3
  55. package/esm/storages/KeyBuilderSS.js +0 -3
  56. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +14 -9
  57. package/esm/storages/inLocalStorage/index.js +1 -5
  58. package/esm/storages/inLocalStorage/validateCache.js +1 -2
  59. package/esm/storages/inMemory/InMemoryStorage.js +0 -3
  60. package/esm/storages/inMemory/InMemoryStorageCS.js +0 -4
  61. package/esm/storages/inRedis/index.js +9 -5
  62. package/esm/storages/pluggable/index.js +0 -2
  63. package/esm/sync/polling/fetchers/splitChangesFetcher.js +4 -51
  64. package/esm/sync/polling/pollingManagerCS.js +7 -7
  65. package/esm/sync/polling/syncTasks/splitsSyncTask.js +1 -1
  66. package/esm/sync/polling/updaters/mySegmentsUpdater.js +2 -2
  67. package/esm/sync/polling/updaters/segmentChangesUpdater.js +1 -1
  68. package/esm/sync/polling/updaters/splitChangesUpdater.js +33 -51
  69. package/esm/sync/streaming/SSEHandler/index.js +1 -2
  70. package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +73 -102
  71. package/esm/sync/streaming/constants.js +0 -1
  72. package/esm/sync/streaming/pushManager.js +19 -6
  73. package/esm/sync/syncManagerOnline.js +2 -2
  74. package/esm/utils/constants/index.js +1 -2
  75. package/package.json +1 -1
  76. package/src/dtos/types.ts +8 -32
  77. package/src/evaluator/Engine.ts +1 -1
  78. package/src/evaluator/combiners/and.ts +4 -5
  79. package/src/evaluator/combiners/ifelseif.ts +9 -7
  80. package/src/evaluator/condition/engineUtils.ts +1 -1
  81. package/src/evaluator/condition/index.ts +12 -12
  82. package/src/evaluator/index.ts +7 -7
  83. package/src/evaluator/matchers/index.ts +1 -3
  84. package/src/evaluator/matchers/matcherTypes.ts +0 -1
  85. package/src/evaluator/matchersTransform/index.ts +0 -3
  86. package/src/evaluator/parser/index.ts +3 -3
  87. package/src/evaluator/types.ts +2 -2
  88. package/src/evaluator/value/index.ts +2 -2
  89. package/src/evaluator/value/sanitize.ts +4 -5
  90. package/src/logger/constants.ts +0 -1
  91. package/src/logger/messages/debug.ts +2 -3
  92. package/src/logger/messages/warn.ts +1 -1
  93. package/src/sdkManager/index.ts +1 -1
  94. package/src/services/splitApi.ts +4 -3
  95. package/src/services/types.ts +1 -1
  96. package/src/storages/AbstractSplitsCacheSync.ts +3 -6
  97. package/src/storages/KeyBuilder.ts +0 -12
  98. package/src/storages/KeyBuilderCS.ts +0 -4
  99. package/src/storages/KeyBuilderSS.ts +0 -4
  100. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +14 -10
  101. package/src/storages/inLocalStorage/index.ts +1 -5
  102. package/src/storages/inLocalStorage/validateCache.ts +1 -3
  103. package/src/storages/inMemory/InMemoryStorage.ts +0 -3
  104. package/src/storages/inMemory/InMemoryStorageCS.ts +0 -4
  105. package/src/storages/inRedis/index.ts +11 -7
  106. package/src/storages/pluggable/index.ts +0 -2
  107. package/src/storages/types.ts +1 -33
  108. package/src/sync/polling/fetchers/splitChangesFetcher.ts +4 -62
  109. package/src/sync/polling/fetchers/types.ts +0 -1
  110. package/src/sync/polling/pollingManagerCS.ts +7 -7
  111. package/src/sync/polling/syncTasks/splitsSyncTask.ts +1 -1
  112. package/src/sync/polling/types.ts +2 -2
  113. package/src/sync/polling/updaters/mySegmentsUpdater.ts +2 -2
  114. package/src/sync/polling/updaters/segmentChangesUpdater.ts +1 -1
  115. package/src/sync/polling/updaters/splitChangesUpdater.ts +42 -61
  116. package/src/sync/streaming/SSEHandler/index.ts +1 -2
  117. package/src/sync/streaming/SSEHandler/types.ts +2 -2
  118. package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +68 -98
  119. package/src/sync/streaming/constants.ts +0 -1
  120. package/src/sync/streaming/parseUtils.ts +2 -2
  121. package/src/sync/streaming/pushManager.ts +18 -6
  122. package/src/sync/streaming/types.ts +2 -3
  123. package/src/sync/syncManagerOnline.ts +2 -2
  124. package/src/utils/constants/index.ts +1 -2
  125. package/src/utils/lang/index.ts +1 -1
  126. package/cjs/evaluator/matchers/rbsegment.js +0 -44
  127. package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +0 -117
  128. package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +0 -61
  129. package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +0 -64
  130. package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +0 -64
  131. package/esm/evaluator/matchers/rbsegment.js +0 -40
  132. package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +0 -114
  133. package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +0 -58
  134. package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +0 -61
  135. package/esm/storages/pluggable/RBSegmentsCachePluggable.js +0 -61
  136. package/src/evaluator/matchers/rbsegment.ts +0 -62
  137. package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +0 -136
  138. package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +0 -68
  139. package/src/storages/inRedis/RBSegmentsCacheInRedis.ts +0 -79
  140. package/src/storages/pluggable/RBSegmentsCachePluggable.ts +0 -76
@@ -1,16 +1,12 @@
1
- import { IRBSegment, ISplit } from '../../../dtos/types';
2
- import { STREAMING_PARSING_SPLIT_UPDATE } from '../../../logger/constants';
1
+ import { ISplit } from '../../../dtos/types';
3
2
  import { ILogger } from '../../../logger/types';
4
3
  import { SDK_SPLITS_ARRIVED } from '../../../readiness/constants';
5
4
  import { ISplitsEventEmitter } from '../../../readiness/types';
6
- import { IRBSegmentsCacheSync, ISplitsCacheSync, IStorageSync } from '../../../storages/types';
5
+ import { ISplitsCacheSync } from '../../../storages/types';
7
6
  import { ITelemetryTracker } from '../../../trackers/types';
8
7
  import { Backoff } from '../../../utils/Backoff';
9
8
  import { SPLITS } from '../../../utils/constants';
10
9
  import { ISegmentsSyncTask, ISplitsSyncTask } from '../../polling/types';
11
- import { InstantUpdate } from '../../polling/updaters/splitChangesUpdater';
12
- import { RB_SEGMENT_UPDATE } from '../constants';
13
- import { parseFFUpdatePayload } from '../parseUtils';
14
10
  import { ISplitKillData, ISplitUpdateData } from '../SSEHandler/types';
15
11
  import { FETCH_BACKOFF_BASE, FETCH_BACKOFF_MAX_WAIT, FETCH_BACKOFF_MAX_RETRIES } from './constants';
16
12
  import { IUpdateWorker } from './types';
@@ -18,128 +14,102 @@ import { IUpdateWorker } from './types';
18
14
  /**
19
15
  * SplitsUpdateWorker factory
20
16
  */
21
- export function SplitsUpdateWorker(log: ILogger, storage: IStorageSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker<[updateData: ISplitUpdateData]> & { killSplit(event: ISplitKillData): void } {
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 } {
22
18
 
23
- const ff = SplitsUpdateWorker(storage.splits);
24
- const rbs = SplitsUpdateWorker(storage.rbSegments);
19
+ let maxChangeNumber = 0;
20
+ let handleNewEvent = false;
21
+ let isHandlingEvent: boolean;
22
+ let cdnBypass: boolean;
23
+ let payload: ISplit | undefined;
24
+ const backoff = new Backoff(__handleSplitUpdateCall, FETCH_BACKOFF_BASE, FETCH_BACKOFF_MAX_WAIT);
25
25
 
26
- function SplitsUpdateWorker(cache: ISplitsCacheSync | IRBSegmentsCacheSync) {
27
- let maxChangeNumber = -1;
28
- let handleNewEvent = false;
29
- let isHandlingEvent: boolean;
30
- let cdnBypass: boolean;
31
- let instantUpdate: InstantUpdate | undefined;
32
- const backoff = new Backoff(__handleSplitUpdateCall, FETCH_BACKOFF_BASE, FETCH_BACKOFF_MAX_WAIT);
26
+ function __handleSplitUpdateCall() {
27
+ isHandlingEvent = true;
28
+ if (maxChangeNumber > splitsCache.getChangeNumber()) {
29
+ handleNewEvent = false;
30
+ const splitUpdateNotification = payload ? { payload, changeNumber: maxChangeNumber } : undefined;
31
+ // fetch splits revalidating data if cached
32
+ splitsSyncTask.execute(true, cdnBypass ? maxChangeNumber : undefined, splitUpdateNotification).then(() => {
33
+ if (!isHandlingEvent) return; // halt if `stop` has been called
34
+ if (handleNewEvent) {
35
+ __handleSplitUpdateCall();
36
+ } else {
37
+ if (splitUpdateNotification) telemetryTracker.trackUpdatesFromSSE(SPLITS);
38
+ // fetch new registered segments for server-side API. Not retrying on error
39
+ if (segmentsSyncTask) segmentsSyncTask.execute(true);
33
40
 
34
- function __handleSplitUpdateCall() {
35
- isHandlingEvent = true;
36
- if (maxChangeNumber > cache.getChangeNumber()) {
37
- handleNewEvent = false;
38
- // fetch splits revalidating data if cached
39
- splitsSyncTask.execute(true, cdnBypass ? maxChangeNumber : undefined, instantUpdate).then(() => {
40
- if (!isHandlingEvent) return; // halt if `stop` has been called
41
- if (handleNewEvent) {
42
- __handleSplitUpdateCall();
43
- } else {
44
- if (instantUpdate) telemetryTracker.trackUpdatesFromSSE(SPLITS);
45
- // fetch new registered segments for server-side API. Not retrying on error
46
- if (segmentsSyncTask) segmentsSyncTask.execute(true);
47
-
48
- const attempts = backoff.attempts + 1;
41
+ const attempts = backoff.attempts + 1;
49
42
 
50
- if (ff.isSync() && rbs.isSync()) {
51
- log.debug(`Refresh completed${cdnBypass ? ' bypassing the CDN' : ''} in ${attempts} attempts.`);
52
- isHandlingEvent = false;
53
- return;
54
- }
43
+ if (maxChangeNumber <= splitsCache.getChangeNumber()) {
44
+ log.debug(`Refresh completed${cdnBypass ? ' bypassing the CDN' : ''} in ${attempts} attempts.`);
45
+ isHandlingEvent = false;
46
+ return;
47
+ }
55
48
 
56
- if (attempts < FETCH_BACKOFF_MAX_RETRIES) {
57
- backoff.scheduleCall();
58
- return;
59
- }
49
+ if (attempts < FETCH_BACKOFF_MAX_RETRIES) {
50
+ backoff.scheduleCall();
51
+ return;
52
+ }
60
53
 
61
- if (cdnBypass) {
62
- log.debug(`No changes fetched after ${attempts} attempts with CDN bypassed.`);
63
- isHandlingEvent = false;
64
- } else {
65
- backoff.reset();
66
- cdnBypass = true;
67
- __handleSplitUpdateCall();
68
- }
54
+ if (cdnBypass) {
55
+ log.debug(`No changes fetched after ${attempts} attempts with CDN bypassed.`);
56
+ isHandlingEvent = false;
57
+ } else {
58
+ backoff.reset();
59
+ cdnBypass = true;
60
+ __handleSplitUpdateCall();
69
61
  }
70
- });
71
- } else {
72
- isHandlingEvent = false;
73
- }
62
+ }
63
+ });
64
+ } else {
65
+ isHandlingEvent = false;
74
66
  }
67
+ }
75
68
 
76
- return {
77
- /**
78
- * Invoked by NotificationProcessor on SPLIT_UPDATE or RB_SEGMENT_UPDATE event
79
- *
80
- * @param changeNumber - change number of the notification
81
- */
82
- put({ changeNumber, pcn, type }: ISplitUpdateData, payload?: ISplit | IRBSegment) {
83
- const currentChangeNumber = cache.getChangeNumber();
69
+ /**
70
+ * Invoked by NotificationProcessor on SPLIT_UPDATE event
71
+ *
72
+ * @param changeNumber - change number of the SPLIT_UPDATE notification
73
+ */
74
+ function put({ changeNumber, pcn }: ISplitUpdateData, _payload?: ISplit) {
75
+ const currentChangeNumber = splitsCache.getChangeNumber();
84
76
 
85
- if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber) return;
77
+ if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber) return;
86
78
 
87
- maxChangeNumber = changeNumber;
88
- handleNewEvent = true;
89
- cdnBypass = false;
90
- instantUpdate = undefined;
79
+ maxChangeNumber = changeNumber;
80
+ handleNewEvent = true;
81
+ cdnBypass = false;
82
+ payload = undefined;
91
83
 
92
- if (payload && currentChangeNumber === pcn) {
93
- instantUpdate = { payload, changeNumber, type };
94
- }
84
+ if (_payload && currentChangeNumber === pcn) {
85
+ payload = _payload;
86
+ }
95
87
 
96
- if (backoff.timeoutID || !isHandlingEvent) __handleSplitUpdateCall();
97
- backoff.reset();
98
- },
99
- stop() {
100
- isHandlingEvent = false;
101
- backoff.reset();
102
- },
103
- isSync() {
104
- return maxChangeNumber <= cache.getChangeNumber();
105
- }
106
- };
88
+ if (backoff.timeoutID || !isHandlingEvent) __handleSplitUpdateCall();
89
+ backoff.reset();
107
90
  }
108
91
 
109
92
  return {
110
- put(parsedData) {
111
- if (parsedData.d && parsedData.c !== undefined) {
112
- try {
113
- const payload = parseFFUpdatePayload(parsedData.c, parsedData.d);
114
- if (payload) {
115
- (parsedData.type === RB_SEGMENT_UPDATE ? rbs : ff).put(parsedData, payload);
116
- return;
117
- }
118
- } catch (e) {
119
- log.warn(STREAMING_PARSING_SPLIT_UPDATE, [parsedData.type, e]);
120
- }
121
- }
122
- (parsedData.type === RB_SEGMENT_UPDATE ? rbs : ff).put(parsedData);
123
- },
93
+ put,
124
94
  /**
125
95
  * Invoked by NotificationProcessor on SPLIT_KILL event
126
96
  *
127
- * @param changeNumber - change number of the notification
97
+ * @param changeNumber - change number of the SPLIT_UPDATE notification
128
98
  * @param splitName - name of split to kill
129
99
  * @param defaultTreatment - default treatment value
130
100
  */
131
101
  killSplit({ changeNumber, splitName, defaultTreatment }: ISplitKillData) {
132
- if (storage.splits.killLocally(splitName, defaultTreatment, changeNumber)) {
102
+ if (splitsCache.killLocally(splitName, defaultTreatment, changeNumber)) {
133
103
  // trigger an SDK_UPDATE if Split was killed locally
134
104
  splitsEventEmitter.emit(SDK_SPLITS_ARRIVED, true);
135
105
  }
136
106
  // queues the SplitChanges fetch (only if changeNumber is newer)
137
- ff.put({ changeNumber } as ISplitUpdateData);
107
+ put({ changeNumber } as ISplitUpdateData);
138
108
  },
139
109
 
140
110
  stop() {
141
- ff.stop();
142
- rbs.stop();
111
+ isHandlingEvent = false;
112
+ backoff.reset();
143
113
  }
144
114
  };
145
115
  }
@@ -30,7 +30,6 @@ export const MEMBERSHIPS_LS_UPDATE = 'MEMBERSHIPS_LS_UPDATE';
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 RB_SEGMENT_UPDATE = 'RB_SEGMENT_UPDATE';
34
33
 
35
34
  // Control-type push notifications, handled by NotificationKeeper
36
35
  export const CONTROL = 'CONTROL';
@@ -2,7 +2,7 @@ import { algorithms } from '../../utils/decompress';
2
2
  import { decodeFromBase64 } from '../../utils/base64';
3
3
  import { hash } from '../../utils/murmur3/murmur3';
4
4
  import { Compression, IMembershipMSUpdateData, KeyList } from './SSEHandler/types';
5
- import { IRBSegment, ISplit } from '../../dtos/types';
5
+ import { ISplit } from '../../dtos/types';
6
6
 
7
7
  const GZIP = 1;
8
8
  const ZLIB = 2;
@@ -82,7 +82,7 @@ export function isInBitmap(bitmap: Uint8Array, hash64hex: string) {
82
82
  /**
83
83
  * Parse feature flags notifications for instant feature flag updates
84
84
  */
85
- export function parseFFUpdatePayload(compression: Compression, data: string): ISplit | IRBSegment | undefined {
85
+ export function parseFFUpdatePayload(compression: Compression, data: string): ISplit | undefined {
86
86
  return compression > 0 ?
87
87
  parseKeyList(data, compression, false) :
88
88
  JSON.parse(decodeFromBase64(data));
@@ -11,10 +11,10 @@ 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 { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, RB_SEGMENT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
15
- import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE } from '../../logger/constants';
14
+ import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, 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
+ import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE, STREAMING_PARSING_SPLIT_UPDATE } from '../../logger/constants';
16
16
  import { IMembershipMSUpdateData, IMembershipLSUpdateData, KeyList, UpdateStrategy } from './SSEHandler/types';
17
- import { getDelay, isInBitmap, parseBitmap, parseKeyList } from './parseUtils';
17
+ import { getDelay, isInBitmap, parseBitmap, parseFFUpdatePayload, parseKeyList } from './parseUtils';
18
18
  import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
19
19
  import { IAuthTokenPushEnabled } from './AuthClient/types';
20
20
  import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
@@ -56,7 +56,7 @@ export function pushManagerFactory(
56
56
  // MySegmentsUpdateWorker (client-side) are initiated in `add` method
57
57
  const segmentsUpdateWorker = userKey ? undefined : SegmentsUpdateWorker(log, pollingManager.segmentsSyncTask as ISegmentsSyncTask, storage.segments);
58
58
  // For server-side we pass the segmentsSyncTask, used by SplitsUpdateWorker to fetch new segments
59
- const splitsUpdateWorker = SplitsUpdateWorker(log, storage, pollingManager.splitsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
59
+ const splitsUpdateWorker = SplitsUpdateWorker(log, storage.splits, pollingManager.splitsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
60
60
 
61
61
  // [Only for client-side] map of hashes to user keys, to dispatch membership update events to the corresponding MySegmentsUpdateWorker
62
62
  const userKeyHashes: Record<string, string> = {};
@@ -219,8 +219,20 @@ export function pushManagerFactory(
219
219
  /** Functions related to synchronization (Queues and Workers in the spec) */
220
220
 
221
221
  pushEmitter.on(SPLIT_KILL, splitsUpdateWorker.killSplit);
222
- pushEmitter.on(SPLIT_UPDATE, splitsUpdateWorker.put);
223
- pushEmitter.on(RB_SEGMENT_UPDATE, splitsUpdateWorker.put);
222
+ pushEmitter.on(SPLIT_UPDATE, (parsedData) => {
223
+ if (parsedData.d && parsedData.c !== undefined) {
224
+ try {
225
+ const payload = parseFFUpdatePayload(parsedData.c, parsedData.d);
226
+ if (payload) {
227
+ splitsUpdateWorker.put(parsedData, payload);
228
+ return;
229
+ }
230
+ } catch (e) {
231
+ log.warn(STREAMING_PARSING_SPLIT_UPDATE, [e]);
232
+ }
233
+ }
234
+ splitsUpdateWorker.put(parsedData);
235
+ });
224
236
 
225
237
  function handleMySegmentsUpdate(parsedData: IMembershipMSUpdateData | IMembershipLSUpdateData) {
226
238
  switch (parsedData.u) {
@@ -16,19 +16,18 @@ export type MEMBERSHIPS_LS_UPDATE = 'MEMBERSHIPS_LS_UPDATE';
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 RB_SEGMENT_UPDATE = 'RB_SEGMENT_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 | MEMBERSHIPS_MS_UPDATE | MEMBERSHIPS_LS_UPDATE | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | RB_SEGMENT_UPDATE | ControlType.STREAMING_RESET
24
+ export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NONRETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MEMBERSHIPS_MS_UPDATE | MEMBERSHIPS_LS_UPDATE | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | ControlType.STREAMING_RESET
26
25
 
27
26
  type IParsedData<T extends IPushEvent> =
28
27
  T extends MEMBERSHIPS_MS_UPDATE ? IMembershipMSUpdateData :
29
28
  T extends MEMBERSHIPS_LS_UPDATE ? IMembershipLSUpdateData :
30
29
  T extends SEGMENT_UPDATE ? ISegmentUpdateData :
31
- T extends SPLIT_UPDATE | RB_SEGMENT_UPDATE ? ISplitUpdateData :
30
+ T extends SPLIT_UPDATE ? ISplitUpdateData :
32
31
  T extends SPLIT_KILL ? ISplitKillData : INotificationData;
33
32
 
34
33
  /**
@@ -155,14 +155,14 @@ export function syncManagerOnlineFactory(
155
155
  if (pushManager) {
156
156
  if (pollingManager.isRunning()) {
157
157
  // if doing polling, we must start the periodic fetch of data
158
- if (storage.splits.usesSegments() || storage.rbSegments.usesSegments()) mySegmentsSyncTask.start();
158
+ if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
159
159
  } else {
160
160
  // if not polling, we must execute the sync task for the initial fetch
161
161
  // of segments since `syncAll` was already executed when starting the main client
162
162
  mySegmentsSyncTask.execute();
163
163
  }
164
164
  } else {
165
- if (storage.splits.usesSegments() || storage.rbSegments.usesSegments()) mySegmentsSyncTask.start();
165
+ if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
166
166
  }
167
167
  } else {
168
168
  if (!readinessManager.isReady()) mySegmentsSyncTask.execute();
@@ -104,9 +104,8 @@ export const DISABLED = 0;
104
104
  export const ENABLED = 1;
105
105
  export const PAUSED = 2;
106
106
 
107
- export const FLAG_SPEC_VERSION = '1.3';
107
+ export const FLAG_SPEC_VERSION = '1.2';
108
108
 
109
109
  // Matcher types
110
110
  export const IN_SEGMENT = 'IN_SEGMENT';
111
111
  export const IN_LARGE_SEGMENT = 'IN_LARGE_SEGMENT';
112
- export const IN_RULE_BASED_SEGMENT = 'IN_RULE_BASED_SEGMENT';
@@ -111,7 +111,7 @@ export function groupBy<T extends Record<string, any>>(source: T[], prop: string
111
111
  /**
112
112
  * Checks if a given value is a boolean.
113
113
  */
114
- export function isBoolean(val: any): val is boolean {
114
+ export function isBoolean(val: any): boolean {
115
115
  return val === true || val === false;
116
116
  }
117
117
 
@@ -1,44 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ruleBasedSegmentMatcherContext = void 0;
4
- var thenable_1 = require("../../utils/promise/thenable");
5
- var key_1 = require("../../utils/key");
6
- var parser_1 = require("../parser");
7
- function ruleBasedSegmentMatcherContext(segmentName, storage, log) {
8
- return function ruleBasedSegmentMatcher(_a, splitEvaluator) {
9
- var key = _a.key, attributes = _a.attributes;
10
- function matchConditions(rbsegment) {
11
- var conditions = rbsegment.conditions || [];
12
- var evaluator = (0, parser_1.parser)(log, conditions, storage);
13
- var evaluation = evaluator((0, key_1.keyParser)(key), undefined, undefined, undefined, attributes, splitEvaluator);
14
- return (0, thenable_1.thenable)(evaluation) ?
15
- evaluation.then(function (evaluation) { return evaluation ? true : false; }) :
16
- evaluation ? true : false;
17
- }
18
- function isExcluded(rbSegment) {
19
- var matchingKey = (0, key_1.getMatching)(key);
20
- var excluded = rbSegment.excluded || {};
21
- if (excluded.keys && excluded.keys.indexOf(matchingKey) !== -1)
22
- return true;
23
- var isInSegment = (excluded.segments || []).map(function (segmentName) {
24
- return storage.segments.isInSegment(segmentName, matchingKey);
25
- });
26
- return isInSegment.length && (0, thenable_1.thenable)(isInSegment[0]) ?
27
- Promise.all(isInSegment).then(function (results) { return results.some(function (result) { return result; }); }) :
28
- isInSegment.some(function (result) { return result; });
29
- }
30
- function isInSegment(rbSegment) {
31
- if (!rbSegment)
32
- return false;
33
- var excluded = isExcluded(rbSegment);
34
- return (0, thenable_1.thenable)(excluded) ?
35
- excluded.then(function (excluded) { return excluded ? false : matchConditions(rbSegment); }) :
36
- excluded ? false : matchConditions(rbSegment);
37
- }
38
- var rbSegment = storage.rbSegments.get(segmentName);
39
- return (0, thenable_1.thenable)(rbSegment) ?
40
- rbSegment.then(isInSegment) :
41
- isInSegment(rbSegment);
42
- };
43
- }
44
- exports.ruleBasedSegmentMatcherContext = ruleBasedSegmentMatcherContext;
@@ -1,117 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RBSegmentsCacheInLocal = void 0;
4
- var lang_1 = require("../../utils/lang");
5
- var sets_1 = require("../../utils/lang/sets");
6
- var AbstractSplitsCacheSync_1 = require("../AbstractSplitsCacheSync");
7
- var constants_1 = require("./constants");
8
- var RBSegmentsCacheInLocal = /** @class */ (function () {
9
- function RBSegmentsCacheInLocal(settings, keys) {
10
- this.keys = keys;
11
- this.log = settings.log;
12
- }
13
- RBSegmentsCacheInLocal.prototype.clear = function () {
14
- var _this = this;
15
- this.getNames().forEach(function (name) { return _this.remove(name); });
16
- localStorage.removeItem(this.keys.buildRBSegmentsTillKey());
17
- };
18
- RBSegmentsCacheInLocal.prototype.update = function (toAdd, toRemove, changeNumber) {
19
- var _this = this;
20
- this.setChangeNumber(changeNumber);
21
- var updated = toAdd.map(function (toAdd) { return _this.add(toAdd); }).some(function (result) { return result; });
22
- return toRemove.map(function (toRemove) { return _this.remove(toRemove.name); }).some(function (result) { return result; }) || updated;
23
- };
24
- RBSegmentsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
25
- try {
26
- localStorage.setItem(this.keys.buildRBSegmentsTillKey(), changeNumber + '');
27
- localStorage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
28
- }
29
- catch (e) {
30
- this.log.error(constants_1.LOG_PREFIX + e);
31
- }
32
- };
33
- RBSegmentsCacheInLocal.prototype.updateSegmentCount = function (diff) {
34
- var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
35
- var count = (0, lang_1.toNumber)(localStorage.getItem(segmentsCountKey)) + diff;
36
- // @ts-expect-error
37
- if (count > 0)
38
- localStorage.setItem(segmentsCountKey, count);
39
- else
40
- localStorage.removeItem(segmentsCountKey);
41
- };
42
- RBSegmentsCacheInLocal.prototype.add = function (rbSegment) {
43
- try {
44
- var name_1 = rbSegment.name;
45
- var rbSegmentKey = this.keys.buildRBSegmentKey(name_1);
46
- var rbSegmentFromLocalStorage = localStorage.getItem(rbSegmentKey);
47
- var previous = rbSegmentFromLocalStorage ? JSON.parse(rbSegmentFromLocalStorage) : null;
48
- localStorage.setItem(rbSegmentKey, JSON.stringify(rbSegment));
49
- var usesSegmentsDiff = 0;
50
- if (previous && (0, AbstractSplitsCacheSync_1.usesSegments)(previous))
51
- usesSegmentsDiff--;
52
- if ((0, AbstractSplitsCacheSync_1.usesSegments)(rbSegment))
53
- usesSegmentsDiff++;
54
- if (usesSegmentsDiff !== 0)
55
- this.updateSegmentCount(usesSegmentsDiff);
56
- return true;
57
- }
58
- catch (e) {
59
- this.log.error(constants_1.LOG_PREFIX + e);
60
- return false;
61
- }
62
- };
63
- RBSegmentsCacheInLocal.prototype.remove = function (name) {
64
- try {
65
- var rbSegment = this.get(name);
66
- if (!rbSegment)
67
- return false;
68
- localStorage.removeItem(this.keys.buildRBSegmentKey(name));
69
- if ((0, AbstractSplitsCacheSync_1.usesSegments)(rbSegment))
70
- this.updateSegmentCount(-1);
71
- return true;
72
- }
73
- catch (e) {
74
- this.log.error(constants_1.LOG_PREFIX + e);
75
- return false;
76
- }
77
- };
78
- RBSegmentsCacheInLocal.prototype.getNames = function () {
79
- var len = localStorage.length;
80
- var accum = [];
81
- var cur = 0;
82
- while (cur < len) {
83
- var key = localStorage.key(cur);
84
- if (key != null && this.keys.isRBSegmentKey(key))
85
- accum.push(this.keys.extractKey(key));
86
- cur++;
87
- }
88
- return accum;
89
- };
90
- RBSegmentsCacheInLocal.prototype.get = function (name) {
91
- var item = localStorage.getItem(this.keys.buildRBSegmentKey(name));
92
- return item && JSON.parse(item);
93
- };
94
- RBSegmentsCacheInLocal.prototype.contains = function (names) {
95
- var namesArray = (0, sets_1.setToArray)(names);
96
- var namesInStorage = this.getNames();
97
- return namesArray.every(function (name) { return namesInStorage.indexOf(name) !== -1; });
98
- };
99
- RBSegmentsCacheInLocal.prototype.getChangeNumber = function () {
100
- var n = -1;
101
- var value = localStorage.getItem(this.keys.buildRBSegmentsTillKey());
102
- if (value !== null) {
103
- value = parseInt(value, 10);
104
- return (0, lang_1.isNaNNumber)(value) ? n : value;
105
- }
106
- return n;
107
- };
108
- RBSegmentsCacheInLocal.prototype.usesSegments = function () {
109
- var storedCount = localStorage.getItem(this.keys.buildSplitsWithSegmentCountKey());
110
- var splitsWithSegmentsCount = storedCount === null ? 0 : (0, lang_1.toNumber)(storedCount);
111
- return (0, lang_1.isFiniteNumber)(splitsWithSegmentsCount) ?
112
- splitsWithSegmentsCount > 0 :
113
- true;
114
- };
115
- return RBSegmentsCacheInLocal;
116
- }());
117
- exports.RBSegmentsCacheInLocal = RBSegmentsCacheInLocal;
@@ -1,61 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RBSegmentsCacheInMemory = void 0;
4
- var sets_1 = require("../../utils/lang/sets");
5
- var AbstractSplitsCacheSync_1 = require("../AbstractSplitsCacheSync");
6
- var RBSegmentsCacheInMemory = /** @class */ (function () {
7
- function RBSegmentsCacheInMemory() {
8
- this.cache = {};
9
- this.changeNumber = -1;
10
- this.segmentsCount = 0;
11
- }
12
- RBSegmentsCacheInMemory.prototype.clear = function () {
13
- this.cache = {};
14
- this.changeNumber = -1;
15
- this.segmentsCount = 0;
16
- };
17
- RBSegmentsCacheInMemory.prototype.update = function (toAdd, toRemove, changeNumber) {
18
- var _this = this;
19
- this.changeNumber = changeNumber;
20
- var updated = toAdd.map(function (toAdd) { return _this.add(toAdd); }).some(function (result) { return result; });
21
- return toRemove.map(function (toRemove) { return _this.remove(toRemove.name); }).some(function (result) { return result; }) || updated;
22
- };
23
- RBSegmentsCacheInMemory.prototype.add = function (rbSegment) {
24
- var name = rbSegment.name;
25
- var previous = this.get(name);
26
- if (previous && (0, AbstractSplitsCacheSync_1.usesSegments)(previous))
27
- this.segmentsCount--;
28
- this.cache[name] = rbSegment;
29
- if ((0, AbstractSplitsCacheSync_1.usesSegments)(rbSegment))
30
- this.segmentsCount++;
31
- return true;
32
- };
33
- RBSegmentsCacheInMemory.prototype.remove = function (name) {
34
- var rbSegment = this.get(name);
35
- if (!rbSegment)
36
- return false;
37
- delete this.cache[name];
38
- if ((0, AbstractSplitsCacheSync_1.usesSegments)(rbSegment))
39
- this.segmentsCount--;
40
- return true;
41
- };
42
- RBSegmentsCacheInMemory.prototype.getNames = function () {
43
- return Object.keys(this.cache);
44
- };
45
- RBSegmentsCacheInMemory.prototype.get = function (name) {
46
- return this.cache[name] || null;
47
- };
48
- RBSegmentsCacheInMemory.prototype.contains = function (names) {
49
- var namesArray = (0, sets_1.setToArray)(names);
50
- var namesInStorage = this.getNames();
51
- return namesArray.every(function (name) { return namesInStorage.indexOf(name) !== -1; });
52
- };
53
- RBSegmentsCacheInMemory.prototype.getChangeNumber = function () {
54
- return this.changeNumber;
55
- };
56
- RBSegmentsCacheInMemory.prototype.usesSegments = function () {
57
- return this.segmentsCount > 0;
58
- };
59
- return RBSegmentsCacheInMemory;
60
- }());
61
- exports.RBSegmentsCacheInMemory = RBSegmentsCacheInMemory;
@@ -1,64 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RBSegmentsCacheInRedis = void 0;
4
- var lang_1 = require("../../utils/lang");
5
- var constants_1 = require("./constants");
6
- var sets_1 = require("../../utils/lang/sets");
7
- var RBSegmentsCacheInRedis = /** @class */ (function () {
8
- function RBSegmentsCacheInRedis(log, keys, redis) {
9
- this.log = log;
10
- this.keys = keys;
11
- this.redis = redis;
12
- }
13
- RBSegmentsCacheInRedis.prototype.get = function (name) {
14
- return this.redis.get(this.keys.buildRBSegmentKey(name))
15
- .then(function (maybeRBSegment) { return maybeRBSegment && JSON.parse(maybeRBSegment); });
16
- };
17
- RBSegmentsCacheInRedis.prototype.getNames = function () {
18
- var _this = this;
19
- return this.redis.keys(this.keys.searchPatternForRBSegmentKeys()).then(function (listOfKeys) { return listOfKeys.map(_this.keys.extractKey); });
20
- };
21
- RBSegmentsCacheInRedis.prototype.contains = function (names) {
22
- var namesArray = (0, sets_1.setToArray)(names);
23
- return this.getNames().then(function (namesInStorage) {
24
- return namesArray.every(function (name) { return namesInStorage.includes(name); });
25
- });
26
- };
27
- RBSegmentsCacheInRedis.prototype.update = function (toAdd, toRemove, changeNumber) {
28
- var _this = this;
29
- return Promise.all([
30
- this.setChangeNumber(changeNumber),
31
- Promise.all(toAdd.map(function (toAdd) {
32
- var key = _this.keys.buildRBSegmentKey(toAdd.name);
33
- var stringifiedNewRBSegment = JSON.stringify(toAdd);
34
- return _this.redis.set(key, stringifiedNewRBSegment).then(function () { return true; });
35
- })),
36
- Promise.all(toRemove.map(function (toRemove) {
37
- var key = _this.keys.buildRBSegmentKey(toRemove.name);
38
- return _this.redis.del(key).then(function (status) { return status === 1; });
39
- }))
40
- ]).then(function (_a) {
41
- var added = _a[1], removed = _a[2];
42
- return added.some(function (result) { return result; }) || removed.some(function (result) { return result; });
43
- });
44
- };
45
- RBSegmentsCacheInRedis.prototype.setChangeNumber = function (changeNumber) {
46
- return this.redis.set(this.keys.buildRBSegmentsTillKey(), changeNumber + '').then(function (status) { return status === 'OK'; });
47
- };
48
- RBSegmentsCacheInRedis.prototype.getChangeNumber = function () {
49
- var _this = this;
50
- return this.redis.get(this.keys.buildRBSegmentsTillKey()).then(function (value) {
51
- var i = parseInt(value, 10);
52
- return (0, lang_1.isNaNNumber)(i) ? -1 : i;
53
- }).catch(function (e) {
54
- _this.log.error(constants_1.LOG_PREFIX + 'Could not retrieve changeNumber from storage. Error: ' + e);
55
- return -1;
56
- });
57
- };
58
- // @TODO implement if required by DataLoader or producer mode
59
- RBSegmentsCacheInRedis.prototype.clear = function () {
60
- return Promise.resolve();
61
- };
62
- return RBSegmentsCacheInRedis;
63
- }());
64
- exports.RBSegmentsCacheInRedis = RBSegmentsCacheInRedis;