@splitsoftware/splitio-commons 3.1.1-rc.0 → 3.1.1-rc.10
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 +10 -1
- package/cjs/evaluator/condition/index.js +1 -1
- package/cjs/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +8 -5
- package/cjs/evaluator/index.js +69 -81
- package/cjs/listeners/browser.js +1 -2
- package/cjs/listeners/node.js +4 -4
- package/cjs/logger/constants.js +20 -15
- package/cjs/logger/messages/debug.js +6 -5
- package/cjs/logger/messages/error.js +3 -3
- package/cjs/logger/messages/info.js +4 -3
- package/cjs/logger/messages/warn.js +7 -6
- package/cjs/presets/serverSide.js +2 -2
- package/cjs/readiness/constants.js +4 -5
- package/cjs/readiness/readinessManager.js +23 -23
- package/cjs/readiness/sdkReadinessManager.js +17 -1
- package/cjs/sdkClient/client.js +34 -9
- package/cjs/sdkClient/clientInputValidation.js +17 -6
- package/cjs/sdkClient/sdkClient.js +60 -3
- package/cjs/sdkFactory/index.js +15 -11
- package/cjs/sdkManager/index.js +5 -5
- package/cjs/services/decorateHeaders.js +1 -2
- package/cjs/services/splitApi.js +1 -14
- package/cjs/services/splitHttpClient.js +5 -3
- package/cjs/storages/AbstractSplitsCacheAsync.js +51 -0
- package/cjs/storages/AbstractSplitsCacheSync.js +76 -0
- package/cjs/storages/KeyBuilder.js +6 -6
- package/cjs/storages/KeyBuilderCS.js +5 -5
- package/cjs/storages/KeyBuilderSS.js +2 -2
- package/cjs/storages/getRolloutPlan.js +3 -3
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +2 -1
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +10 -10
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +194 -0
- package/cjs/storages/inLocalStorage/index.js +6 -6
- package/cjs/storages/inLocalStorage/validateCache.js +3 -3
- package/cjs/storages/inMemory/InMemoryStorage.js +4 -4
- package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +5 -5
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +121 -0
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +5 -5
- package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/RedisAdapter.js +8 -5
- package/cjs/storages/inRedis/{DefinitionsCacheInRedis.js → SplitsCacheInRedis.js} +77 -77
- package/cjs/storages/inRedis/index.js +2 -2
- package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
- package/cjs/storages/pluggable/SplitsCachePluggable.js +212 -0
- package/cjs/storages/pluggable/index.js +2 -2
- package/cjs/storages/setRolloutPlan.js +4 -4
- package/cjs/storages/utils.js +0 -1
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +5 -5
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +15 -24
- package/cjs/sync/polling/pollingManagerCS.js +20 -20
- package/cjs/sync/polling/pollingManagerSS.js +15 -15
- package/cjs/sync/polling/syncTasks/segmentsSyncTask.js +3 -2
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +13 -0
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +3 -3
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +6 -6
- package/cjs/sync/polling/updaters/{definitionChangesUpdater.js → splitChangesUpdater.js} +68 -65
- package/cjs/sync/streaming/AuthClient/index.js +1 -1
- package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +1 -1
- package/cjs/sync/streaming/UpdateWorkers/{DefinitionsUpdateWorker.js → SplitsUpdateWorker.js} +19 -16
- package/cjs/sync/streaming/constants.js +3 -3
- package/cjs/sync/streaming/parseUtils.js +11 -11
- package/cjs/sync/streaming/pushManager.js +16 -16
- package/cjs/sync/submitters/eventsSubmitter.js +1 -1
- package/cjs/sync/submitters/impressionCountsSubmitter.js +1 -1
- package/cjs/sync/submitters/impressionsSubmitter.js +4 -5
- package/cjs/sync/submitters/telemetrySubmitter.js +4 -3
- package/cjs/sync/submitters/uniqueKeysSubmitter.js +1 -1
- package/cjs/sync/syncManagerOnline.js +7 -12
- package/cjs/utils/Backoff.js +0 -20
- package/cjs/utils/inputValidation/index.js +7 -7
- package/cjs/utils/inputValidation/isOperational.js +4 -4
- package/cjs/utils/inputValidation/{definition.js → split.js} +10 -10
- package/cjs/utils/inputValidation/{definitionExistence.js → splitExistence.js} +6 -6
- package/cjs/utils/inputValidation/splits.js +25 -0
- package/cjs/utils/labels/index.js +3 -3
- package/cjs/utils/settingsValidation/index.js +0 -2
- package/cjs/utils/settingsValidation/splitFilters.js +3 -3
- package/cjs/utils/settingsValidation/url.js +2 -6
- package/esm/evaluator/condition/index.js +1 -1
- package/esm/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +8 -5
- package/esm/evaluator/index.js +69 -80
- package/esm/listeners/browser.js +1 -2
- package/esm/listeners/node.js +4 -4
- package/esm/logger/constants.js +17 -12
- package/esm/logger/messages/debug.js +6 -5
- package/esm/logger/messages/error.js +3 -3
- package/esm/logger/messages/info.js +4 -3
- package/esm/logger/messages/warn.js +7 -6
- package/esm/presets/serverSide.js +2 -2
- package/esm/readiness/constants.js +3 -4
- package/esm/readiness/readinessManager.js +24 -24
- package/esm/readiness/sdkReadinessManager.js +18 -2
- package/esm/sdkClient/client.js +35 -9
- package/esm/sdkClient/clientInputValidation.js +19 -8
- package/esm/sdkClient/sdkClient.js +60 -3
- package/esm/sdkFactory/index.js +16 -12
- package/esm/sdkManager/index.js +6 -6
- package/esm/services/decorateHeaders.js +1 -2
- package/esm/services/splitApi.js +1 -14
- package/esm/services/splitHttpClient.js +5 -3
- package/esm/storages/AbstractSplitsCacheAsync.js +48 -0
- package/esm/storages/AbstractSplitsCacheSync.js +71 -0
- package/esm/storages/KeyBuilder.js +6 -6
- package/esm/storages/KeyBuilderCS.js +5 -5
- package/esm/storages/KeyBuilderSS.js +2 -2
- package/esm/storages/getRolloutPlan.js +3 -3
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +2 -1
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +7 -7
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +191 -0
- package/esm/storages/inLocalStorage/index.js +6 -6
- package/esm/storages/inLocalStorage/validateCache.js +3 -3
- package/esm/storages/inMemory/InMemoryStorage.js +4 -4
- package/esm/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +2 -2
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/SplitsCacheInMemory.js +118 -0
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +5 -5
- package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
- package/esm/storages/inRedis/RedisAdapter.js +8 -5
- package/esm/storages/inRedis/{DefinitionsCacheInRedis.js → SplitsCacheInRedis.js} +76 -76
- package/esm/storages/inRedis/index.js +2 -2
- package/esm/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
- package/esm/storages/pluggable/SplitsCachePluggable.js +209 -0
- package/esm/storages/pluggable/index.js +2 -2
- package/esm/storages/setRolloutPlan.js +4 -4
- package/esm/storages/utils.js +0 -1
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +6 -6
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +16 -25
- package/esm/sync/polling/pollingManagerCS.js +17 -17
- package/esm/sync/polling/pollingManagerSS.js +15 -15
- package/esm/sync/polling/syncTasks/segmentsSyncTask.js +3 -2
- package/esm/sync/polling/syncTasks/splitsSyncTask.js +9 -0
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +3 -3
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +7 -7
- package/esm/sync/polling/updaters/{definitionChangesUpdater.js → splitChangesUpdater.js} +68 -65
- package/esm/sync/streaming/AuthClient/index.js +1 -1
- package/esm/sync/streaming/SSEHandler/NotificationKeeper.js +2 -2
- package/esm/sync/streaming/SSEHandler/index.js +2 -2
- package/esm/sync/streaming/UpdateWorkers/{DefinitionsUpdateWorker.js → SplitsUpdateWorker.js} +18 -15
- package/esm/sync/streaming/constants.js +2 -2
- package/esm/sync/streaming/parseUtils.js +9 -9
- package/esm/sync/streaming/pushManager.js +18 -18
- package/esm/sync/submitters/eventsSubmitter.js +1 -1
- package/esm/sync/submitters/impressionCountsSubmitter.js +1 -1
- package/esm/sync/submitters/impressionsSubmitter.js +4 -5
- package/esm/sync/submitters/telemetrySubmitter.js +4 -3
- package/esm/sync/submitters/uniqueKeysSubmitter.js +1 -1
- package/esm/sync/syncManagerOnline.js +6 -11
- package/esm/utils/Backoff.js +0 -20
- package/esm/utils/inputValidation/index.js +3 -3
- package/esm/utils/inputValidation/isOperational.js +4 -4
- package/esm/utils/inputValidation/{definition.js → split.js} +8 -8
- package/esm/utils/inputValidation/splitExistence.js +15 -0
- package/esm/utils/inputValidation/splits.js +21 -0
- package/esm/utils/labels/index.js +2 -2
- package/esm/utils/settingsValidation/index.js +0 -2
- package/esm/utils/settingsValidation/splitFilters.js +3 -3
- package/esm/utils/settingsValidation/url.js +2 -6
- package/package.json +6 -7
- package/src/dtos/types.ts +1 -1
- package/src/evaluator/Engine.ts +3 -3
- package/src/evaluator/condition/index.ts +2 -2
- package/src/evaluator/index.ts +27 -35
- package/src/evaluator/types.ts +2 -6
- package/src/presets/serverSide.ts +3 -3
- package/src/sdkClient/client.ts +22 -24
- package/src/sdkClient/sdkLifecycle.ts +3 -0
- package/src/services/authProvider.ts +41 -19
- package/src/services/secureSplitHttpClient.ts +10 -18
- package/src/services/serviceApi.ts +27 -24
- package/src/services/splitApi.ts +10 -9
- package/src/services/types.ts +5 -4
- package/src/storages/inRedis/RedisAdapter.ts +8 -5
- package/src/sync/polling/pollingManagerCS.ts +80 -78
- package/src/sync/polling/pollingManagerSS.ts +49 -45
- package/src/sync/polling/updaters/definitionChangesUpdater.ts +3 -3
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +1 -1
- package/src/sync/streaming/AuthClient/index.ts +14 -15
- package/src/sync/streaming/AuthClient/types.ts +9 -13
- package/src/sync/streaming/SSEClient/index.ts +2 -2
- package/src/sync/streaming/SSEClient/types.ts +2 -2
- package/src/sync/streaming/SSEHandler/index.ts +2 -1
- package/src/sync/streaming/SSEHandler/types.ts +2 -2
- package/src/sync/streaming/constants.ts +1 -0
- package/src/sync/streaming/pushManager.ts +32 -42
- package/src/sync/streaming/types.ts +3 -2
- package/src/sync/submitters/impressionsSubmitter.ts +3 -3
- package/src/sync/submitters/types.ts +2 -2
- package/src/sync/syncManagerOnline.ts +2 -8
- package/src/utils/Backoff.ts +16 -4
- package/types/splitio.d.ts +5 -4
- package/cjs/platform/browser.js +0 -15
- package/cjs/platform/getEventSource/browser.js +0 -8
- package/cjs/platform/getEventSource/eventsource.js +0 -480
- package/cjs/platform/getEventSource/node.js +0 -26
- package/cjs/platform/getFetch/browser.js +0 -9
- package/cjs/platform/getFetch/node.js +0 -27
- package/cjs/platform/getOptions/node.js +0 -25
- package/cjs/platform/node.js +0 -17
- package/cjs/sdkClient/sdkLifecycle.js +0 -72
- package/cjs/sdkClient/trackMethod.js +0 -56
- package/cjs/services/authProvider.js +0 -67
- package/cjs/services/secureSplitHttpClient.js +0 -39
- package/cjs/services/serviceApi.js +0 -145
- package/cjs/storages/AbstractDefinitionsCacheAsync.js +0 -51
- package/cjs/storages/AbstractDefinitionsCacheSync.js +0 -76
- package/cjs/storages/inLocalStorage/DefinitionsCacheInLocal.js +0 -194
- package/cjs/storages/inMemory/DefinitionsCacheInMemory.js +0 -121
- package/cjs/storages/pluggable/DefinitionsCachePluggable.js +0 -212
- package/cjs/sync/polling/syncTasks/definitionsSyncTask.js +0 -13
- package/cjs/utils/EventEmitter.js +0 -391
- package/cjs/utils/filter/bloomFilter.js +0 -37
- package/cjs/utils/inputValidation/definitions.js +0 -25
- package/cjs/utils/inputValidation/target.js +0 -22
- package/esm/platform/browser.js +0 -12
- package/esm/platform/getEventSource/browser.js +0 -4
- package/esm/platform/getEventSource/eventsource.js +0 -480
- package/esm/platform/getEventSource/node.js +0 -20
- package/esm/platform/getFetch/browser.js +0 -5
- package/esm/platform/getFetch/node.js +0 -22
- package/esm/platform/getOptions/node.js +0 -20
- package/esm/platform/node.js +0 -14
- package/esm/sdkClient/sdkLifecycle.js +0 -68
- package/esm/sdkClient/trackMethod.js +0 -52
- package/esm/services/authProvider.js +0 -63
- package/esm/services/secureSplitHttpClient.js +0 -35
- package/esm/services/serviceApi.js +0 -141
- package/esm/storages/AbstractDefinitionsCacheAsync.js +0 -48
- package/esm/storages/AbstractDefinitionsCacheSync.js +0 -71
- package/esm/storages/inLocalStorage/DefinitionsCacheInLocal.js +0 -191
- package/esm/storages/inMemory/DefinitionsCacheInMemory.js +0 -118
- package/esm/storages/pluggable/DefinitionsCachePluggable.js +0 -209
- package/esm/sync/polling/syncTasks/definitionsSyncTask.js +0 -9
- package/esm/utils/EventEmitter.js +0 -387
- package/esm/utils/filter/bloomFilter.js +0 -33
- package/esm/utils/inputValidation/definitionExistence.js +0 -15
- package/esm/utils/inputValidation/definitions.js +0 -21
- package/esm/utils/inputValidation/target.js +0 -18
package/esm/sync/streaming/UpdateWorkers/{DefinitionsUpdateWorker.js → SplitsUpdateWorker.js}
RENAMED
|
@@ -1,37 +1,40 @@
|
|
|
1
1
|
import { STREAMING_PARSING_SPLIT_UPDATE } from '../../../logger/constants';
|
|
2
|
-
import {
|
|
2
|
+
import { SDK_SPLITS_ARRIVED } from '../../../readiness/constants';
|
|
3
3
|
import { Backoff } from '../../../utils/Backoff';
|
|
4
4
|
import { SPLITS } from '../../../utils/constants';
|
|
5
5
|
import { RB_SEGMENT_UPDATE } from '../constants';
|
|
6
6
|
import { parseFFUpdatePayload } from '../parseUtils';
|
|
7
7
|
import { FETCH_BACKOFF_BASE, FETCH_BACKOFF_MAX_WAIT, FETCH_BACKOFF_MAX_RETRIES } from './constants';
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* SplitsUpdateWorker factory
|
|
10
10
|
*/
|
|
11
|
-
export function
|
|
12
|
-
var ff =
|
|
13
|
-
var rbs =
|
|
14
|
-
function
|
|
11
|
+
export function SplitsUpdateWorker(log, storage, splitsSyncTask, splitsEventEmitter, telemetryTracker, segmentsSyncTask) {
|
|
12
|
+
var ff = SplitsUpdateWorker(storage.splits);
|
|
13
|
+
var rbs = SplitsUpdateWorker(storage.rbSegments);
|
|
14
|
+
function SplitsUpdateWorker(cache) {
|
|
15
15
|
var maxChangeNumber = -1;
|
|
16
16
|
var handleNewEvent = false;
|
|
17
17
|
var isHandlingEvent;
|
|
18
18
|
var cdnBypass;
|
|
19
19
|
var instantUpdate;
|
|
20
|
-
var backoff = new Backoff(
|
|
21
|
-
function
|
|
20
|
+
var backoff = new Backoff(__handleSplitUpdateCall, FETCH_BACKOFF_BASE, FETCH_BACKOFF_MAX_WAIT);
|
|
21
|
+
function __handleSplitUpdateCall() {
|
|
22
22
|
isHandlingEvent = true;
|
|
23
23
|
if (maxChangeNumber > cache.getChangeNumber()) {
|
|
24
24
|
handleNewEvent = false;
|
|
25
25
|
// fetch splits revalidating data if cached
|
|
26
|
-
|
|
26
|
+
splitsSyncTask.execute(true, cdnBypass ? maxChangeNumber : undefined, instantUpdate).then(function () {
|
|
27
27
|
if (!isHandlingEvent)
|
|
28
28
|
return; // halt if `stop` has been called
|
|
29
29
|
if (handleNewEvent) {
|
|
30
|
-
|
|
30
|
+
__handleSplitUpdateCall();
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
33
|
if (instantUpdate)
|
|
34
34
|
telemetryTracker.trackUpdatesFromSSE(SPLITS);
|
|
35
|
+
// fetch new registered segments for server-side API. Not retrying on error
|
|
36
|
+
if (segmentsSyncTask)
|
|
37
|
+
segmentsSyncTask.execute(true);
|
|
35
38
|
var attempts = backoff.attempts + 1;
|
|
36
39
|
if (ff.isSync() && rbs.isSync()) {
|
|
37
40
|
log.debug("Refresh completed".concat(cdnBypass ? ' bypassing the CDN' : '', " in ").concat(attempts, " attempts."));
|
|
@@ -49,7 +52,7 @@ export function DefinitionsUpdateWorker(log, storage, definitionsSyncTask, defin
|
|
|
49
52
|
else {
|
|
50
53
|
backoff.reset();
|
|
51
54
|
cdnBypass = true;
|
|
52
|
-
|
|
55
|
+
__handleSplitUpdateCall();
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
});
|
|
@@ -77,7 +80,7 @@ export function DefinitionsUpdateWorker(log, storage, definitionsSyncTask, defin
|
|
|
77
80
|
instantUpdate = { payload: payload, changeNumber: changeNumber, type: type };
|
|
78
81
|
}
|
|
79
82
|
if (backoff.timeoutID || !isHandlingEvent)
|
|
80
|
-
|
|
83
|
+
__handleSplitUpdateCall();
|
|
81
84
|
backoff.reset();
|
|
82
85
|
},
|
|
83
86
|
stop: function () {
|
|
@@ -112,11 +115,11 @@ export function DefinitionsUpdateWorker(log, storage, definitionsSyncTask, defin
|
|
|
112
115
|
* @param splitName - name of split to kill
|
|
113
116
|
* @param defaultTreatment - default treatment value
|
|
114
117
|
*/
|
|
115
|
-
|
|
118
|
+
killSplit: function (_a) {
|
|
116
119
|
var changeNumber = _a.changeNumber, splitName = _a.splitName, defaultTreatment = _a.defaultTreatment;
|
|
117
|
-
if (storage.
|
|
120
|
+
if (storage.splits.killLocally(splitName, defaultTreatment, changeNumber)) {
|
|
118
121
|
// trigger an SDK_UPDATE if Split was killed locally
|
|
119
|
-
|
|
122
|
+
splitsEventEmitter.emit(SDK_SPLITS_ARRIVED, true);
|
|
120
123
|
}
|
|
121
124
|
// queues the SplitChanges fetch (only if changeNumber is newer)
|
|
122
125
|
ff.put({ changeNumber: changeNumber });
|
|
@@ -5,7 +5,7 @@ export var SECONDS_BEFORE_EXPIRATION = 600;
|
|
|
5
5
|
* emitted on SSE and Authenticate non-recoverable errors, STREAMING_DISABLED control notification and authentication with pushEnabled false
|
|
6
6
|
* triggers `handleNonRetryableError` call
|
|
7
7
|
*/
|
|
8
|
-
export var
|
|
8
|
+
export var PUSH_NONRETRYABLE_ERROR = 'PUSH_NONRETRYABLE_ERROR';
|
|
9
9
|
/**
|
|
10
10
|
* emitted on SSE and Authenticate recoverable errors
|
|
11
11
|
* triggers `handleRetryableError` call
|
|
@@ -17,7 +17,7 @@ export var PUSH_RETRYABLE_ERROR = 'PUSH_RETRYABLE_ERROR';
|
|
|
17
17
|
*/
|
|
18
18
|
export var PUSH_SUBSYSTEM_UP = 'PUSH_SUBSYSTEM_UP';
|
|
19
19
|
/**
|
|
20
|
-
* emitted on STREAMING_PAUSED control notification, OCCUPANCY equal to 0,
|
|
20
|
+
* emitted on STREAMING_PAUSED control notification, OCCUPANCY equal to 0, PUSH_NONRETRYABLE_ERROR and PUSH_RETRYABLE_ERROR events.
|
|
21
21
|
* triggers `startPolling` and `stopWorkers` calls
|
|
22
22
|
*/
|
|
23
23
|
export var PUSH_SUBSYSTEM_DOWN = 'PUSH_SUBSYSTEM_DOWN';
|
|
@@ -30,22 +30,22 @@ function decompress(data, compression) {
|
|
|
30
30
|
throw new Error("Invalid compression algorithm #".concat(compression));
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* Decode, decompress and parse the provided 'data' into
|
|
33
|
+
* Decode, decompress and parse the provided 'data' into a KeyList object
|
|
34
34
|
*
|
|
35
35
|
* @param data - base64 encoded string
|
|
36
36
|
* @param compression - 1 GZIP, 2 ZLIB
|
|
37
37
|
* @param avoidPrecisionLoss - true as default, set it as false if dont need to avoid precission loss
|
|
38
|
-
* @returns
|
|
38
|
+
* @returns keyList
|
|
39
39
|
* @throws if data string cannot be decoded, decompressed or parsed
|
|
40
40
|
*/
|
|
41
|
-
export function
|
|
41
|
+
export function parseKeyList(data, compression, avoidPrecisionLoss) {
|
|
42
42
|
if (avoidPrecisionLoss === void 0) { avoidPrecisionLoss = true; }
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
// replace numbers to strings, to avoid losing precision
|
|
43
|
+
var binKeyList = decompress(data, compression);
|
|
44
|
+
var strKeyList = Uint8ArrayToString(binKeyList);
|
|
45
|
+
// replace numbers to strings, to avoid losing precision
|
|
46
46
|
if (avoidPrecisionLoss)
|
|
47
|
-
|
|
48
|
-
return JSON.parse(
|
|
47
|
+
strKeyList = strKeyList.replace(/\d+/g, '"$&"');
|
|
48
|
+
return JSON.parse(strKeyList);
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
51
|
* Decode, decompress and parse the provided 'data' into a Bitmap object
|
|
@@ -77,7 +77,7 @@ export function isInBitmap(bitmap, hash64hex) {
|
|
|
77
77
|
*/
|
|
78
78
|
export function parseFFUpdatePayload(compression, data) {
|
|
79
79
|
return compression > 0 ?
|
|
80
|
-
|
|
80
|
+
parseKeyList(data, compression, false) :
|
|
81
81
|
JSON.parse(decodeFromBase64(data));
|
|
82
82
|
}
|
|
83
83
|
var DEFAULT_MAX_INTERVAL = 60000;
|
|
@@ -3,15 +3,15 @@ import { Backoff } from '../../utils/Backoff';
|
|
|
3
3
|
import { SSEHandlerFactory } from './SSEHandler';
|
|
4
4
|
import { MySegmentsUpdateWorker } from './UpdateWorkers/MySegmentsUpdateWorker';
|
|
5
5
|
import { SegmentsUpdateWorker } from './UpdateWorkers/SegmentsUpdateWorker';
|
|
6
|
-
import {
|
|
6
|
+
import { SplitsUpdateWorker } from './UpdateWorkers/SplitsUpdateWorker';
|
|
7
7
|
import { authenticateFactory, hashUserKey } from './AuthClient';
|
|
8
8
|
import { forOwn } from '../../utils/lang';
|
|
9
9
|
import { SSEClient } from './SSEClient';
|
|
10
10
|
import { checkIfServerSide, getMatching } from '../../utils/key';
|
|
11
|
-
import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE,
|
|
11
|
+
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';
|
|
12
12
|
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE } from '../../logger/constants';
|
|
13
13
|
import { UpdateStrategy } from './SSEHandler/types';
|
|
14
|
-
import { getDelay, isInBitmap, parseBitmap,
|
|
14
|
+
import { getDelay, isInBitmap, parseBitmap, parseKeyList } from './parseUtils';
|
|
15
15
|
import { hash64 } from '../../utils/murmur3/murmur3_64';
|
|
16
16
|
import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
|
|
17
17
|
/**
|
|
@@ -20,7 +20,7 @@ import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
|
|
|
20
20
|
* - for client-side, with support for multiple clients, if key is provided in settings
|
|
21
21
|
*/
|
|
22
22
|
export function pushManagerFactory(params, pollingManager) {
|
|
23
|
-
var settings = params.settings, storage = params.storage,
|
|
23
|
+
var settings = params.settings, storage = params.storage, splitApi = params.splitApi, readiness = params.readiness, platform = params.platform, telemetryTracker = params.telemetryTracker;
|
|
24
24
|
// `userKey` is the matching key of main client in client-side SDK.
|
|
25
25
|
// It can be used to check if running on client-side or server-side SDK.
|
|
26
26
|
var userKey = checkIfServerSide(settings) ? undefined : getMatching(settings.core.key);
|
|
@@ -34,7 +34,7 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
34
34
|
log.warn(STREAMING_FALLBACK, [e]);
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
var authenticate = authenticateFactory(
|
|
37
|
+
var authenticate = authenticateFactory(splitApi.fetchAuth);
|
|
38
38
|
// init feedback loop
|
|
39
39
|
var pushEmitter = new platform.EventEmitter();
|
|
40
40
|
var sseHandler = SSEHandlerFactory(log, pushEmitter, telemetryTracker);
|
|
@@ -42,8 +42,8 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
42
42
|
// init workers
|
|
43
43
|
// MySegmentsUpdateWorker (client-side) are initiated in `add` method
|
|
44
44
|
var segmentsUpdateWorker = userKey ? undefined : SegmentsUpdateWorker(log, pollingManager.segmentsSyncTask, storage.segments);
|
|
45
|
-
// For server-side we pass the segmentsSyncTask, used by
|
|
46
|
-
var
|
|
45
|
+
// For server-side we pass the segmentsSyncTask, used by SplitsUpdateWorker to fetch new segments
|
|
46
|
+
var splitsUpdateWorker = SplitsUpdateWorker(log, storage, pollingManager.splitsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask);
|
|
47
47
|
// [Only for client-side] map of hashes to user keys, to dispatch membership update events to the corresponding MySegmentsUpdateWorker
|
|
48
48
|
var userKeyHashes = {};
|
|
49
49
|
// [Only for client-side] map of user keys to their corresponding hash64 and MySegmentsUpdateWorkers.
|
|
@@ -51,10 +51,10 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
51
51
|
var clients = {};
|
|
52
52
|
// [Only for client-side] variable to flag that a new client was added. It is needed to reconnect streaming.
|
|
53
53
|
var connectForNewClient = false;
|
|
54
|
-
// flag that indicates if `stop/disconnectPush` was called, either by the SyncManager, when the client is destroyed, or due to a
|
|
54
|
+
// flag that indicates if `stop/disconnectPush` was called, either by the SyncManager, when the client is destroyed, or due to a PUSH_NONRETRYABLE_ERROR error.
|
|
55
55
|
// It is used to halt the `connectPush` process if it was in progress.
|
|
56
56
|
var disconnected;
|
|
57
|
-
// flag that indicates a
|
|
57
|
+
// flag that indicates a PUSH_NONRETRYABLE_ERROR, condition with which starting pushManager again is ignored.
|
|
58
58
|
// true if STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE or Auth errors.
|
|
59
59
|
var disabled; // `disabled` implies `disconnected === true`
|
|
60
60
|
/** PushManager functions related to initialization */
|
|
@@ -93,11 +93,11 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
93
93
|
authenticate(userKeys).then(function (authData) {
|
|
94
94
|
if (disconnected)
|
|
95
95
|
return;
|
|
96
|
-
// 'pushEnabled: false' is handled as a
|
|
96
|
+
// 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
|
|
97
97
|
// close the sseClient in case the org has been bloqued while the instance was connected to streaming
|
|
98
98
|
if (!authData.pushEnabled) {
|
|
99
99
|
log.info(STREAMING_DISABLED);
|
|
100
|
-
pushEmitter.emit(
|
|
100
|
+
pushEmitter.emit(PUSH_NONRETRYABLE_ERROR);
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
// [Only for client-side] don't open SSE connection if a new shared client was added, since it means that a new authentication is taking place
|
|
@@ -112,7 +112,7 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
112
112
|
// Handle 4XX HTTP errors: 401 (invalid SDK Key) or 400 (using incorrect SDK Key, i.e., client-side SDK Key on server-side)
|
|
113
113
|
if (error.statusCode >= 400 && error.statusCode < 500) {
|
|
114
114
|
telemetryTracker.streamingEvent(AUTH_REJECTION);
|
|
115
|
-
pushEmitter.emit(
|
|
115
|
+
pushEmitter.emit(PUSH_NONRETRYABLE_ERROR);
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
118
|
// Handle other HTTP and network errors as recoverable errors
|
|
@@ -136,7 +136,7 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
136
136
|
}
|
|
137
137
|
// cancel scheduled fetch retries of Splits, Segments, and MySegments Update Workers
|
|
138
138
|
function stopWorkers() {
|
|
139
|
-
|
|
139
|
+
splitsUpdateWorker.stop();
|
|
140
140
|
if (userKey)
|
|
141
141
|
forOwn(clients, function (_a) {
|
|
142
142
|
var worker = _a.worker;
|
|
@@ -152,7 +152,7 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
152
152
|
connectPushRetryBackoff.reset();
|
|
153
153
|
});
|
|
154
154
|
/** Fallback to polling without retry due to: STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE and Authentication errors */
|
|
155
|
-
pushEmitter.on(
|
|
155
|
+
pushEmitter.on(PUSH_NONRETRYABLE_ERROR, function handleNonRetryableError() {
|
|
156
156
|
disabled = true;
|
|
157
157
|
// Note: `stopWorkers` is been called twice, but it is not harmful
|
|
158
158
|
disconnectPush();
|
|
@@ -178,9 +178,9 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
178
178
|
connectPush();
|
|
179
179
|
});
|
|
180
180
|
/** Functions related to synchronization (Queues and Workers in the spec) */
|
|
181
|
-
pushEmitter.on(SPLIT_KILL,
|
|
182
|
-
pushEmitter.on(SPLIT_UPDATE,
|
|
183
|
-
pushEmitter.on(RB_SEGMENT_UPDATE,
|
|
181
|
+
pushEmitter.on(SPLIT_KILL, splitsUpdateWorker.killSplit);
|
|
182
|
+
pushEmitter.on(SPLIT_UPDATE, splitsUpdateWorker.put);
|
|
183
|
+
pushEmitter.on(RB_SEGMENT_UPDATE, splitsUpdateWorker.put);
|
|
184
184
|
function handleMySegmentsUpdate(parsedData) {
|
|
185
185
|
switch (parsedData.u) {
|
|
186
186
|
case UpdateStrategy.BoundedFetchRequest: {
|
|
@@ -203,7 +203,7 @@ export function pushManagerFactory(params, pollingManager) {
|
|
|
203
203
|
case UpdateStrategy.KeyList: {
|
|
204
204
|
var keyList = void 0, added_1, removed_1;
|
|
205
205
|
try {
|
|
206
|
-
keyList =
|
|
206
|
+
keyList = parseKeyList(parsedData.d, parsedData.c);
|
|
207
207
|
added_1 = new Set(keyList.a);
|
|
208
208
|
removed_1 = new Set(keyList.r);
|
|
209
209
|
}
|
|
@@ -4,7 +4,7 @@ import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
|
|
|
4
4
|
* Submitter that periodically posts tracked events
|
|
5
5
|
*/
|
|
6
6
|
export function eventsSubmitterFactory(params) {
|
|
7
|
-
var _a = params.settings, log = _a.log, eventsPushRate = _a.scheduler.eventsPushRate, eventsFirstPushWindow = _a.startup.eventsFirstPushWindow, postEventsBulk = params.
|
|
7
|
+
var _a = params.settings, log = _a.log, eventsPushRate = _a.scheduler.eventsPushRate, eventsFirstPushWindow = _a.startup.eventsFirstPushWindow, postEventsBulk = params.splitApi.postEventsBulk, events = params.storage.events;
|
|
8
8
|
// don't retry events.
|
|
9
9
|
var submitter = submitterFactory(log, postEventsBulk, events, eventsPushRate);
|
|
10
10
|
// Set a timer for the first push window of events.
|
|
@@ -25,7 +25,7 @@ var IMPRESSIONS_COUNT_RATE = 1800000; // 30 minutes
|
|
|
25
25
|
* Submitter that periodically posts impression counts
|
|
26
26
|
*/
|
|
27
27
|
export function impressionCountsSubmitterFactory(params) {
|
|
28
|
-
var log = params.settings.log, postTestImpressionsCount = params.
|
|
28
|
+
var log = params.settings.log, postTestImpressionsCount = params.splitApi.postTestImpressionsCount, impressionCounts = params.storage.impressionCounts;
|
|
29
29
|
// retry impressions counts only once.
|
|
30
30
|
return submitterFactory(log, postTestImpressionsCount, impressionCounts, IMPRESSIONS_COUNT_RATE, fromImpressionCountsCollector, 1);
|
|
31
31
|
}
|
|
@@ -11,7 +11,7 @@ export function fromImpressionsCollector(sendLabels, data) {
|
|
|
11
11
|
dto.push({
|
|
12
12
|
f: name,
|
|
13
13
|
i: value.map(function (entry) {
|
|
14
|
-
|
|
14
|
+
var keyImpression = {
|
|
15
15
|
k: entry.keyName,
|
|
16
16
|
t: entry.treatment,
|
|
17
17
|
m: entry.time,
|
|
@@ -19,10 +19,9 @@ export function fromImpressionsCollector(sendLabels, data) {
|
|
|
19
19
|
r: sendLabels ? entry.label : undefined,
|
|
20
20
|
b: entry.bucketingKey,
|
|
21
21
|
pt: entry.pt,
|
|
22
|
-
properties: entry.properties
|
|
23
|
-
// @ts-expect-error - entityType is not yet public. @TODO: add to SplitIO.ImpressionDTO type
|
|
24
|
-
et: entry.entityType, // Definition type
|
|
22
|
+
properties: entry.properties // Properties
|
|
25
23
|
};
|
|
24
|
+
return keyImpression;
|
|
26
25
|
})
|
|
27
26
|
});
|
|
28
27
|
});
|
|
@@ -32,7 +31,7 @@ export function fromImpressionsCollector(sendLabels, data) {
|
|
|
32
31
|
* Submitter that periodically posts impressions data
|
|
33
32
|
*/
|
|
34
33
|
export function impressionsSubmitterFactory(params) {
|
|
35
|
-
var _a = params.settings, log = _a.log, impressionsRefreshRate = _a.scheduler.impressionsRefreshRate, labelsEnabled = _a.core.labelsEnabled, postTestImpressionsBulk = params.
|
|
34
|
+
var _a = params.settings, log = _a.log, impressionsRefreshRate = _a.scheduler.impressionsRefreshRate, labelsEnabled = _a.core.labelsEnabled, postTestImpressionsBulk = params.splitApi.postTestImpressionsBulk, impressions = params.storage.impressions;
|
|
36
35
|
// retry impressions only once.
|
|
37
36
|
var syncTask = submitterFactory(log, postTestImpressionsBulk, impressions, impressionsRefreshRate, fromImpressionsCollector.bind(undefined, labelsEnabled), 1);
|
|
38
37
|
// register impressions submitter to be executed when impressions cache is full
|
|
@@ -102,17 +102,18 @@ export function telemetrySubmitterFactory(params) {
|
|
|
102
102
|
var telemetry = params.storage.telemetry, now = params.platform.now;
|
|
103
103
|
if (!telemetry || !now)
|
|
104
104
|
return; // No submitter created if telemetry cache is not defined
|
|
105
|
-
var settings = params.settings, _a = params.settings, log = _a.log, telemetryRefreshRate = _a.scheduler.telemetryRefreshRate,
|
|
105
|
+
var settings = params.settings, _a = params.settings, log = _a.log, telemetryRefreshRate = _a.scheduler.telemetryRefreshRate, splitApi = params.splitApi, readiness = params.readiness, sdkReadinessManager = params.sdkReadinessManager;
|
|
106
106
|
var stopTimer = timer(now);
|
|
107
|
-
var submitter = firstPushWindowDecorator(submitterFactory(log,
|
|
107
|
+
var submitter = firstPushWindowDecorator(submitterFactory(log, splitApi.postMetricsUsage, telemetry, telemetryRefreshRate, undefined, 0, true), telemetryRefreshRate);
|
|
108
108
|
readiness.gate.once(SDK_READY_FROM_CACHE, function () {
|
|
109
109
|
telemetry.recordTimeUntilReadyFromCache(stopTimer());
|
|
110
110
|
});
|
|
111
|
+
sdkReadinessManager.incInternalReadyCbCount();
|
|
111
112
|
readiness.gate.once(SDK_READY, function () {
|
|
112
113
|
telemetry.recordTimeUntilReady(stopTimer());
|
|
113
114
|
// Post config data when the SDK is ready and if the telemetry submitter was started
|
|
114
115
|
if (submitter.isRunning()) {
|
|
115
|
-
var postMetricsConfigTask = submitterFactory(log,
|
|
116
|
+
var postMetricsConfigTask = submitterFactory(log, splitApi.postMetricsConfig, telemetryCacheConfigAdapter(telemetry, settings), 0, undefined, 0, true);
|
|
116
117
|
postMetricsConfigTask.execute();
|
|
117
118
|
}
|
|
118
119
|
});
|
|
@@ -5,7 +5,7 @@ var UNIQUE_KEYS_RATE = 900000; // 15 minutes
|
|
|
5
5
|
* Submitter that periodically posts impression counts
|
|
6
6
|
*/
|
|
7
7
|
export function uniqueKeysSubmitterFactory(params) {
|
|
8
|
-
var _a = params.settings, log = _a.log, key = _a.core.key, _b = params.
|
|
8
|
+
var _a = params.settings, log = _a.log, key = _a.core.key, _b = params.splitApi, postUniqueKeysBulkCs = _b.postUniqueKeysBulkCs, postUniqueKeysBulkSs = _b.postUniqueKeysBulkSs, uniqueKeys = params.storage.uniqueKeys;
|
|
9
9
|
var isClientSide = key !== undefined;
|
|
10
10
|
var postUniqueKeysBulk = isClientSide ? postUniqueKeysBulkCs : postUniqueKeysBulkSs;
|
|
11
11
|
var syncTask = submitterFactory(log, postUniqueKeysBulk, uniqueKeys, UNIQUE_KEYS_RATE);
|
|
@@ -3,10 +3,8 @@ 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
5
|
import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
|
|
6
|
-
import {
|
|
7
|
-
import { usesSegmentsSync } from '../storages/
|
|
8
|
-
import { splitChangesFetcherFactory } from './polling/fetchers/splitChangesFetcher';
|
|
9
|
-
import { segmentChangesFetcherFactory } from './polling/fetchers/segmentChangesFetcher';
|
|
6
|
+
import { SDK_SPLITS_CACHE_LOADED } from '../readiness/constants';
|
|
7
|
+
import { usesSegmentsSync } from '../storages/AbstractSplitsCacheSync';
|
|
10
8
|
/**
|
|
11
9
|
* Online SyncManager factory.
|
|
12
10
|
* Can be used for server-side API, and client-side API with or without multiple clients.
|
|
@@ -14,24 +12,21 @@ import { segmentChangesFetcherFactory } from './polling/fetchers/segmentChangesF
|
|
|
14
12
|
* @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
|
|
15
13
|
* `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
|
|
16
14
|
* @param pushManagerFactory - optional to build a SyncManager with or without streaming support
|
|
17
|
-
* @param definitionChangesFetcherFactory - optional to replace the default split changes fetcher
|
|
18
15
|
*/
|
|
19
|
-
export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory
|
|
20
|
-
if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcherFactory; }
|
|
21
|
-
if (segmentFetcherFactory === void 0) { segmentFetcherFactory = function (params) { return segmentChangesFetcherFactory(params.serviceApi.fetchSegmentChanges); }; }
|
|
16
|
+
export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
22
17
|
/**
|
|
23
18
|
* SyncManager factory for modular SDK
|
|
24
19
|
*/
|
|
25
20
|
return function (params) {
|
|
26
21
|
var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker, storage = params.storage, readiness = params.readiness;
|
|
27
22
|
/** Polling Manager */
|
|
28
|
-
var pollingManager = pollingManagerFactory && pollingManagerFactory(params
|
|
23
|
+
var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
29
24
|
/** Push Manager */
|
|
30
25
|
var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
|
31
26
|
pushManagerFactory(params, pollingManager) :
|
|
32
27
|
undefined;
|
|
33
28
|
/** Submitter Manager */
|
|
34
|
-
// It is not
|
|
29
|
+
// It is not inyected as push and polling managers, because at the moment it is required
|
|
35
30
|
var submitterManager = submitterManagerFactory(params);
|
|
36
31
|
/** Sync Manager logic */
|
|
37
32
|
function startPolling() {
|
|
@@ -79,7 +74,7 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
|
|
|
79
74
|
if (startFirstTime) {
|
|
80
75
|
// Emits SDK_READY_FROM_CACHE
|
|
81
76
|
if (!cacheMetadata.initialCacheLoad) {
|
|
82
|
-
readiness.
|
|
77
|
+
readiness.splits.emit(SDK_SPLITS_CACHE_LOADED, cacheMetadata);
|
|
83
78
|
}
|
|
84
79
|
}
|
|
85
80
|
// start syncing splits and segments
|
package/esm/utils/Backoff.js
CHANGED
|
@@ -24,26 +24,6 @@ var Backoff = /** @class */ (function () {
|
|
|
24
24
|
this.attempts++;
|
|
25
25
|
return delayInMillis;
|
|
26
26
|
};
|
|
27
|
-
/**
|
|
28
|
-
* Schedule a delayed call to `cb`
|
|
29
|
-
* @returns a promise that resolves/rejects with the result of the `cb` function, which must return a promise.
|
|
30
|
-
*/
|
|
31
|
-
Backoff.prototype.scheduleCallAsync = function () {
|
|
32
|
-
var _this = this;
|
|
33
|
-
var delayInMillis = Math.min(this.baseMillis * Math.pow(2, this.attempts), this.maxMillis);
|
|
34
|
-
if (this.timeoutID)
|
|
35
|
-
clearTimeout(this.timeoutID);
|
|
36
|
-
this.attempts++;
|
|
37
|
-
return new Promise(function (resolve, reject) {
|
|
38
|
-
_this.timeoutID = setTimeout(function () {
|
|
39
|
-
_this.timeoutID = undefined;
|
|
40
|
-
_this.cb().then(resolve, reject);
|
|
41
|
-
}, delayInMillis);
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* Reset the backoff attempts
|
|
46
|
-
*/
|
|
47
27
|
Backoff.prototype.reset = function () {
|
|
48
28
|
this.attempts = 0;
|
|
49
29
|
if (this.timeoutID) {
|
|
@@ -4,10 +4,10 @@ export { validateEvent } from './event';
|
|
|
4
4
|
export { validateEventValue } from './eventValue';
|
|
5
5
|
export { validateEventProperties } from './eventProperties';
|
|
6
6
|
export { validateKey } from './key';
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
7
|
+
export { validateSplit } from './split';
|
|
8
|
+
export { validateSplits } from './splits';
|
|
9
9
|
export { validateTrafficType } from './trafficType';
|
|
10
10
|
export { validateIfNotDestroyed, validateIfReadyFromCache, validateIfOperational } from './isOperational';
|
|
11
|
-
export {
|
|
11
|
+
export { validateSplitExistence } from './splitExistence';
|
|
12
12
|
export { validateTrafficTypeExistence } from './trafficTypeExistence';
|
|
13
13
|
export { validateEvaluationOptions } from './eventProperties';
|
|
@@ -5,13 +5,13 @@ export function validateIfNotDestroyed(log, readinessManager, method) {
|
|
|
5
5
|
log.error(ERROR_CLIENT_DESTROYED, [method]);
|
|
6
6
|
return false;
|
|
7
7
|
}
|
|
8
|
-
export function validateIfReadyFromCache(log, readinessManager, method) {
|
|
8
|
+
export function validateIfReadyFromCache(log, readinessManager, method, featureFlagNameOrNames) {
|
|
9
9
|
if (readinessManager.isReadyFromCache())
|
|
10
10
|
return true;
|
|
11
|
-
log.warn(CLIENT_NOT_READY_FROM_CACHE, [method]);
|
|
11
|
+
log.warn(CLIENT_NOT_READY_FROM_CACHE, [method, featureFlagNameOrNames ? " for feature flag ".concat(featureFlagNameOrNames.toString()) : '']);
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
14
|
// Operational means that the SDK is ready to evaluate (not destroyed and ready from cache)
|
|
15
|
-
export function validateIfOperational(log, readinessManager, method) {
|
|
16
|
-
return validateIfNotDestroyed(log, readinessManager, method) && validateIfReadyFromCache(log, readinessManager, method);
|
|
15
|
+
export function validateIfOperational(log, readinessManager, method, featureFlagNameOrNames) {
|
|
16
|
+
return validateIfNotDestroyed(log, readinessManager, method) && validateIfReadyFromCache(log, readinessManager, method, featureFlagNameOrNames);
|
|
17
17
|
}
|
|
@@ -2,21 +2,21 @@ import { ERROR_NULL, ERROR_INVALID, WARN_TRIMMING, ERROR_EMPTY } from '../../log
|
|
|
2
2
|
import { isString } from '../lang';
|
|
3
3
|
// include BOM and nbsp
|
|
4
4
|
var TRIMMABLE_SPACES_REGEX = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/;
|
|
5
|
-
export function
|
|
5
|
+
export function validateSplit(log, maybeSplit, method, item) {
|
|
6
6
|
if (item === void 0) { item = 'feature flag name'; }
|
|
7
|
-
if (
|
|
7
|
+
if (maybeSplit == undefined) { // eslint-disable-line eqeqeq
|
|
8
8
|
log.error(ERROR_NULL, [method, item]);
|
|
9
9
|
}
|
|
10
|
-
else if (!isString(
|
|
10
|
+
else if (!isString(maybeSplit)) {
|
|
11
11
|
log.error(ERROR_INVALID, [method, item]);
|
|
12
12
|
}
|
|
13
13
|
else {
|
|
14
|
-
if (TRIMMABLE_SPACES_REGEX.test(
|
|
15
|
-
log.warn(WARN_TRIMMING, [method, item,
|
|
16
|
-
|
|
14
|
+
if (TRIMMABLE_SPACES_REGEX.test(maybeSplit)) {
|
|
15
|
+
log.warn(WARN_TRIMMING, [method, item, maybeSplit]);
|
|
16
|
+
maybeSplit = maybeSplit.trim();
|
|
17
17
|
}
|
|
18
|
-
if (
|
|
19
|
-
return
|
|
18
|
+
if (maybeSplit.length > 0) {
|
|
19
|
+
return maybeSplit;
|
|
20
20
|
}
|
|
21
21
|
else {
|
|
22
22
|
log.error(ERROR_EMPTY, [method, item]);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FALLBACK_SPLIT_NOT_FOUND, SPLIT_NOT_FOUND } from '../labels';
|
|
2
|
+
import { WARN_NOT_EXISTENT_SPLIT } from '../../logger/constants';
|
|
3
|
+
/**
|
|
4
|
+
* This is defined here and in this format mostly because of the logger and the fact that it's considered a validation at product level.
|
|
5
|
+
* But it's not going to run on the input validation layer. In any case, the most compelling reason to use it as we do is to avoid going to Redis and get a split twice.
|
|
6
|
+
*/
|
|
7
|
+
export function validateSplitExistence(log, readinessManager, splitName, labelOrSplitObj, method) {
|
|
8
|
+
if (readinessManager.isReady()) { // Only if it's ready (synced with BE) we validate this, otherwise it may just be that the SDK is still syncing
|
|
9
|
+
if (labelOrSplitObj === SPLIT_NOT_FOUND || labelOrSplitObj === FALLBACK_SPLIT_NOT_FOUND || labelOrSplitObj == null) {
|
|
10
|
+
log.warn(WARN_NOT_EXISTENT_SPLIT, [method, splitName]);
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ERROR_EMPTY_ARRAY } from '../../logger/constants';
|
|
2
|
+
import { uniq } from '../lang';
|
|
3
|
+
import { validateSplit } from './split';
|
|
4
|
+
export function validateSplits(log, maybeSplits, method, listName, item) {
|
|
5
|
+
if (listName === void 0) { listName = 'feature flag names'; }
|
|
6
|
+
if (item === void 0) { item = 'feature flag name'; }
|
|
7
|
+
if (Array.isArray(maybeSplits) && maybeSplits.length > 0) {
|
|
8
|
+
var validatedArray_1 = [];
|
|
9
|
+
// Remove invalid values
|
|
10
|
+
maybeSplits.forEach(function (maybeSplit) {
|
|
11
|
+
var splitName = validateSplit(log, maybeSplit, method, item);
|
|
12
|
+
if (splitName)
|
|
13
|
+
validatedArray_1.push(splitName);
|
|
14
|
+
});
|
|
15
|
+
// Strip off duplicated values if we have valid split names then return
|
|
16
|
+
if (validatedArray_1.length)
|
|
17
|
+
return uniq(validatedArray_1);
|
|
18
|
+
}
|
|
19
|
+
log.error(ERROR_EMPTY_ARRAY, [method, listName]);
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { FALLBACK_PREFIX } from '../../evaluator/fallbackTreatmentsCalculator';
|
|
2
2
|
export var SPLIT_KILLED = 'killed';
|
|
3
3
|
export var NO_CONDITION_MATCH = 'default rule';
|
|
4
|
-
export var
|
|
4
|
+
export var SPLIT_NOT_FOUND = 'definition not found';
|
|
5
5
|
export var SDK_NOT_READY = 'not ready';
|
|
6
6
|
export var EXCEPTION = 'exception';
|
|
7
7
|
export var SPLIT_ARCHIVED = 'archived';
|
|
8
8
|
export var NOT_IN_SPLIT = 'not in split';
|
|
9
9
|
export var UNSUPPORTED_MATCHER_TYPE = 'targeting rule type unsupported by sdk';
|
|
10
10
|
export var PREREQUISITES_NOT_MET = 'prerequisites not met';
|
|
11
|
-
export var
|
|
11
|
+
export var FALLBACK_SPLIT_NOT_FOUND = FALLBACK_PREFIX + SPLIT_NOT_FOUND;
|
|
@@ -52,8 +52,6 @@ export var base = {
|
|
|
52
52
|
streaming: 'https://streaming.split.io',
|
|
53
53
|
// Telemetry Server
|
|
54
54
|
telemetry: 'https://telemetry.split.io/api',
|
|
55
|
-
// Configs Server
|
|
56
|
-
configs: 'https://configs.split.io',
|
|
57
55
|
},
|
|
58
56
|
// Defines which kind of storage we should instantiate.
|
|
59
57
|
storage: undefined,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { validateSplits } from '../inputValidation/splits';
|
|
2
2
|
import { WARN_SPLITS_FILTER_IGNORED, WARN_SPLITS_FILTER_EMPTY, WARN_SPLITS_FILTER_INVALID, SETTINGS_SPLITS_FILTER, LOG_PREFIX_SETTINGS, ERROR_SETS_FILTER_EXCLUSIVE, WARN_LOWERCASE_FLAGSET, WARN_INVALID_FLAGSET, WARN_FLAGSET_NOT_CONFIGURED } from '../../logger/constants';
|
|
3
3
|
import { objectAssign } from '../lang/objectAssign';
|
|
4
4
|
import { find, uniq } from '../lang';
|
|
@@ -42,7 +42,7 @@ function validateFilterType(maybeFilterType) {
|
|
|
42
42
|
*/
|
|
43
43
|
function validateSplitFilter(log, type, values, maxLength) {
|
|
44
44
|
// validate and remove invalid and duplicated values
|
|
45
|
-
var result =
|
|
45
|
+
var result = validateSplits(log, values, LOG_PREFIX_SETTINGS, "".concat(type, " filter"), "".concat(type, " filter value"));
|
|
46
46
|
if (result) {
|
|
47
47
|
if (type === 'bySet') {
|
|
48
48
|
result = sanitizeFlagSets(log, result, LOG_PREFIX_SETTINGS);
|
|
@@ -168,7 +168,7 @@ export function validateSplitFilters(log, maybeSplitFilters, mode) {
|
|
|
168
168
|
return res;
|
|
169
169
|
}
|
|
170
170
|
export function validateFlagSets(log, method, flagSets, flagSetsInConfig) {
|
|
171
|
-
var sets =
|
|
171
|
+
var sets = validateSplits(log, flagSets, method, 'flag sets', 'flag set');
|
|
172
172
|
var toReturn = sets ? sanitizeFlagSets(log, sets, method) : [];
|
|
173
173
|
if (flagSetsInConfig.length > 0) {
|
|
174
174
|
toReturn = toReturn.filter(function (flagSet) {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
var telemetryEndpointMatcher = /^\/v1\/
|
|
1
|
+
var telemetryEndpointMatcher = /^\/v1\/metrics\/(config|usage)/;
|
|
2
2
|
var eventsEndpointMatcher = /^\/(testImpressions|metrics|events)/;
|
|
3
|
-
var authEndpointMatcher = /^\/
|
|
3
|
+
var authEndpointMatcher = /^\/v2\/auth/;
|
|
4
4
|
var streamingEndpointMatcher = /^\/(sse|event-stream)/;
|
|
5
|
-
var configsEndpointMatcher = /^\/v1\/(configs|segmentChanges)/;
|
|
6
5
|
/**
|
|
7
6
|
* Get URL based on a given target (path).
|
|
8
7
|
* ATM, it is only used for testing purposes.
|
|
@@ -24,8 +23,5 @@ export function url(settings, target) {
|
|
|
24
23
|
if (streamingEndpointMatcher.test(target)) {
|
|
25
24
|
return "".concat(settings.urls.streaming).concat(target);
|
|
26
25
|
}
|
|
27
|
-
if (configsEndpointMatcher.test(target)) {
|
|
28
|
-
return "".concat(settings.urls.configs).concat(target);
|
|
29
|
-
}
|
|
30
26
|
return "".concat(settings.urls.sdk).concat(target);
|
|
31
27
|
}
|