@splitsoftware/splitio-commons 1.17.0 → 1.17.1-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.
- package/CHANGES.txt +8 -0
- package/cjs/evaluator/matchers/index.js +3 -1
- package/cjs/evaluator/matchers/large_segment.js +16 -0
- package/cjs/evaluator/matchers/matcherTypes.js +1 -0
- package/cjs/evaluator/matchersTransform/index.js +4 -1
- package/cjs/evaluator/matchersTransform/segment.js +3 -1
- package/cjs/logger/constants.js +2 -2
- package/cjs/logger/messages/info.js +1 -1
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/readiness/readinessManager.js +5 -6
- package/cjs/readiness/sdkReadinessManager.js +5 -6
- package/cjs/sdkClient/identity.js +7 -0
- package/cjs/sdkClient/sdkClient.js +5 -5
- package/cjs/sdkClient/sdkClientMethod.js +3 -1
- package/cjs/sdkClient/sdkClientMethodCS.js +9 -14
- package/cjs/sdkClient/sdkClientMethodCSWithTT.js +9 -14
- package/cjs/sdkFactory/index.js +6 -2
- package/cjs/services/splitApi.js +5 -5
- package/cjs/storages/AbstractSegmentsCacheSync.js +41 -12
- package/cjs/storages/AbstractSplitsCacheSync.js +2 -1
- package/cjs/storages/KeyBuilderCS.js +23 -5
- package/cjs/storages/dataLoader.js +1 -1
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +29 -52
- package/cjs/storages/inLocalStorage/index.js +6 -2
- package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -0
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +9 -40
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +8 -8
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +7 -10
- package/cjs/storages/pluggable/inMemoryWrapper.js +1 -1
- package/cjs/sync/polling/fetchers/mySegmentsFetcher.js +5 -8
- package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/cjs/sync/polling/pollingManagerCS.js +1 -1
- package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +15 -21
- package/cjs/sync/streaming/AuthClient/index.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +3 -5
- package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +107 -48
- package/cjs/sync/streaming/constants.js +3 -3
- package/cjs/sync/streaming/parseUtils.js +14 -9
- package/cjs/sync/streaming/pushManager.js +69 -67
- package/cjs/utils/constants/index.js +5 -4
- package/cjs/utils/settingsValidation/index.js +2 -1
- package/esm/evaluator/matchers/index.js +3 -1
- package/esm/evaluator/matchers/large_segment.js +12 -0
- package/esm/evaluator/matchers/matcherTypes.js +1 -0
- package/esm/evaluator/matchersTransform/index.js +4 -1
- package/esm/evaluator/matchersTransform/segment.js +3 -1
- package/esm/logger/constants.js +1 -1
- package/esm/logger/messages/info.js +1 -1
- package/esm/logger/messages/warn.js +1 -1
- package/esm/readiness/readinessManager.js +5 -6
- package/esm/readiness/sdkReadinessManager.js +5 -6
- package/esm/sdkClient/identity.js +3 -0
- package/esm/sdkClient/sdkClient.js +5 -5
- package/esm/sdkClient/sdkClientMethod.js +3 -1
- package/esm/sdkClient/sdkClientMethodCS.js +7 -12
- package/esm/sdkClient/sdkClientMethodCSWithTT.js +7 -12
- package/esm/sdkFactory/index.js +6 -2
- package/esm/services/splitApi.js +6 -6
- package/esm/storages/AbstractSegmentsCacheSync.js +41 -12
- package/esm/storages/AbstractSplitsCacheSync.js +3 -2
- package/esm/storages/KeyBuilderCS.js +21 -4
- package/esm/storages/dataLoader.js +1 -1
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +29 -52
- package/esm/storages/inLocalStorage/index.js +7 -3
- package/esm/storages/inMemory/InMemoryStorageCS.js +5 -0
- package/esm/storages/inMemory/MySegmentsCacheInMemory.js +9 -40
- package/esm/storages/inMemory/SplitsCacheInMemory.js +8 -8
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +7 -10
- package/esm/storages/pluggable/inMemoryWrapper.js +1 -1
- package/esm/sync/polling/fetchers/mySegmentsFetcher.js +5 -8
- package/esm/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/esm/sync/polling/pollingManagerCS.js +1 -1
- package/esm/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +15 -21
- package/esm/sync/streaming/AuthClient/index.js +1 -1
- package/esm/sync/streaming/SSEHandler/index.js +4 -6
- package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +108 -49
- package/esm/sync/streaming/constants.js +2 -2
- package/esm/sync/streaming/parseUtils.js +12 -8
- package/esm/sync/streaming/pushManager.js +72 -70
- package/esm/utils/constants/index.js +3 -2
- package/esm/utils/settingsValidation/index.js +2 -1
- package/package.json +1 -1
- package/src/dtos/types.ts +21 -7
- package/src/evaluator/matchers/index.ts +2 -0
- package/src/evaluator/matchers/large_segment.ts +18 -0
- package/src/evaluator/matchers/matcherTypes.ts +1 -0
- package/src/evaluator/matchersTransform/index.ts +4 -1
- package/src/evaluator/matchersTransform/segment.ts +5 -3
- package/src/logger/constants.ts +1 -1
- package/src/logger/messages/info.ts +1 -1
- package/src/logger/messages/warn.ts +1 -1
- package/src/readiness/readinessManager.ts +7 -5
- package/src/readiness/sdkReadinessManager.ts +7 -7
- package/src/readiness/types.ts +2 -2
- package/src/sdkClient/identity.ts +5 -0
- package/src/sdkClient/sdkClient.ts +5 -5
- package/src/sdkClient/sdkClientMethod.ts +4 -1
- package/src/sdkClient/sdkClientMethodCS.ts +7 -13
- package/src/sdkClient/sdkClientMethodCSWithTT.ts +7 -13
- package/src/sdkFactory/index.ts +8 -4
- package/src/sdkFactory/types.ts +2 -1
- package/src/services/splitApi.ts +7 -7
- package/src/services/splitHttpClient.ts +1 -1
- package/src/services/types.ts +2 -2
- package/src/storages/AbstractSegmentsCacheSync.ts +53 -12
- package/src/storages/AbstractSplitsCacheSync.ts +4 -3
- package/src/storages/KeyBuilderCS.ts +34 -5
- package/src/storages/dataLoader.ts +1 -1
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +29 -59
- package/src/storages/inLocalStorage/index.ts +8 -4
- package/src/storages/inMemory/InMemoryStorageCS.ts +5 -0
- package/src/storages/inMemory/MySegmentsCacheInMemory.ts +10 -44
- package/src/storages/inMemory/SplitsCacheInMemory.ts +7 -8
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +7 -11
- package/src/storages/pluggable/inMemoryWrapper.ts +1 -1
- package/src/storages/types.ts +11 -7
- package/src/sync/polling/fetchers/mySegmentsFetcher.ts +8 -10
- package/src/sync/polling/fetchers/segmentChangesFetcher.ts +1 -1
- package/src/sync/polling/fetchers/types.ts +3 -2
- package/src/sync/polling/pollingManagerCS.ts +4 -4
- package/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +4 -5
- package/src/sync/polling/types.ts +7 -6
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +19 -22
- 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 -8
- package/src/sync/streaming/SSEHandler/types.ts +15 -15
- package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +116 -49
- 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 -2
- package/src/sync/streaming/parseUtils.ts +19 -11
- package/src/sync/streaming/pushManager.ts +73 -72
- package/src/sync/streaming/types.ts +10 -10
- package/src/sync/submitters/types.ts +8 -5
- package/src/types.ts +7 -1
- package/src/utils/constants/index.ts +3 -2
- package/src/utils/settingsValidation/index.ts +3 -2
- package/src/utils/settingsValidation/types.ts +1 -1
- package/types/dtos/types.d.ts +18 -7
- package/types/evaluator/matchersTransform/segment.d.ts +2 -2
- package/types/logger/constants.d.ts +1 -1
- package/types/readiness/readinessManager.d.ts +2 -2
- package/types/readiness/sdkReadinessManager.d.ts +2 -3
- package/types/readiness/types.d.ts +2 -2
- package/types/sdkClient/identity.d.ts +0 -4
- package/types/sdkClient/sdkClientMethod.d.ts +1 -1
- package/types/sdkFactory/types.d.ts +2 -1
- package/types/services/splitApi.d.ts +1 -1
- package/types/services/splitHttpClient.d.ts +1 -1
- package/types/services/types.d.ts +2 -2
- package/types/storages/AbstractMySegmentsCacheSync.d.ts +39 -0
- package/types/storages/AbstractSegmentsCacheSync.d.ts +9 -11
- package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
- package/types/storages/KeyBuilderCS.d.ts +9 -2
- package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +4 -14
- package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +3 -9
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +1 -1
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +4 -6
- package/types/storages/pluggable/inMemoryWrapper.d.ts +1 -1
- package/types/storages/types.d.ts +7 -5
- 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 +2 -2
- package/types/sync/polling/types.d.ts +7 -4
- package/types/sync/polling/updaters/mySegmentsUpdater.d.ts +4 -3
- package/types/sync/streaming/SSEHandler/types.d.ts +16 -14
- package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +4 -2
- 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 -2
- package/types/sync/streaming/parseUtils.d.ts +4 -5
- package/types/sync/streaming/types.d.ts +8 -8
- package/types/sync/submitters/types.d.ts +7 -4
- package/types/types.d.ts +7 -1
- package/types/utils/constants/index.d.ts +3 -2
- package/types/utils/settingsValidation/types.d.ts +1 -1
|
@@ -8,10 +8,10 @@ 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 { 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';
|
|
12
|
+
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';
|
|
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
16
|
import { hash64 } from '../../utils/murmur3/murmur3_64';
|
|
17
17
|
import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
|
|
@@ -45,10 +45,10 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
45
45
|
var segmentsUpdateWorker = userKey ? undefined : SegmentsUpdateWorker(log, pollingManager.segmentsSyncTask, storage.segments);
|
|
46
46
|
// For server-side we pass the segmentsSyncTask, used by SplitsUpdateWorker to fetch new segments
|
|
47
47
|
var splitsUpdateWorker = SplitsUpdateWorker(log, storage.splits, pollingManager.splitsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask);
|
|
48
|
-
// [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
|
|
49
49
|
var userKeyHashes = {};
|
|
50
50
|
// [Only for client-side] map of user keys to their corresponding hash64 and MySegmentsUpdateWorkers.
|
|
51
|
-
// Hash64 is used to process
|
|
51
|
+
// Hash64 is used to process membership update events and dispatch actions to the corresponding MySegmentsUpdateWorker.
|
|
52
52
|
var clients = {};
|
|
53
53
|
// [Only for client-side] variable to flag that a new client was added. It is needed to reconnect streaming.
|
|
54
54
|
var connectForNewClient = false;
|
|
@@ -195,77 +195,76 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
195
195
|
}
|
|
196
196
|
splitsUpdateWorker.put(parsedData);
|
|
197
197
|
});
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
pushEmitter.on(MY_SEGMENTS_UPDATE_V2, function handleMySegmentsUpdate(parsedData) {
|
|
207
|
-
switch (parsedData.u) {
|
|
208
|
-
case UpdateStrategy.BoundedFetchRequest: {
|
|
209
|
-
var bitmap_1;
|
|
210
|
-
try {
|
|
211
|
-
bitmap_1 = parseBitmap(parsedData.d, parsedData.c);
|
|
212
|
-
}
|
|
213
|
-
catch (e) {
|
|
214
|
-
log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['BoundedFetchRequest', e]);
|
|
215
|
-
break;
|
|
216
|
-
}
|
|
217
|
-
forOwn(clients, function (_a) {
|
|
218
|
-
var hash64 = _a.hash64, worker = _a.worker;
|
|
219
|
-
if (isInBitmap(bitmap_1, hash64.hex)) {
|
|
220
|
-
worker.put(parsedData.changeNumber); // fetch mySegments
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
return;
|
|
198
|
+
function handleMySegmentsUpdate(parsedData) {
|
|
199
|
+
switch (parsedData.u) {
|
|
200
|
+
case UpdateStrategy.BoundedFetchRequest: {
|
|
201
|
+
var bitmap_1;
|
|
202
|
+
try {
|
|
203
|
+
bitmap_1 = parseBitmap(parsedData.d, parsedData.c);
|
|
224
204
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
keyList = parseKeyList(parsedData.d, parsedData.c);
|
|
229
|
-
added_1 = new _Set(keyList.a);
|
|
230
|
-
removed_1 = new _Set(keyList.r);
|
|
231
|
-
}
|
|
232
|
-
catch (e) {
|
|
233
|
-
log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['KeyList', e]);
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
forOwn(clients, function (_a) {
|
|
237
|
-
var hash64 = _a.hash64, worker = _a.worker;
|
|
238
|
-
var add = added_1.has(hash64.dec) ? true : removed_1.has(hash64.dec) ? false : undefined;
|
|
239
|
-
if (add !== undefined) {
|
|
240
|
-
worker.put(parsedData.changeNumber, {
|
|
241
|
-
name: parsedData.segmentName,
|
|
242
|
-
add: add
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
return;
|
|
205
|
+
catch (e) {
|
|
206
|
+
log.warn(STREAMING_PARSING_MEMBERSHIPS_UPDATE, ['BoundedFetchRequest', e]);
|
|
207
|
+
break;
|
|
247
208
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
209
|
+
forOwn(clients, function (_a, matchingKey) {
|
|
210
|
+
var hash64 = _a.hash64, worker = _a.worker;
|
|
211
|
+
if (isInBitmap(bitmap_1, hash64.hex)) {
|
|
212
|
+
worker.put(parsedData, undefined, getDelay(parsedData, matchingKey));
|
|
252
213
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
214
|
+
});
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
case UpdateStrategy.KeyList: {
|
|
218
|
+
var keyList = void 0, added_1, removed_1;
|
|
219
|
+
try {
|
|
220
|
+
keyList = parseKeyList(parsedData.d, parsedData.c);
|
|
221
|
+
added_1 = new _Set(keyList.a);
|
|
222
|
+
removed_1 = new _Set(keyList.r);
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
log.warn(STREAMING_PARSING_MEMBERSHIPS_UPDATE, ['KeyList', e]);
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
if (!parsedData.n || !parsedData.n.length) {
|
|
229
|
+
log.warn(STREAMING_PARSING_MEMBERSHIPS_UPDATE, ['KeyList', 'No segment name was provided']);
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
forOwn(clients, function (_a) {
|
|
233
|
+
var hash64 = _a.hash64, worker = _a.worker;
|
|
234
|
+
var add = added_1.has(hash64.dec) ? true : removed_1.has(hash64.dec) ? false : undefined;
|
|
235
|
+
if (add !== undefined) {
|
|
236
|
+
worker.put(parsedData, {
|
|
237
|
+
added: add ? [parsedData.n[0]] : [],
|
|
238
|
+
removed: add ? [] : [parsedData.n[0]]
|
|
258
239
|
});
|
|
259
|
-
}
|
|
260
|
-
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
return;
|
|
261
243
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
244
|
+
case UpdateStrategy.SegmentRemoval:
|
|
245
|
+
if (!parsedData.n || !parsedData.n.length) {
|
|
246
|
+
log.warn(STREAMING_PARSING_MEMBERSHIPS_UPDATE, ['SegmentRemoval', 'No segment name was provided']);
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
forOwn(clients, function (_a) {
|
|
250
|
+
var worker = _a.worker;
|
|
251
|
+
worker.put(parsedData, {
|
|
252
|
+
added: [],
|
|
253
|
+
removed: parsedData.n
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
// `UpdateStrategy.UnboundedFetchRequest` and fallbacks of other cases
|
|
259
|
+
forOwn(clients, function (_a, matchingKey) {
|
|
260
|
+
var worker = _a.worker;
|
|
261
|
+
worker.put(parsedData, undefined, getDelay(parsedData, matchingKey));
|
|
267
262
|
});
|
|
268
263
|
}
|
|
264
|
+
if (userKey) {
|
|
265
|
+
pushEmitter.on(MEMBERSHIPS_MS_UPDATE, handleMySegmentsUpdate);
|
|
266
|
+
pushEmitter.on(MEMBERSHIPS_LS_UPDATE, handleMySegmentsUpdate);
|
|
267
|
+
}
|
|
269
268
|
else {
|
|
270
269
|
pushEmitter.on(SEGMENT_UPDATE, segmentsUpdateWorker.put);
|
|
271
270
|
}
|
|
@@ -300,7 +299,10 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
300
299
|
var hash = hashUserKey(userKey);
|
|
301
300
|
if (!userKeyHashes[hash]) {
|
|
302
301
|
userKeyHashes[hash] = userKey;
|
|
303
|
-
clients[userKey] = {
|
|
302
|
+
clients[userKey] = {
|
|
303
|
+
hash64: hash64(userKey),
|
|
304
|
+
worker: MySegmentsUpdateWorker(log, storage, mySegmentsSyncTask, telemetryTracker)
|
|
305
|
+
};
|
|
304
306
|
connectForNewClient = true; // we must reconnect on start, to listen the channel for the new user key
|
|
305
307
|
// Reconnects in case of a new client.
|
|
306
308
|
// Run in next event-loop cycle to save authentication calls
|
|
@@ -60,7 +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
|
|
63
|
+
export var MEMBERSHIPS = 'ms';
|
|
64
64
|
export var TREATMENT = 't';
|
|
65
65
|
export var TREATMENTS = 'ts';
|
|
66
66
|
export var TREATMENT_WITH_CONFIG = 'tc';
|
|
@@ -86,6 +86,7 @@ export var NON_REQUESTED = 1;
|
|
|
86
86
|
export var DISABLED = 0;
|
|
87
87
|
export var ENABLED = 1;
|
|
88
88
|
export var PAUSED = 2;
|
|
89
|
-
export var FLAG_SPEC_VERSION = '1.
|
|
89
|
+
export var FLAG_SPEC_VERSION = '1.2';
|
|
90
90
|
// Matcher types
|
|
91
91
|
export var IN_SEGMENT = 'IN_SEGMENT';
|
|
92
|
+
export var IN_LARGE_SEGMENT = 'IN_LARGE_SEGMENT';
|
|
@@ -183,9 +183,10 @@ export function settingsValidation(config, validationParams) {
|
|
|
183
183
|
var splitFiltersValidation = validateSplitFilters(log, sync.splitFilters, withDefaults.mode);
|
|
184
184
|
sync.splitFilters = splitFiltersValidation.validFilters;
|
|
185
185
|
sync.__splitFiltersValidation = splitFiltersValidation;
|
|
186
|
+
// ensure a valid flag spec version
|
|
186
187
|
sync.flagSpecVersion = flagSpec ? flagSpec(withDefaults) : FLAG_SPEC_VERSION;
|
|
187
188
|
// ensure a valid user consent value
|
|
188
189
|
// @ts-ignore, modify readonly prop
|
|
189
|
-
withDefaults.userConsent = consent(withDefaults);
|
|
190
|
+
withDefaults.userConsent = consent ? consent(withDefaults) : undefined;
|
|
190
191
|
return withDefaults;
|
|
191
192
|
}
|
package/package.json
CHANGED
package/src/dtos/types.ts
CHANGED
|
@@ -30,6 +30,10 @@ export interface IInSegmentMatcherData {
|
|
|
30
30
|
segmentName: string
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
export interface IInLargeSegmentMatcherData {
|
|
34
|
+
largeSegmentName: string
|
|
35
|
+
}
|
|
36
|
+
|
|
33
37
|
export interface IDependencyMatcherData {
|
|
34
38
|
split: string,
|
|
35
39
|
treatments: string[]
|
|
@@ -43,6 +47,7 @@ interface ISplitMatcherBase {
|
|
|
43
47
|
attribute: string | null
|
|
44
48
|
}
|
|
45
49
|
userDefinedSegmentMatcherData?: null | IInSegmentMatcherData
|
|
50
|
+
userDefinedLargeSegmentMatcherData?: null | IInLargeSegmentMatcherData
|
|
46
51
|
whitelistMatcherData?: null | IWhitelistMatcherData
|
|
47
52
|
unaryNumericMatcherData?: null | IUnaryNumericMatcherData
|
|
48
53
|
betweenMatcherData?: null | IBetweenMatcherData
|
|
@@ -61,6 +66,11 @@ interface IInSegmentMatcher extends ISplitMatcherBase {
|
|
|
61
66
|
userDefinedSegmentMatcherData: IInSegmentMatcherData
|
|
62
67
|
}
|
|
63
68
|
|
|
69
|
+
interface IInLargeSegmentMatcher extends ISplitMatcherBase {
|
|
70
|
+
matcherType: 'IN_LARGE_SEGMENT',
|
|
71
|
+
userDefinedLargeSegmentMatcherData: IInLargeSegmentMatcherData
|
|
72
|
+
}
|
|
73
|
+
|
|
64
74
|
interface IWhitelistMatcher extends ISplitMatcherBase {
|
|
65
75
|
matcherType: 'WHITELIST',
|
|
66
76
|
whitelistMatcherData: IWhitelistMatcherData
|
|
@@ -165,7 +175,8 @@ interface IInListSemverMatcher extends ISplitMatcherBase {
|
|
|
165
175
|
export type ISplitMatcher = IAllKeysMatcher | IInSegmentMatcher | IWhitelistMatcher | IEqualToMatcher | IGreaterThanOrEqualToMatcher |
|
|
166
176
|
ILessThanOrEqualToMatcher | IBetweenMatcher | IEqualToSetMatcher | IContainsAnyOfSetMatcher | IContainsAllOfSetMatcher | IPartOfSetMatcher |
|
|
167
177
|
IStartsWithMatcher | IEndsWithMatcher | IContainsStringMatcher | IInSplitTreatmentMatcher | IEqualToBooleanMatcher | IMatchesStringMatcher |
|
|
168
|
-
IEqualToSemverMatcher | IGreaterThanOrEqualToSemverMatcher | ILessThanOrEqualToSemverMatcher | IBetweenSemverMatcher | IInListSemverMatcher
|
|
178
|
+
IEqualToSemverMatcher | IGreaterThanOrEqualToSemverMatcher | ILessThanOrEqualToSemverMatcher | IBetweenSemverMatcher | IInListSemverMatcher |
|
|
179
|
+
IInLargeSegmentMatcher
|
|
169
180
|
|
|
170
181
|
/** Split object */
|
|
171
182
|
export interface ISplitPartition {
|
|
@@ -218,14 +229,17 @@ export interface ISegmentChangesResponse {
|
|
|
218
229
|
till: number
|
|
219
230
|
}
|
|
220
231
|
|
|
221
|
-
export interface
|
|
222
|
-
|
|
223
|
-
|
|
232
|
+
export interface IMySegmentsResponse {
|
|
233
|
+
cn?: number,
|
|
234
|
+
k?: {
|
|
235
|
+
n: string
|
|
236
|
+
}[]
|
|
224
237
|
}
|
|
225
238
|
|
|
226
|
-
/** Interface of the parsed JSON response of `/
|
|
227
|
-
export interface
|
|
228
|
-
|
|
239
|
+
/** Interface of the parsed JSON response of `/memberships/{userKey}` */
|
|
240
|
+
export interface IMembershipsResponse {
|
|
241
|
+
ms?: IMySegmentsResponse,
|
|
242
|
+
ls?: IMySegmentsResponse
|
|
229
243
|
}
|
|
230
244
|
|
|
231
245
|
/** Metadata internal type for storages */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { allMatcherContext } from './all';
|
|
2
2
|
import { segmentMatcherContext } from './segment';
|
|
3
|
+
import { largeSegmentMatcherContext } from './large_segment';
|
|
3
4
|
import { whitelistMatcherContext } from './whitelist';
|
|
4
5
|
import { equalToMatcherContext } from './eq';
|
|
5
6
|
import { greaterThanEqualMatcherContext } from './gte';
|
|
@@ -48,6 +49,7 @@ const matchers = [
|
|
|
48
49
|
lessThanEqualToSemverMatcherContext, // LESS_THAN_OR_EQUAL_TO_SEMVER: 20
|
|
49
50
|
betweenSemverMatcherContext, // BETWEEN_SEMVER: 21
|
|
50
51
|
inListSemverMatcherContext, // IN_LIST_SEMVER: 22
|
|
52
|
+
largeSegmentMatcherContext, // IN_LARGE_SEGMENT: 23
|
|
51
53
|
];
|
|
52
54
|
|
|
53
55
|
/**
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MaybeThenable } from '../../dtos/types';
|
|
2
|
+
import { ISegmentsCacheBase } from '../../storages/types';
|
|
3
|
+
import { thenable } from '../../utils/promise/thenable';
|
|
4
|
+
|
|
5
|
+
export function largeSegmentMatcherContext(largeSegmentName: string, storage: { largeSegments?: ISegmentsCacheBase }) {
|
|
6
|
+
|
|
7
|
+
return function largeSegmentMatcher(key: string): MaybeThenable<boolean> {
|
|
8
|
+
const isInLargeSegment = storage.largeSegments ? storage.largeSegments.isInSegment(largeSegmentName, key) : false;
|
|
9
|
+
|
|
10
|
+
if (thenable(isInLargeSegment)) {
|
|
11
|
+
isInLargeSegment.then(result => {
|
|
12
|
+
return result;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return isInLargeSegment;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -4,7 +4,7 @@ import { segmentTransform } from './segment';
|
|
|
4
4
|
import { whitelistTransform } from './whitelist';
|
|
5
5
|
import { numericTransform } from './unaryNumeric';
|
|
6
6
|
import { zeroSinceHH, zeroSinceSS } from '../convertions';
|
|
7
|
-
import { IBetweenMatcherData, IInSegmentMatcherData, ISplitMatcher, IUnaryNumericMatcherData } from '../../dtos/types';
|
|
7
|
+
import { IBetweenMatcherData, IInLargeSegmentMatcherData, IInSegmentMatcherData, ISplitMatcher, IUnaryNumericMatcherData } from '../../dtos/types';
|
|
8
8
|
import { IMatcherDto } from '../types';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -18,6 +18,7 @@ export function matchersTransform(matchers: ISplitMatcher[]): IMatcherDto[] {
|
|
|
18
18
|
negate,
|
|
19
19
|
keySelector,
|
|
20
20
|
userDefinedSegmentMatcherData,
|
|
21
|
+
userDefinedLargeSegmentMatcherData,
|
|
21
22
|
whitelistMatcherData, /* whitelistObject, provided by 'WHITELIST', 'IN_LIST_SEMVER', set and string matchers */
|
|
22
23
|
unaryNumericMatcherData,
|
|
23
24
|
betweenMatcherData,
|
|
@@ -35,6 +36,8 @@ export function matchersTransform(matchers: ISplitMatcher[]): IMatcherDto[] {
|
|
|
35
36
|
|
|
36
37
|
if (type === matcherTypes.IN_SEGMENT) {
|
|
37
38
|
value = segmentTransform(userDefinedSegmentMatcherData as IInSegmentMatcherData);
|
|
39
|
+
} else if (type === matcherTypes.IN_LARGE_SEGMENT) {
|
|
40
|
+
value = segmentTransform(userDefinedLargeSegmentMatcherData as IInLargeSegmentMatcherData);
|
|
38
41
|
} else if (type === matcherTypes.EQUAL_TO) {
|
|
39
42
|
value = numericTransform(unaryNumericMatcherData as IUnaryNumericMatcherData);
|
|
40
43
|
dataType = matcherDataTypes.NUMBER;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { IInSegmentMatcherData } from '../../dtos/types';
|
|
1
|
+
import { IInSegmentMatcherData, IInLargeSegmentMatcherData } from '../../dtos/types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Extract segment name as a plain string.
|
|
5
5
|
*/
|
|
6
|
-
export function segmentTransform(segment?: IInSegmentMatcherData) {
|
|
7
|
-
return segment ?
|
|
6
|
+
export function segmentTransform(segment?: IInSegmentMatcherData | IInLargeSegmentMatcherData) {
|
|
7
|
+
return segment ?
|
|
8
|
+
(segment as IInSegmentMatcherData).segmentName || (segment as IInLargeSegmentMatcherData).largeSegmentName :
|
|
9
|
+
undefined;
|
|
8
10
|
}
|
package/src/logger/constants.ts
CHANGED
|
@@ -79,7 +79,7 @@ export const WARN_SPLITS_FILTER_IGNORED = 219;
|
|
|
79
79
|
export const WARN_SPLITS_FILTER_INVALID = 220;
|
|
80
80
|
export const WARN_SPLITS_FILTER_EMPTY = 221;
|
|
81
81
|
export const WARN_SDK_KEY = 222;
|
|
82
|
-
export const
|
|
82
|
+
export const STREAMING_PARSING_MEMBERSHIPS_UPDATE = 223;
|
|
83
83
|
export const STREAMING_PARSING_SPLIT_UPDATE = 224;
|
|
84
84
|
export const WARN_INVALID_FLAGSET = 225;
|
|
85
85
|
export const WARN_LOWERCASE_FLAGSET = 226;
|
|
@@ -23,7 +23,7 @@ export const codesInfo: [number, string][] = codesWarn.concat([
|
|
|
23
23
|
[c.POLLING_START, c.LOG_PREFIX_SYNC_POLLING + 'Starting polling'],
|
|
24
24
|
[c.POLLING_STOP, c.LOG_PREFIX_SYNC_POLLING + 'Stopping polling'],
|
|
25
25
|
[c.SYNC_SPLITS_FETCH_RETRY, c.LOG_PREFIX_SYNC_SPLITS + 'Retrying download of feature flags #%s. Reason: %s'],
|
|
26
|
-
[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.'],
|
|
27
27
|
[c.SUBMITTERS_PUSH, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Pushing %s.'],
|
|
28
28
|
[c.STREAMING_REFRESH_TOKEN, c.LOG_PREFIX_SYNC_STREAMING + 'Refreshing streaming token in %s seconds, and connecting streaming in %s seconds.'],
|
|
29
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_MEMBERSHIPS_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.'],
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
|
-
import { IEventEmitter } from '../types';
|
|
2
|
+
import { IEventEmitter, ISettings } from '../types';
|
|
3
3
|
import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED, SDK_SEGMENTS_ARRIVED, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE, SDK_READY } from './constants';
|
|
4
4
|
import { IReadinessEventEmitter, IReadinessManager, ISegmentsEventEmitter, ISplitsEventEmitter } from './types';
|
|
5
5
|
|
|
@@ -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; });
|
|
@@ -33,9 +33,11 @@ function segmentsEventEmitterFactory(EventEmitter: new () => IEventEmitter): ISe
|
|
|
33
33
|
*/
|
|
34
34
|
export function readinessManagerFactory(
|
|
35
35
|
EventEmitter: new () => IEventEmitter,
|
|
36
|
-
|
|
36
|
+
settings: ISettings,
|
|
37
37
|
splits: ISplitsEventEmitter = splitsEventEmitterFactory(EventEmitter)): IReadinessManager {
|
|
38
38
|
|
|
39
|
+
const readyTimeout = settings.startup.readyTimeout;
|
|
40
|
+
|
|
39
41
|
const segments: ISegmentsEventEmitter = segmentsEventEmitterFactory(EventEmitter);
|
|
40
42
|
const gate: IReadinessEventEmitter = new EventEmitter();
|
|
41
43
|
|
|
@@ -118,9 +120,9 @@ export function readinessManagerFactory(
|
|
|
118
120
|
segments,
|
|
119
121
|
gate,
|
|
120
122
|
|
|
121
|
-
shared(
|
|
123
|
+
shared() {
|
|
122
124
|
refCount++;
|
|
123
|
-
return readinessManagerFactory(EventEmitter,
|
|
125
|
+
return readinessManagerFactory(EventEmitter, settings, splits);
|
|
124
126
|
},
|
|
125
127
|
|
|
126
128
|
// @TODO review/remove next methods when non-recoverable errors are reworked
|
|
@@ -2,9 +2,8 @@ import { objectAssign } from '../utils/lang/objectAssign';
|
|
|
2
2
|
import { promiseWrapper } from '../utils/promise/wrapper';
|
|
3
3
|
import { readinessManagerFactory } from './readinessManager';
|
|
4
4
|
import { ISdkReadinessManager } from './types';
|
|
5
|
-
import { IEventEmitter } from '../types';
|
|
5
|
+
import { IEventEmitter, ISettings } from '../types';
|
|
6
6
|
import { SDK_READY, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE } from './constants';
|
|
7
|
-
import { ILogger } from '../logger/types';
|
|
8
7
|
import { ERROR_CLIENT_LISTENER, CLIENT_READY_FROM_CACHE, CLIENT_READY, CLIENT_NO_LISTENER } from '../logger/constants';
|
|
9
8
|
|
|
10
9
|
const NEW_LISTENER_EVENT = 'newListener';
|
|
@@ -18,10 +17,11 @@ const REMOVE_LISTENER_EVENT = 'removeListener';
|
|
|
18
17
|
* @param readinessManager optional readinessManager to use. only used internally for `shared` method
|
|
19
18
|
*/
|
|
20
19
|
export function sdkReadinessManagerFactory(
|
|
21
|
-
log: ILogger,
|
|
22
20
|
EventEmitter: new () => IEventEmitter,
|
|
23
|
-
|
|
24
|
-
readinessManager = readinessManagerFactory(EventEmitter,
|
|
21
|
+
settings: ISettings,
|
|
22
|
+
readinessManager = readinessManagerFactory(EventEmitter, settings)): ISdkReadinessManager {
|
|
23
|
+
|
|
24
|
+
const log = settings.log;
|
|
25
25
|
|
|
26
26
|
/** Ready callback warning */
|
|
27
27
|
let internalReadyCbCount = 0;
|
|
@@ -72,8 +72,8 @@ export function sdkReadinessManagerFactory(
|
|
|
72
72
|
return {
|
|
73
73
|
readinessManager,
|
|
74
74
|
|
|
75
|
-
shared(
|
|
76
|
-
return sdkReadinessManagerFactory(
|
|
75
|
+
shared() {
|
|
76
|
+
return sdkReadinessManagerFactory(EventEmitter, settings, readinessManager.shared());
|
|
77
77
|
},
|
|
78
78
|
|
|
79
79
|
incInternalReadyCbCount() {
|
package/src/readiness/types.ts
CHANGED
|
@@ -61,7 +61,7 @@ export interface IReadinessManager {
|
|
|
61
61
|
destroy(): void,
|
|
62
62
|
|
|
63
63
|
/** for client-side */
|
|
64
|
-
shared(
|
|
64
|
+
shared(): IReadinessManager,
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/** SDK readiness manager */
|
|
@@ -77,5 +77,5 @@ export interface ISdkReadinessManager {
|
|
|
77
77
|
incInternalReadyCbCount(): void
|
|
78
78
|
|
|
79
79
|
/** for client-side */
|
|
80
|
-
shared(
|
|
80
|
+
shared(): ISdkReadinessManager
|
|
81
81
|
}
|
|
@@ -66,11 +66,11 @@ export function sdkClientFactory(params: ISdkFactoryContext, isSharedClient?: bo
|
|
|
66
66
|
syncManager && syncManager.stop();
|
|
67
67
|
|
|
68
68
|
return __flush().then(() => {
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
// For main client, cleanup event listeners and scheduled jobs
|
|
70
|
+
if (!isSharedClient) {
|
|
71
|
+
signalListener && signalListener.stop();
|
|
72
|
+
uniqueKeysTracker && uniqueKeysTracker.stop();
|
|
73
|
+
}
|
|
74
74
|
|
|
75
75
|
// Cleanup storage
|
|
76
76
|
return storage.destroy();
|
|
@@ -4,12 +4,15 @@ import { RETRIEVE_CLIENT_DEFAULT } from '../logger/constants';
|
|
|
4
4
|
import { ISdkFactoryContext } from '../sdkFactory/types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Factory of client method for server-side SDKs
|
|
7
|
+
* Factory of client method for server-side SDKs
|
|
8
8
|
*/
|
|
9
9
|
export function sdkClientMethodFactory(params: ISdkFactoryContext): () => SplitIO.IClient | SplitIO.IAsyncClient {
|
|
10
10
|
const log = params.settings.log;
|
|
11
11
|
const clientInstance = sdkClientFactory(params);
|
|
12
12
|
|
|
13
|
+
// Only one client in server-side without bound key
|
|
14
|
+
params.clients[''] = clientInstance;
|
|
15
|
+
|
|
13
16
|
return function client() {
|
|
14
17
|
if (arguments.length > 0) {
|
|
15
18
|
throw new Error('Shared Client not supported by the storage mechanism. Create isolated instances instead.');
|
|
@@ -8,18 +8,14 @@ import { objectAssign } from '../utils/lang/objectAssign';
|
|
|
8
8
|
import { RETRIEVE_CLIENT_DEFAULT, NEW_SHARED_CLIENT, RETRIEVE_CLIENT_EXISTING, LOG_PREFIX_CLIENT_INSTANTIATION } from '../logger/constants';
|
|
9
9
|
import { SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
|
|
10
10
|
import { ISdkFactoryContext } from '../sdkFactory/types';
|
|
11
|
-
|
|
12
|
-
function buildInstanceId(key: SplitIO.SplitKey) {
|
|
13
|
-
// @ts-ignore
|
|
14
|
-
return `${key.matchingKey ? key.matchingKey : key}-${key.bucketingKey ? key.bucketingKey : key}-`;
|
|
15
|
-
}
|
|
11
|
+
import { buildInstanceId } from './identity';
|
|
16
12
|
|
|
17
13
|
/**
|
|
18
14
|
* Factory of client method for the client-side API variant where TT is ignored.
|
|
19
15
|
* Therefore, clients don't have a bound TT for the track method.
|
|
20
16
|
*/
|
|
21
17
|
export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitIO.SplitKey) => SplitIO.ICsClient {
|
|
22
|
-
const { storage, syncManager, sdkReadinessManager, settings: { core: { key },
|
|
18
|
+
const { clients, storage, syncManager, sdkReadinessManager, settings: { core: { key }, log } } = params;
|
|
23
19
|
|
|
24
20
|
const mainClientInstance = clientCSDecorator(
|
|
25
21
|
log,
|
|
@@ -31,8 +27,7 @@ export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: Spl
|
|
|
31
27
|
const defaultInstanceId = buildInstanceId(parsedDefaultKey);
|
|
32
28
|
|
|
33
29
|
// Cache instances created per factory.
|
|
34
|
-
|
|
35
|
-
clientInstances[defaultInstanceId] = mainClientInstance;
|
|
30
|
+
clients[defaultInstanceId] = mainClientInstance;
|
|
36
31
|
|
|
37
32
|
return function client(key?: SplitIO.SplitKey) {
|
|
38
33
|
if (key === undefined) {
|
|
@@ -48,10 +43,10 @@ export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: Spl
|
|
|
48
43
|
|
|
49
44
|
const instanceId = buildInstanceId(validKey);
|
|
50
45
|
|
|
51
|
-
if (!
|
|
46
|
+
if (!clients[instanceId]) {
|
|
52
47
|
const matchingKey = getMatching(validKey);
|
|
53
48
|
|
|
54
|
-
const sharedSdkReadiness = sdkReadinessManager.shared(
|
|
49
|
+
const sharedSdkReadiness = sdkReadinessManager.shared();
|
|
55
50
|
const sharedStorage = storage.shared && storage.shared(matchingKey, (err) => {
|
|
56
51
|
if (err) {
|
|
57
52
|
sharedSdkReadiness.readinessManager.timeout();
|
|
@@ -70,13 +65,12 @@ export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: Spl
|
|
|
70
65
|
|
|
71
66
|
// As shared clients reuse all the storage information, we don't need to check here if we
|
|
72
67
|
// will use offline or online mode. We should stick with the original decision.
|
|
73
|
-
|
|
68
|
+
clients[instanceId] = clientCSDecorator(
|
|
74
69
|
log,
|
|
75
70
|
sdkClientFactory(objectAssign({}, params, {
|
|
76
71
|
sdkReadinessManager: sharedSdkReadiness,
|
|
77
72
|
storage: sharedStorage || storage,
|
|
78
73
|
syncManager: sharedSyncManager,
|
|
79
|
-
signalListener: undefined, // only the main client "destroy" method stops the signal listener
|
|
80
74
|
}), true) as SplitIO.IClient,
|
|
81
75
|
validKey
|
|
82
76
|
);
|
|
@@ -88,6 +82,6 @@ export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: Spl
|
|
|
88
82
|
log.debug(RETRIEVE_CLIENT_EXISTING);
|
|
89
83
|
}
|
|
90
84
|
|
|
91
|
-
return
|
|
85
|
+
return clients[instanceId] as SplitIO.ICsClient;
|
|
92
86
|
};
|
|
93
87
|
}
|