@splitsoftware/splitio-commons 1.16.1-rc.1 → 1.16.1-rc.11
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.
- package/CHANGES.txt +4 -0
- package/cjs/logger/constants.js +5 -4
- package/cjs/logger/messages/info.js +2 -1
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/readiness/readinessManager.js +7 -12
- package/cjs/services/splitApi.js +5 -9
- package/cjs/storages/AbstractSegmentsCacheSync.js +41 -12
- package/cjs/storages/AbstractSplitsCacheAsync.js +2 -2
- package/cjs/storages/AbstractSplitsCacheSync.js +7 -5
- package/cjs/storages/KeyBuilder.js +0 -3
- package/cjs/storages/KeyBuilderCS.js +6 -0
- package/cjs/storages/dataLoader.js +1 -1
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +29 -52
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +4 -16
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +9 -40
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +6 -15
- package/cjs/sync/polling/fetchers/mySegmentsFetcher.js +4 -11
- package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/cjs/sync/polling/pollingManagerCS.js +33 -51
- package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +14 -20
- package/cjs/sync/streaming/AuthClient/index.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +3 -6
- package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +15 -9
- package/cjs/sync/streaming/constants.js +3 -4
- package/cjs/sync/streaming/parseUtils.js +14 -9
- package/cjs/sync/streaming/pushManager.js +29 -55
- package/cjs/sync/submitters/telemetrySubmitter.js +0 -2
- package/cjs/sync/syncManagerOnline.js +14 -24
- package/cjs/utils/constants/index.js +4 -5
- package/cjs/utils/settingsValidation/index.js +1 -5
- package/esm/logger/constants.js +2 -1
- package/esm/logger/messages/info.js +2 -1
- package/esm/logger/messages/warn.js +1 -1
- package/esm/readiness/readinessManager.js +7 -12
- package/esm/services/splitApi.js +6 -10
- package/esm/storages/AbstractSegmentsCacheSync.js +41 -12
- package/esm/storages/AbstractSplitsCacheAsync.js +2 -2
- package/esm/storages/AbstractSplitsCacheSync.js +5 -3
- package/esm/storages/KeyBuilder.js +0 -3
- package/esm/storages/KeyBuilderCS.js +6 -0
- package/esm/storages/dataLoader.js +1 -1
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +29 -52
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +5 -17
- package/esm/storages/inMemory/MySegmentsCacheInMemory.js +9 -40
- package/esm/storages/inMemory/SplitsCacheInMemory.js +7 -16
- package/esm/sync/polling/fetchers/mySegmentsFetcher.js +4 -11
- package/esm/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/esm/sync/polling/pollingManagerCS.js +34 -52
- package/esm/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +12 -18
- package/esm/sync/streaming/AuthClient/index.js +1 -1
- package/esm/sync/streaming/SSEHandler/index.js +4 -7
- package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +15 -9
- package/esm/sync/streaming/constants.js +2 -3
- package/esm/sync/streaming/parseUtils.js +12 -8
- package/esm/sync/streaming/pushManager.js +32 -57
- package/esm/sync/submitters/telemetrySubmitter.js +0 -2
- package/esm/sync/syncManagerOnline.js +15 -25
- package/esm/utils/constants/index.js +2 -3
- package/esm/utils/settingsValidation/index.js +1 -5
- package/package.json +1 -1
- package/src/dtos/types.ts +7 -8
- package/src/logger/constants.ts +2 -1
- package/src/logger/messages/info.ts +2 -1
- package/src/logger/messages/warn.ts +1 -1
- package/src/readiness/readinessManager.ts +7 -9
- package/src/readiness/types.ts +0 -1
- package/src/services/splitApi.ts +7 -12
- package/src/services/splitHttpClient.ts +1 -1
- package/src/services/types.ts +2 -3
- package/src/storages/AbstractSegmentsCacheSync.ts +53 -12
- package/src/storages/AbstractSplitsCacheAsync.ts +2 -2
- package/src/storages/AbstractSplitsCacheSync.ts +7 -5
- package/src/storages/KeyBuilder.ts +0 -3
- package/src/storages/KeyBuilderCS.ts +9 -0
- package/src/storages/dataLoader.ts +1 -1
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +26 -56
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +5 -20
- package/src/storages/inMemory/MySegmentsCacheInMemory.ts +10 -44
- package/src/storages/inMemory/SplitsCacheInMemory.ts +7 -13
- package/src/storages/types.ts +10 -8
- package/src/sync/polling/fetchers/mySegmentsFetcher.ts +7 -14
- package/src/sync/polling/fetchers/segmentChangesFetcher.ts +1 -1
- package/src/sync/polling/fetchers/types.ts +2 -2
- package/src/sync/polling/pollingManagerCS.ts +29 -61
- package/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +12 -13
- package/src/sync/polling/types.ts +8 -8
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +17 -18
- package/src/sync/streaming/AuthClient/index.ts +1 -1
- package/src/sync/streaming/SSEClient/index.ts +4 -6
- package/src/sync/streaming/SSEHandler/index.ts +5 -9
- package/src/sync/streaming/SSEHandler/types.ts +13 -25
- package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +17 -12
- package/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts +1 -1
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +1 -1
- package/src/sync/streaming/UpdateWorkers/types.ts +2 -2
- package/src/sync/streaming/constants.ts +2 -3
- package/src/sync/streaming/parseUtils.ts +19 -11
- package/src/sync/streaming/pushManager.ts +38 -68
- package/src/sync/streaming/types.ts +11 -13
- package/src/sync/submitters/telemetrySubmitter.ts +0 -2
- package/src/sync/submitters/types.ts +3 -6
- package/src/sync/syncManagerOnline.ts +11 -19
- package/src/types.ts +1 -26
- package/src/utils/constants/index.ts +2 -3
- package/src/utils/settingsValidation/index.ts +1 -5
- package/types/dtos/types.d.ts +7 -8
- package/types/logger/constants.d.ts +2 -1
- package/types/readiness/types.d.ts +0 -1
- package/types/services/decorateHeaders.d.ts +2 -0
- package/types/services/splitApi.d.ts +1 -1
- package/types/services/splitHttpClient.d.ts +1 -1
- package/types/services/types.d.ts +2 -3
- package/types/storages/AbstractSegmentsCacheSync.d.ts +9 -11
- package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
- package/types/storages/AbstractSplitsCacheSync.d.ts +4 -4
- package/types/storages/KeyBuilder.d.ts +0 -1
- package/types/storages/KeyBuilderCS.d.ts +2 -0
- package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +2 -12
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +1 -1
- package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +3 -9
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +1 -2
- package/types/storages/types.d.ts +8 -7
- package/types/sync/polling/fetchers/mySegmentsFetcher.d.ts +2 -2
- package/types/sync/polling/fetchers/types.d.ts +2 -2
- package/types/sync/polling/syncTasks/mySegmentsSyncTask.d.ts +4 -3
- package/types/sync/polling/types.d.ts +8 -12
- package/types/sync/polling/updaters/mySegmentsUpdater.d.ts +3 -2
- package/types/sync/streaming/SSEHandler/types.d.ts +13 -22
- package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +2 -3
- package/types/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.d.ts +2 -1
- package/types/sync/streaming/UpdateWorkers/SplitsUpdateWorker.d.ts +3 -2
- package/types/sync/streaming/UpdateWorkers/types.d.ts +2 -2
- package/types/sync/streaming/constants.d.ts +2 -3
- package/types/sync/streaming/parseUtils.d.ts +4 -5
- package/types/sync/streaming/pushManager.d.ts +0 -2
- package/types/sync/streaming/pushManagerCS_Spec1_3.d.ts +9 -0
- package/types/sync/streaming/pushManager_Spec1_3.d.ts +9 -0
- package/types/sync/streaming/types.d.ts +9 -10
- package/types/sync/submitters/types.d.ts +3 -6
- package/types/types.d.ts +0 -25
- package/types/utils/constants/index.d.ts +2 -3
- package/types/utils/settingsValidation/index.d.ts +0 -2
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Backoff } from '../../../utils/Backoff';
|
|
2
|
+
import { MEMBERSHIPS } from '../../../utils/constants';
|
|
2
3
|
/**
|
|
3
4
|
* MySegmentsUpdateWorker factory
|
|
4
5
|
*/
|
|
5
|
-
export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker
|
|
6
|
+
export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker) {
|
|
6
7
|
var maxChangeNumber = 0; // keeps the maximum changeNumber among queued events
|
|
7
8
|
var currentChangeNumber = -1;
|
|
8
9
|
var handleNewEvent = false;
|
|
@@ -20,6 +21,7 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
|
|
|
20
21
|
var syncTask = _delay ?
|
|
21
22
|
new Promise(function (res) {
|
|
22
23
|
_delayTimeoutID = setTimeout(function () {
|
|
24
|
+
_delay = undefined;
|
|
23
25
|
mySegmentsSyncTask.execute(_segmentsData, true).then(res);
|
|
24
26
|
}, _delay);
|
|
25
27
|
}) :
|
|
@@ -29,7 +31,7 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
|
|
|
29
31
|
return; // halt if `stop` has been called
|
|
30
32
|
if (result !== false) { // Unlike `Splits|SegmentsUpdateWorker`, we cannot use `mySegmentsCache.getChangeNumber` since `/mySegments` endpoint doesn't provide this value.
|
|
31
33
|
if (_segmentsData)
|
|
32
|
-
telemetryTracker.trackUpdatesFromSSE(
|
|
34
|
+
telemetryTracker.trackUpdatesFromSSE(MEMBERSHIPS);
|
|
33
35
|
currentChangeNumber = Math.max(currentChangeNumber, currentMaxChangeNumber_1); // use `currentMaxChangeNumber`, in case that `maxChangeNumber` was updated during fetch.
|
|
34
36
|
}
|
|
35
37
|
if (handleNewEvent) {
|
|
@@ -46,17 +48,20 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
|
|
|
46
48
|
}
|
|
47
49
|
return {
|
|
48
50
|
/**
|
|
49
|
-
* Invoked by NotificationProcessor on
|
|
51
|
+
* Invoked by NotificationProcessor on MY_(LARGE)_SEGMENTS_UPDATE notifications
|
|
50
52
|
*
|
|
51
|
-
* @param
|
|
52
|
-
* @param
|
|
53
|
+
* @param changeNumber change number of the notification
|
|
54
|
+
* @param segmentsData data for KeyList or SegmentRemoval instant updates
|
|
55
|
+
* @param delay optional time to wait for BoundedFetchRequest or BoundedFetchRequest updates
|
|
53
56
|
*/
|
|
54
|
-
put: function (
|
|
55
|
-
|
|
57
|
+
put: function (mySegmentsData, payload, delay) {
|
|
58
|
+
var type = mySegmentsData.type, cn = mySegmentsData.cn;
|
|
59
|
+
// Ignore event if it is outdated or if there is a pending fetch request (_delay is set)
|
|
60
|
+
if (cn <= currentChangeNumber || cn <= maxChangeNumber || _delay)
|
|
56
61
|
return;
|
|
57
|
-
maxChangeNumber =
|
|
62
|
+
maxChangeNumber = cn;
|
|
58
63
|
handleNewEvent = true;
|
|
59
|
-
_segmentsData =
|
|
64
|
+
_segmentsData = payload && { type: type, cn: cn, added: payload.added, removed: payload.removed };
|
|
60
65
|
_delay = delay;
|
|
61
66
|
if (backoff.timeoutID || !isHandlingEvent)
|
|
62
67
|
__handleMySegmentsUpdateCall();
|
|
@@ -64,6 +69,7 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
|
|
|
64
69
|
},
|
|
65
70
|
stop: function () {
|
|
66
71
|
clearTimeout(_delayTimeoutID);
|
|
72
|
+
_delay = undefined;
|
|
67
73
|
isHandlingEvent = false;
|
|
68
74
|
backoff.reset();
|
|
69
75
|
}
|
|
@@ -22,12 +22,11 @@ export var PUSH_SUBSYSTEM_UP = 'PUSH_SUBSYSTEM_UP';
|
|
|
22
22
|
*/
|
|
23
23
|
export var PUSH_SUBSYSTEM_DOWN = 'PUSH_SUBSYSTEM_DOWN';
|
|
24
24
|
// Update-type push notifications, handled by NotificationProcessor
|
|
25
|
-
export var
|
|
26
|
-
export var
|
|
25
|
+
export var MEMBERSHIP_MS_UPDATE = 'MEMBERSHIP_MS_UPDATE';
|
|
26
|
+
export var MEMBERSHIP_LS_UPDATE = 'MEMBERSHIP_LS_UPDATE';
|
|
27
27
|
export var SEGMENT_UPDATE = 'SEGMENT_UPDATE';
|
|
28
28
|
export var SPLIT_KILL = 'SPLIT_KILL';
|
|
29
29
|
export var SPLIT_UPDATE = 'SPLIT_UPDATE';
|
|
30
|
-
export var MY_LARGE_SEGMENTS_UPDATE = 'MY_LARGE_SEGMENTS_UPDATE';
|
|
31
30
|
// Control-type push notifications, handled by NotificationKeeper
|
|
32
31
|
export var CONTROL = 'CONTROL';
|
|
33
32
|
export var OCCUPANCY = 'OCCUPANCY';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { algorithms } from '../../utils/decompress';
|
|
2
2
|
import { decodeFromBase64 } from '../../utils/base64';
|
|
3
|
+
import { hash } from '../../utils/murmur3/murmur3';
|
|
3
4
|
var GZIP = 1;
|
|
4
5
|
var ZLIB = 2;
|
|
5
6
|
function Uint8ArrayToString(myUint8Arr) {
|
|
@@ -74,14 +75,17 @@ export function isInBitmap(bitmap, hash64hex) {
|
|
|
74
75
|
}
|
|
75
76
|
/**
|
|
76
77
|
* Parse feature flags notifications for instant feature flag updates
|
|
77
|
-
*
|
|
78
|
-
* @param {ISplitUpdateData} data
|
|
79
|
-
* @returns {KeyList}
|
|
80
78
|
*/
|
|
81
79
|
export function parseFFUpdatePayload(compression, data) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
return compression > 0 ?
|
|
81
|
+
parseKeyList(data, compression, false) :
|
|
82
|
+
JSON.parse(decodeFromBase64(data));
|
|
83
|
+
}
|
|
84
|
+
var DEFAULT_MAX_INTERVAL = 60000;
|
|
85
|
+
export function getDelay(parsedData, matchingKey) {
|
|
86
|
+
if (parsedData.h === 0)
|
|
87
|
+
return 0;
|
|
88
|
+
var interval = parsedData.i || DEFAULT_MAX_INTERVAL;
|
|
89
|
+
var seed = parsedData.s || 0;
|
|
90
|
+
return hash(matchingKey, seed) % interval;
|
|
87
91
|
}
|
|
@@ -8,19 +8,13 @@ import { authenticateFactory, hashUserKey } from './AuthClient';
|
|
|
8
8
|
import { forOwn } from '../../utils/lang';
|
|
9
9
|
import { SSEClient } from './SSEClient';
|
|
10
10
|
import { getMatching } from '../../utils/key';
|
|
11
|
-
import {
|
|
12
|
-
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT,
|
|
11
|
+
import { MEMBERSHIP_MS_UPDATE, MEMBERSHIP_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';
|
|
12
|
+
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIP_UPDATE, STREAMING_PARSING_SPLIT_UPDATE } from '../../logger/constants';
|
|
13
13
|
import { UpdateStrategy } from './SSEHandler/types';
|
|
14
|
-
import { isInBitmap, parseBitmap, parseFFUpdatePayload, parseKeyList } from './parseUtils';
|
|
14
|
+
import { getDelay, isInBitmap, parseBitmap, parseFFUpdatePayload, parseKeyList } from './parseUtils';
|
|
15
15
|
import { _Set } from '../../utils/lang/sets';
|
|
16
|
-
import { hash } from '../../utils/murmur3/murmur3';
|
|
17
16
|
import { hash64 } from '../../utils/murmur3/murmur3_64';
|
|
18
|
-
import { TOKEN_REFRESH, AUTH_REJECTION
|
|
19
|
-
export function getDelay(parsedData, matchingKey) {
|
|
20
|
-
var interval = parsedData.i || 60000;
|
|
21
|
-
var seed = parsedData.s || 0;
|
|
22
|
-
return hash(matchingKey, seed) % interval;
|
|
23
|
-
}
|
|
17
|
+
import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
|
|
24
18
|
/**
|
|
25
19
|
* PushManager factory:
|
|
26
20
|
* - for server-side if key is not provided in settings.
|
|
@@ -51,10 +45,10 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
51
45
|
var segmentsUpdateWorker = userKey ? undefined : SegmentsUpdateWorker(log, pollingManager.segmentsSyncTask, storage.segments);
|
|
52
46
|
// For server-side we pass the segmentsSyncTask, used by SplitsUpdateWorker to fetch new segments
|
|
53
47
|
var splitsUpdateWorker = SplitsUpdateWorker(log, storage.splits, pollingManager.splitsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask);
|
|
54
|
-
// [Only for client-side] map of hashes to user keys, to dispatch
|
|
48
|
+
// [Only for client-side] map of hashes to user keys, to dispatch membership update events to the corresponding MySegmentsUpdateWorker
|
|
55
49
|
var userKeyHashes = {};
|
|
56
50
|
// [Only for client-side] map of user keys to their corresponding hash64 and MySegmentsUpdateWorkers.
|
|
57
|
-
// Hash64 is used to process
|
|
51
|
+
// Hash64 is used to process membership update events and dispatch actions to the corresponding MySegmentsUpdateWorker.
|
|
58
52
|
var clients = {};
|
|
59
53
|
// [Only for client-side] variable to flag that a new client was added. It is needed to reconnect streaming.
|
|
60
54
|
var connectForNewClient = false;
|
|
@@ -148,7 +142,7 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
148
142
|
forOwn(clients, function (_a) {
|
|
149
143
|
var worker = _a.worker, workerLarge = _a.workerLarge;
|
|
150
144
|
worker.stop();
|
|
151
|
-
workerLarge
|
|
145
|
+
workerLarge.stop();
|
|
152
146
|
});
|
|
153
147
|
else
|
|
154
148
|
segmentsUpdateWorker.stop();
|
|
@@ -203,7 +197,7 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
203
197
|
splitsUpdateWorker.put(parsedData);
|
|
204
198
|
});
|
|
205
199
|
function handleMySegmentsUpdate(parsedData) {
|
|
206
|
-
var isLS = parsedData.type ===
|
|
200
|
+
var isLS = parsedData.type === MEMBERSHIP_LS_UPDATE;
|
|
207
201
|
switch (parsedData.u) {
|
|
208
202
|
case UpdateStrategy.BoundedFetchRequest: {
|
|
209
203
|
var bitmap_1;
|
|
@@ -211,15 +205,13 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
211
205
|
bitmap_1 = parseBitmap(parsedData.d, parsedData.c);
|
|
212
206
|
}
|
|
213
207
|
catch (e) {
|
|
214
|
-
log.warn(
|
|
208
|
+
log.warn(STREAMING_PARSING_MEMBERSHIP_UPDATE, ['BoundedFetchRequest', e]);
|
|
215
209
|
break;
|
|
216
210
|
}
|
|
217
211
|
forOwn(clients, function (_a, matchingKey) {
|
|
218
212
|
var hash64 = _a.hash64, worker = _a.worker, workerLarge = _a.workerLarge;
|
|
219
213
|
if (isInBitmap(bitmap_1, hash64.hex)) {
|
|
220
|
-
isLS ?
|
|
221
|
-
workerLarge && workerLarge.put(parsedData.changeNumber, undefined, getDelay(parsedData, matchingKey)) :
|
|
222
|
-
worker.put(parsedData.changeNumber);
|
|
214
|
+
(isLS ? workerLarge : worker).put(parsedData, undefined, getDelay(parsedData, matchingKey));
|
|
223
215
|
}
|
|
224
216
|
});
|
|
225
217
|
return;
|
|
@@ -232,65 +224,48 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
232
224
|
removed_1 = new _Set(keyList.r);
|
|
233
225
|
}
|
|
234
226
|
catch (e) {
|
|
235
|
-
log.warn(
|
|
227
|
+
log.warn(STREAMING_PARSING_MEMBERSHIP_UPDATE, ['KeyList', e]);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
if (!parsedData.n || !parsedData.n.length) {
|
|
231
|
+
log.warn(STREAMING_PARSING_MEMBERSHIP_UPDATE, ['KeyList', 'No segment name was provided']);
|
|
236
232
|
break;
|
|
237
233
|
}
|
|
238
234
|
forOwn(clients, function (_a) {
|
|
239
235
|
var hash64 = _a.hash64, worker = _a.worker, workerLarge = _a.workerLarge;
|
|
240
236
|
var add = added_1.has(hash64.dec) ? true : removed_1.has(hash64.dec) ? false : undefined;
|
|
241
237
|
if (add !== undefined) {
|
|
242
|
-
isLS ?
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}) :
|
|
247
|
-
worker.put(parsedData.changeNumber, {
|
|
248
|
-
name: parsedData.segmentName,
|
|
249
|
-
add: add
|
|
250
|
-
});
|
|
238
|
+
(isLS ? workerLarge : worker).put(parsedData, {
|
|
239
|
+
added: add ? [parsedData.n[0]] : [],
|
|
240
|
+
removed: add ? [] : [parsedData.n[0]]
|
|
241
|
+
});
|
|
251
242
|
}
|
|
252
243
|
});
|
|
253
244
|
return;
|
|
254
245
|
}
|
|
255
246
|
case UpdateStrategy.SegmentRemoval:
|
|
256
|
-
if (
|
|
257
|
-
log.warn(
|
|
247
|
+
if (!parsedData.n || !parsedData.n.length) {
|
|
248
|
+
log.warn(STREAMING_PARSING_MEMBERSHIP_UPDATE, ['SegmentRemoval', 'No segment name was provided']);
|
|
258
249
|
break;
|
|
259
250
|
}
|
|
260
251
|
forOwn(clients, function (_a) {
|
|
261
252
|
var worker = _a.worker, workerLarge = _a.workerLarge;
|
|
262
|
-
isLS ?
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
add: false
|
|
267
|
-
});
|
|
268
|
-
}) :
|
|
269
|
-
worker.put(parsedData.changeNumber, {
|
|
270
|
-
name: parsedData.segmentName,
|
|
271
|
-
add: false
|
|
272
|
-
});
|
|
253
|
+
(isLS ? workerLarge : worker).put(parsedData, {
|
|
254
|
+
added: [],
|
|
255
|
+
removed: parsedData.n
|
|
256
|
+
});
|
|
273
257
|
});
|
|
274
258
|
return;
|
|
275
259
|
}
|
|
276
260
|
// `UpdateStrategy.UnboundedFetchRequest` and fallbacks of other cases
|
|
277
261
|
forOwn(clients, function (_a, matchingKey) {
|
|
278
262
|
var worker = _a.worker, workerLarge = _a.workerLarge;
|
|
279
|
-
isLS ?
|
|
280
|
-
workerLarge && workerLarge.put(parsedData.changeNumber, undefined, getDelay(parsedData, matchingKey)) :
|
|
281
|
-
worker.put(parsedData.changeNumber);
|
|
263
|
+
(isLS ? workerLarge : worker).put(parsedData, undefined, getDelay(parsedData, matchingKey));
|
|
282
264
|
});
|
|
283
265
|
}
|
|
284
266
|
if (userKey) {
|
|
285
|
-
pushEmitter.on(
|
|
286
|
-
|
|
287
|
-
var userKey = userKeyHashes[userKeyHash];
|
|
288
|
-
if (userKey && clients[userKey]) { // check existence since it can be undefined if client has been destroyed
|
|
289
|
-
clients[userKey].worker.put(parsedData.changeNumber, parsedData.includesPayload ? parsedData.segmentList ? parsedData.segmentList : [] : undefined);
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
pushEmitter.on(MY_SEGMENTS_UPDATE_V2, handleMySegmentsUpdate);
|
|
293
|
-
pushEmitter.on(MY_LARGE_SEGMENTS_UPDATE, handleMySegmentsUpdate);
|
|
267
|
+
pushEmitter.on(MEMBERSHIP_MS_UPDATE, handleMySegmentsUpdate);
|
|
268
|
+
pushEmitter.on(MEMBERSHIP_LS_UPDATE, handleMySegmentsUpdate);
|
|
294
269
|
}
|
|
295
270
|
else {
|
|
296
271
|
pushEmitter.on(SEGMENT_UPDATE, segmentsUpdateWorker.put);
|
|
@@ -313,7 +288,7 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
313
288
|
return;
|
|
314
289
|
disconnected = false;
|
|
315
290
|
if (userKey)
|
|
316
|
-
this.add(userKey, pollingManager.segmentsSyncTask
|
|
291
|
+
this.add(userKey, pollingManager.segmentsSyncTask); // client-side
|
|
317
292
|
else
|
|
318
293
|
setTimeout(connectPush); // server-side runs in next cycle as in client-side, for consistency with client-side
|
|
319
294
|
},
|
|
@@ -322,14 +297,14 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
322
297
|
return disconnected === false;
|
|
323
298
|
},
|
|
324
299
|
// [Only for client-side]
|
|
325
|
-
add: function (userKey, mySegmentsSyncTask
|
|
300
|
+
add: function (userKey, mySegmentsSyncTask) {
|
|
326
301
|
var hash = hashUserKey(userKey);
|
|
327
302
|
if (!userKeyHashes[hash]) {
|
|
328
303
|
userKeyHashes[hash] = userKey;
|
|
329
304
|
clients[userKey] = {
|
|
330
305
|
hash64: hash64(userKey),
|
|
331
|
-
worker: MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker
|
|
332
|
-
workerLarge:
|
|
306
|
+
worker: MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker),
|
|
307
|
+
workerLarge: MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker)
|
|
333
308
|
};
|
|
334
309
|
connectForNewClient = true; // we must reconnect on start, to listen the channel for the new user key
|
|
335
310
|
// Reconnects in case of a new client.
|
|
@@ -61,12 +61,10 @@ export function telemetryCacheConfigAdapter(telemetry, settings) {
|
|
|
61
61
|
var _a = getTelemetryFlagSetsStats(settings.sync.__splitFiltersValidation), flagSetsTotal = _a.flagSetsTotal, flagSetsIgnored = _a.flagSetsIgnored;
|
|
62
62
|
return objectAssign(getTelemetryConfigStats(settings.mode, settings.storage.type), {
|
|
63
63
|
sE: settings.streamingEnabled,
|
|
64
|
-
lE: isClientSide ? settings.sync.largeSegmentsEnabled : undefined,
|
|
65
64
|
rR: {
|
|
66
65
|
sp: scheduler.featuresRefreshRate / 1000,
|
|
67
66
|
se: isClientSide ? undefined : scheduler.segmentsRefreshRate / 1000,
|
|
68
67
|
ms: isClientSide ? scheduler.segmentsRefreshRate / 1000 : undefined,
|
|
69
|
-
mls: isClientSide && settings.sync.largeSegmentsEnabled ? scheduler.largeSegmentsRefreshRate / 1000 : undefined,
|
|
70
68
|
im: scheduler.impressionsRefreshRate / 1000,
|
|
71
69
|
ev: scheduler.eventsPushRate / 1000,
|
|
72
70
|
te: scheduler.telemetryRefreshRate / 1000,
|
|
@@ -2,7 +2,7 @@ import { submitterManagerFactory } from './submitters/submitterManager';
|
|
|
2
2
|
import { PUSH_SUBSYSTEM_UP, PUSH_SUBSYSTEM_DOWN } from './streaming/constants';
|
|
3
3
|
import { SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING } from '../logger/constants';
|
|
4
4
|
import { isConsentGranted } from '../consent';
|
|
5
|
-
import {
|
|
5
|
+
import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
|
|
6
6
|
/**
|
|
7
7
|
* Online SyncManager factory.
|
|
8
8
|
* Can be used for server-side API, and client-side API with or without multiple clients.
|
|
@@ -114,53 +114,43 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
|
|
|
114
114
|
shared: function (matchingKey, readinessManager, storage) {
|
|
115
115
|
if (!pollingManager)
|
|
116
116
|
return;
|
|
117
|
-
var
|
|
117
|
+
var mySegmentsSyncTask = pollingManager.add(matchingKey, readinessManager, storage);
|
|
118
118
|
return {
|
|
119
|
-
isRunning:
|
|
119
|
+
isRunning: mySegmentsSyncTask.isRunning,
|
|
120
120
|
start: function () {
|
|
121
121
|
if (syncEnabled) {
|
|
122
122
|
if (pushManager) {
|
|
123
123
|
if (pollingManager.isRunning()) {
|
|
124
124
|
// if doing polling, we must start the periodic fetch of data
|
|
125
|
-
if (storage.splits.
|
|
126
|
-
|
|
127
|
-
if (mlsSyncTask && storage.splits.usesMatcher(IN_LARGE_SEGMENT))
|
|
128
|
-
mlsSyncTask.start();
|
|
125
|
+
if (storage.splits.usesSegments())
|
|
126
|
+
mySegmentsSyncTask.start();
|
|
129
127
|
}
|
|
130
128
|
else {
|
|
131
129
|
// if not polling, we must execute the sync task for the initial fetch
|
|
132
130
|
// of segments since `syncAll` was already executed when starting the main client
|
|
133
|
-
|
|
134
|
-
mlsSyncTask && mlsSyncTask.execute();
|
|
131
|
+
mySegmentsSyncTask.execute();
|
|
135
132
|
}
|
|
136
|
-
pushManager.add(matchingKey,
|
|
133
|
+
pushManager.add(matchingKey, mySegmentsSyncTask);
|
|
137
134
|
}
|
|
138
135
|
else {
|
|
139
|
-
if (storage.splits.
|
|
140
|
-
|
|
141
|
-
if (mlsSyncTask && storage.splits.usesMatcher(IN_LARGE_SEGMENT))
|
|
142
|
-
mlsSyncTask.start();
|
|
136
|
+
if (storage.splits.usesSegments())
|
|
137
|
+
mySegmentsSyncTask.start();
|
|
143
138
|
}
|
|
144
139
|
}
|
|
145
140
|
else {
|
|
146
|
-
if (!readinessManager.isReady())
|
|
147
|
-
|
|
148
|
-
mlsSyncTask && mlsSyncTask.execute();
|
|
149
|
-
}
|
|
141
|
+
if (!readinessManager.isReady())
|
|
142
|
+
mySegmentsSyncTask.execute();
|
|
150
143
|
}
|
|
151
144
|
},
|
|
152
145
|
stop: function () {
|
|
153
146
|
// check in case `client.destroy()` has been invoked more than once for the same client
|
|
154
|
-
var
|
|
155
|
-
if (
|
|
156
|
-
var msSyncTask_1 = syncTasks.msSyncTask, mlsSyncTask_1 = syncTasks.mlsSyncTask;
|
|
147
|
+
var mySegmentsSyncTask = pollingManager.get(matchingKey);
|
|
148
|
+
if (mySegmentsSyncTask) {
|
|
157
149
|
// stop syncing
|
|
158
150
|
if (pushManager)
|
|
159
151
|
pushManager.remove(matchingKey);
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
-
if (mlsSyncTask_1 && mlsSyncTask_1.isRunning())
|
|
163
|
-
mlsSyncTask_1.stop();
|
|
152
|
+
if (mySegmentsSyncTask.isRunning())
|
|
153
|
+
mySegmentsSyncTask.stop();
|
|
164
154
|
pollingManager.remove(matchingKey);
|
|
165
155
|
}
|
|
166
156
|
},
|
|
@@ -60,8 +60,7 @@ export var EVENTS = 'ev';
|
|
|
60
60
|
export var TELEMETRY = 'te';
|
|
61
61
|
export var TOKEN = 'to';
|
|
62
62
|
export var SEGMENT = 'se';
|
|
63
|
-
export var
|
|
64
|
-
export var MY_LARGE_SEGMENT = 'mls';
|
|
63
|
+
export var MEMBERSHIPS = 'ms';
|
|
65
64
|
export var TREATMENT = 't';
|
|
66
65
|
export var TREATMENTS = 'ts';
|
|
67
66
|
export var TREATMENT_WITH_CONFIG = 'tc';
|
|
@@ -87,7 +86,7 @@ export var NON_REQUESTED = 1;
|
|
|
87
86
|
export var DISABLED = 0;
|
|
88
87
|
export var ENABLED = 1;
|
|
89
88
|
export var PAUSED = 2;
|
|
90
|
-
export var FLAG_SPEC_VERSION = '1.
|
|
89
|
+
export var FLAG_SPEC_VERSION = '1.2';
|
|
91
90
|
// Matcher types
|
|
92
91
|
export var IN_SEGMENT = 'IN_SEGMENT';
|
|
93
92
|
export var IN_LARGE_SEGMENT = 'IN_LARGE_SEGMENT';
|
|
@@ -27,8 +27,6 @@ export var base = {
|
|
|
27
27
|
featuresRefreshRate: 60,
|
|
28
28
|
// fetch segments updates each 60 sec
|
|
29
29
|
segmentsRefreshRate: 60,
|
|
30
|
-
// fetch large segments updates each 60 sec
|
|
31
|
-
largeSegmentsRefreshRate: 60,
|
|
32
30
|
// publish telemetry stats each 3600 secs (1 hour)
|
|
33
31
|
telemetryRefreshRate: 3600,
|
|
34
32
|
// publish evaluations each 300 sec (default value for OPTIMIZED impressions mode)
|
|
@@ -74,8 +72,7 @@ export var base = {
|
|
|
74
72
|
impressionsMode: OPTIMIZED,
|
|
75
73
|
localhostMode: undefined,
|
|
76
74
|
enabled: true,
|
|
77
|
-
flagSpecVersion: FLAG_SPEC_VERSION
|
|
78
|
-
largeSegmentsEnabled: false
|
|
75
|
+
flagSpecVersion: FLAG_SPEC_VERSION
|
|
79
76
|
},
|
|
80
77
|
// Logger
|
|
81
78
|
log: undefined
|
|
@@ -114,7 +111,6 @@ export function settingsValidation(config, validationParams) {
|
|
|
114
111
|
var scheduler = withDefaults.scheduler, startup = withDefaults.startup;
|
|
115
112
|
scheduler.featuresRefreshRate = fromSecondsToMillis(scheduler.featuresRefreshRate);
|
|
116
113
|
scheduler.segmentsRefreshRate = fromSecondsToMillis(scheduler.segmentsRefreshRate);
|
|
117
|
-
scheduler.largeSegmentsRefreshRate = fromSecondsToMillis(scheduler.largeSegmentsRefreshRate);
|
|
118
114
|
scheduler.offlineRefreshRate = fromSecondsToMillis(scheduler.offlineRefreshRate);
|
|
119
115
|
scheduler.eventsPushRate = fromSecondsToMillis(scheduler.eventsPushRate);
|
|
120
116
|
scheduler.telemetryRefreshRate = fromSecondsToMillis(validateMinValue('telemetryRefreshRate', scheduler.telemetryRefreshRate, 60));
|
package/package.json
CHANGED
package/src/dtos/types.ts
CHANGED
|
@@ -224,18 +224,17 @@ export interface ISegmentChangesResponse {
|
|
|
224
224
|
till: number
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
/** Interface of the parsed JSON response of `/mySegments/{userKey}` */
|
|
228
227
|
export interface IMySegmentsResponse {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
cn?: number,
|
|
229
|
+
k?: {
|
|
230
|
+
n: string
|
|
232
231
|
}[]
|
|
233
232
|
}
|
|
234
233
|
|
|
235
|
-
/** Interface of the parsed JSON response of `/
|
|
236
|
-
export interface
|
|
237
|
-
|
|
238
|
-
|
|
234
|
+
/** Interface of the parsed JSON response of `/memberships/{userKey}` */
|
|
235
|
+
export interface IMembershipsResponse {
|
|
236
|
+
ms?: IMySegmentsResponse,
|
|
237
|
+
ls?: IMySegmentsResponse
|
|
239
238
|
}
|
|
240
239
|
|
|
241
240
|
/** Metadata internal type for storages */
|
package/src/logger/constants.ts
CHANGED
|
@@ -36,6 +36,7 @@ export const IMPRESSION = 102;
|
|
|
36
36
|
export const IMPRESSION_QUEUEING = 103;
|
|
37
37
|
export const NEW_SHARED_CLIENT = 104;
|
|
38
38
|
export const NEW_FACTORY = 105;
|
|
39
|
+
export const POLLING_SMART_PAUSING = 106;
|
|
39
40
|
export const POLLING_START = 107;
|
|
40
41
|
export const POLLING_STOP = 108;
|
|
41
42
|
export const SYNC_SPLITS_FETCH_RETRY = 109;
|
|
@@ -78,7 +79,7 @@ export const WARN_SPLITS_FILTER_IGNORED = 219;
|
|
|
78
79
|
export const WARN_SPLITS_FILTER_INVALID = 220;
|
|
79
80
|
export const WARN_SPLITS_FILTER_EMPTY = 221;
|
|
80
81
|
export const WARN_SDK_KEY = 222;
|
|
81
|
-
export const
|
|
82
|
+
export const STREAMING_PARSING_MEMBERSHIP_UPDATE = 223;
|
|
82
83
|
export const STREAMING_PARSING_SPLIT_UPDATE = 224;
|
|
83
84
|
export const WARN_INVALID_FLAGSET = 225;
|
|
84
85
|
export const WARN_LOWERCASE_FLAGSET = 226;
|
|
@@ -19,10 +19,11 @@ export const codesInfo: [number, string][] = codesWarn.concat([
|
|
|
19
19
|
[c.USER_CONSENT_INITIAL, 'Starting the SDK with %s user consent. No data will be sent.'],
|
|
20
20
|
|
|
21
21
|
// synchronizer
|
|
22
|
+
[c.POLLING_SMART_PAUSING, c.LOG_PREFIX_SYNC_POLLING + 'Turning segments data polling %s.'],
|
|
22
23
|
[c.POLLING_START, c.LOG_PREFIX_SYNC_POLLING + 'Starting polling'],
|
|
23
24
|
[c.POLLING_STOP, c.LOG_PREFIX_SYNC_POLLING + 'Stopping polling'],
|
|
24
25
|
[c.SYNC_SPLITS_FETCH_RETRY, c.LOG_PREFIX_SYNC_SPLITS + 'Retrying download of feature flags #%s. Reason: %s'],
|
|
25
|
-
[c.SUBMITTERS_PUSH_FULL_QUEUE, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Flushing full %s queue and
|
|
26
|
+
[c.SUBMITTERS_PUSH_FULL_QUEUE, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Flushing full %s queue and resetting timer.'],
|
|
26
27
|
[c.SUBMITTERS_PUSH, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Pushing %s.'],
|
|
27
28
|
[c.STREAMING_REFRESH_TOKEN, c.LOG_PREFIX_SYNC_STREAMING + 'Refreshing streaming token in %s seconds, and connecting streaming in %s seconds.'],
|
|
28
29
|
[c.STREAMING_RECONNECT, c.LOG_PREFIX_SYNC_STREAMING + 'Attempting to reconnect streaming in %s seconds.'],
|
|
@@ -32,7 +32,7 @@ export const codesWarn: [number, string][] = codesError.concat([
|
|
|
32
32
|
[c.WARN_SPLITS_FILTER_EMPTY, c.LOG_PREFIX_SETTINGS + ': feature flag filter configuration must be a non-empty array of filter objects.'],
|
|
33
33
|
[c.WARN_SDK_KEY, c.LOG_PREFIX_SETTINGS + ': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'],
|
|
34
34
|
|
|
35
|
-
[c.
|
|
35
|
+
[c.STREAMING_PARSING_MEMBERSHIP_UPDATE, c.LOG_PREFIX_SYNC_STREAMING + 'Fetching Memberships due to an error processing %s notification: %s'],
|
|
36
36
|
[c.STREAMING_PARSING_SPLIT_UPDATE, c.LOG_PREFIX_SYNC_STREAMING + 'Fetching SplitChanges due to an error processing SPLIT_UPDATE notification: %s'],
|
|
37
37
|
[c.WARN_INVALID_FLAGSET, '%s: you passed %s, flag set must adhere to the regular expressions %s. This means a flag set must start with a letter or number, be in lowercase, alphanumeric and have a max length of 50 characters. %s was discarded.'],
|
|
38
38
|
[c.WARN_LOWERCASE_FLAGSET, '%s: flag set %s should be all lowercase - converting string to lowercase.'],
|
|
@@ -10,7 +10,7 @@ function splitsEventEmitterFactory(EventEmitter: new () => IEventEmitter): ISpli
|
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
// `isSplitKill` condition avoids an edge-case of wrongly emitting SDK_READY if:
|
|
13
|
-
// - `/
|
|
13
|
+
// - `/memberships` fetch and SPLIT_KILL occurs before `/splitChanges` fetch, and
|
|
14
14
|
// - storage has cached splits (for which case `splitsStorage.killLocally` can return true)
|
|
15
15
|
splitsEventEmitter.on(SDK_SPLITS_ARRIVED, (isSplitKill: boolean) => { if (!isSplitKill) splitsEventEmitter.splitsArrived = true; });
|
|
16
16
|
splitsEventEmitter.once(SDK_SPLITS_CACHE_LOADED, () => { splitsEventEmitter.splitsCacheLoaded = true; });
|
|
@@ -18,8 +18,10 @@ function splitsEventEmitterFactory(EventEmitter: new () => IEventEmitter): ISpli
|
|
|
18
18
|
return splitsEventEmitter;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
function segmentsEventEmitterFactory(EventEmitter: new () => IEventEmitter
|
|
22
|
-
const segmentsEventEmitter = objectAssign(new EventEmitter(), {
|
|
21
|
+
function segmentsEventEmitterFactory(EventEmitter: new () => IEventEmitter): ISegmentsEventEmitter {
|
|
22
|
+
const segmentsEventEmitter = objectAssign(new EventEmitter(), {
|
|
23
|
+
segmentsArrived: false
|
|
24
|
+
});
|
|
23
25
|
|
|
24
26
|
segmentsEventEmitter.once(SDK_SEGMENTS_ARRIVED, () => { segmentsEventEmitter.segmentsArrived = true; });
|
|
25
27
|
|
|
@@ -34,10 +36,9 @@ export function readinessManagerFactory(
|
|
|
34
36
|
settings: ISettings,
|
|
35
37
|
splits: ISplitsEventEmitter = splitsEventEmitterFactory(EventEmitter)): IReadinessManager {
|
|
36
38
|
|
|
37
|
-
const
|
|
39
|
+
const readyTimeout = settings.startup.readyTimeout;
|
|
38
40
|
|
|
39
41
|
const segments: ISegmentsEventEmitter = segmentsEventEmitterFactory(EventEmitter);
|
|
40
|
-
const largeSegments = largeSegmentsEnabled ? segmentsEventEmitterFactory(EventEmitter, !waitForLargeSegments) : undefined;
|
|
41
42
|
const gate: IReadinessEventEmitter = new EventEmitter();
|
|
42
43
|
|
|
43
44
|
// emit SDK_READY_FROM_CACHE
|
|
@@ -63,7 +64,6 @@ export function readinessManagerFactory(
|
|
|
63
64
|
let isReady = false;
|
|
64
65
|
splits.on(SDK_SPLITS_ARRIVED, checkIsReadyOrUpdate);
|
|
65
66
|
segments.on(SDK_SEGMENTS_ARRIVED, checkIsReadyOrUpdate);
|
|
66
|
-
if (largeSegments) largeSegments.on(SDK_SEGMENTS_ARRIVED, checkIsReadyOrUpdate);
|
|
67
67
|
|
|
68
68
|
let isDestroyed = false;
|
|
69
69
|
|
|
@@ -89,7 +89,7 @@ export function readinessManagerFactory(
|
|
|
89
89
|
setTimeout(() => { throw e; }, 0);
|
|
90
90
|
}
|
|
91
91
|
} else {
|
|
92
|
-
if (splits.splitsArrived && segments.segmentsArrived
|
|
92
|
+
if (splits.splitsArrived && segments.segmentsArrived) {
|
|
93
93
|
clearTimeout(readyTimeoutId);
|
|
94
94
|
isReady = true;
|
|
95
95
|
try {
|
|
@@ -107,7 +107,6 @@ export function readinessManagerFactory(
|
|
|
107
107
|
return {
|
|
108
108
|
splits,
|
|
109
109
|
segments,
|
|
110
|
-
largeSegments,
|
|
111
110
|
gate,
|
|
112
111
|
|
|
113
112
|
shared() {
|
|
@@ -126,7 +125,6 @@ export function readinessManagerFactory(
|
|
|
126
125
|
isDestroyed = true;
|
|
127
126
|
|
|
128
127
|
segments.removeAllListeners();
|
|
129
|
-
if (largeSegments) largeSegments.removeAllListeners();
|
|
130
128
|
gate.removeAllListeners();
|
|
131
129
|
clearTimeout(readyTimeoutId);
|
|
132
130
|
|
package/src/readiness/types.ts
CHANGED
|
@@ -45,7 +45,6 @@ export interface IReadinessManager {
|
|
|
45
45
|
/** Event emitters */
|
|
46
46
|
splits: ISplitsEventEmitter,
|
|
47
47
|
segments: ISegmentsEventEmitter,
|
|
48
|
-
largeSegments?: ISegmentsEventEmitter, // Undefined if largeSegmentsEnabled or waitForLargeSegments are false
|
|
49
48
|
gate: IReadinessEventEmitter,
|
|
50
49
|
|
|
51
50
|
/** Readiness status */
|
package/src/services/splitApi.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { splitHttpClientFactory } from './splitHttpClient';
|
|
|
4
4
|
import { ISplitApi } from './types';
|
|
5
5
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
6
6
|
import { ITelemetryTracker } from '../trackers/types';
|
|
7
|
-
import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT,
|
|
7
|
+
import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MEMBERSHIPS } from '../utils/constants';
|
|
8
8
|
import { ERROR_TOO_MANY_SETS } from '../logger/constants';
|
|
9
9
|
|
|
10
10
|
const noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
|
|
@@ -22,7 +22,7 @@ function userKeyToQueryParam(userKey: string) {
|
|
|
22
22
|
*/
|
|
23
23
|
export function splitApiFactory(
|
|
24
24
|
settings: ISettings,
|
|
25
|
-
platform: IPlatform,
|
|
25
|
+
platform: Pick<IPlatform, 'getOptions' | 'getFetch'>,
|
|
26
26
|
telemetryTracker: ITelemetryTracker
|
|
27
27
|
): ISplitApi {
|
|
28
28
|
|
|
@@ -67,20 +67,15 @@ export function splitApiFactory(
|
|
|
67
67
|
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SEGMENT));
|
|
68
68
|
},
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
fetchMemberships(userMatchingKey: string, noCache?: boolean) {
|
|
71
71
|
/**
|
|
72
72
|
* URI encoding of user keys in order to:
|
|
73
|
-
* - avoid 400 responses (due to URI malformed). E.g.: '/api/
|
|
74
|
-
* - avoid 404 responses. E.g.: '/api/
|
|
73
|
+
* - avoid 400 responses (due to URI malformed). E.g.: '/api/memberships/%'
|
|
74
|
+
* - avoid 404 responses. E.g.: '/api/memberships/foo/bar'
|
|
75
75
|
* - match user keys with special characters. E.g.: 'foo%bar', 'foo/bar'
|
|
76
76
|
*/
|
|
77
|
-
const url = `${urls.sdk}/
|
|
78
|
-
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(
|
|
79
|
-
},
|
|
80
|
-
|
|
81
|
-
fetchMyLargeSegments(userMatchingKey: string, noCache?: boolean) {
|
|
82
|
-
const url = `${urls.sdk}/myLargeSegments/${encodeURIComponent(userMatchingKey)}`;
|
|
83
|
-
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(MY_LARGE_SEGMENT));
|
|
77
|
+
const url = `${urls.sdk}/memberships/${encodeURIComponent(userMatchingKey)}`;
|
|
78
|
+
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(MEMBERSHIPS));
|
|
84
79
|
},
|
|
85
80
|
|
|
86
81
|
/**
|