@splitsoftware/splitio-commons 3.0.0-rc.0 → 3.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.txt +8 -3
- package/cjs/evaluator/index.js +11 -11
- package/cjs/logger/constants.js +4 -4
- package/cjs/logger/messages/warn.js +0 -1
- package/cjs/readiness/constants.js +4 -4
- package/cjs/readiness/readinessManager.js +22 -22
- package/cjs/readiness/sdkReadinessManager.js +0 -16
- package/cjs/sdkClient/sdkLifecycle.js +2 -1
- package/cjs/sdkClient/trackMethod.js +2 -2
- package/cjs/sdkFactory/index.js +5 -5
- package/cjs/sdkManager/index.js +2 -2
- package/cjs/services/authProvider.js +67 -0
- package/cjs/services/secureSplitHttpClient.js +39 -0
- package/cjs/services/splitApi.js +7 -2
- package/cjs/storages/AbstractDefinitionsCacheAsync.js +51 -0
- package/cjs/storages/AbstractDefinitionsCacheSync.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/DefinitionsCacheInLocal.js +194 -0
- package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +9 -9
- package/cjs/storages/inLocalStorage/index.js +6 -6
- package/cjs/storages/inLocalStorage/validateCache.js +3 -3
- package/cjs/storages/inMemory/DefinitionsCacheInMemory.js +121 -0
- package/cjs/storages/inMemory/InMemoryStorage.js +4 -4
- package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +4 -4
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +3 -3
- package/cjs/storages/inRedis/{SplitsCacheInRedis.js → DefinitionsCacheInRedis.js} +77 -77
- package/cjs/storages/inRedis/index.js +2 -2
- package/cjs/storages/pluggable/DefinitionsCachePluggable.js +212 -0
- package/cjs/storages/pluggable/index.js +2 -2
- package/cjs/storages/setRolloutPlan.js +5 -5
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +5 -5
- package/cjs/sync/polling/fetchers/splitChangesFetcher.js +1 -1
- package/cjs/sync/polling/pollingManagerCS.js +7 -7
- package/cjs/sync/polling/syncTasks/definitionsSyncTask.js +1 -1
- package/cjs/sync/polling/updaters/definitionChangesUpdater.js +8 -8
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +2 -2
- package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +1 -1
- package/cjs/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.js → DefinitionsUpdateWorker.js} +15 -15
- package/cjs/sync/streaming/constants.js +3 -3
- package/cjs/sync/streaming/pushManager.js +13 -13
- package/cjs/sync/submitters/telemetrySubmitter.js +1 -2
- package/cjs/sync/syncManagerOnline.js +4 -4
- package/cjs/utils/Backoff.js +20 -0
- package/cjs/utils/lang/sets.js +4 -4
- package/cjs/utils/settingsValidation/url.js +1 -1
- package/esm/evaluator/index.js +11 -11
- package/esm/logger/constants.js +1 -1
- package/esm/logger/messages/warn.js +0 -1
- package/esm/readiness/constants.js +3 -3
- package/esm/readiness/readinessManager.js +23 -23
- package/esm/readiness/sdkReadinessManager.js +1 -17
- package/esm/sdkClient/sdkLifecycle.js +2 -1
- package/esm/sdkClient/trackMethod.js +2 -2
- package/esm/sdkFactory/index.js +6 -6
- package/esm/sdkManager/index.js +2 -2
- package/esm/services/authProvider.js +63 -0
- package/esm/services/secureSplitHttpClient.js +35 -0
- package/esm/services/splitApi.js +7 -2
- package/esm/storages/AbstractDefinitionsCacheAsync.js +48 -0
- package/esm/storages/AbstractDefinitionsCacheSync.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/DefinitionsCacheInLocal.js +191 -0
- package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +6 -6
- package/esm/storages/inLocalStorage/index.js +6 -6
- package/esm/storages/inLocalStorage/validateCache.js +3 -3
- package/esm/storages/inMemory/DefinitionsCacheInMemory.js +118 -0
- package/esm/storages/inMemory/InMemoryStorage.js +4 -4
- package/esm/storages/inMemory/InMemoryStorageCS.js +5 -5
- package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +1 -1
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +3 -3
- package/esm/storages/inRedis/{SplitsCacheInRedis.js → DefinitionsCacheInRedis.js} +76 -76
- package/esm/storages/inRedis/index.js +2 -2
- package/esm/storages/pluggable/DefinitionsCachePluggable.js +209 -0
- package/esm/storages/pluggable/index.js +2 -2
- package/esm/storages/setRolloutPlan.js +5 -5
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +6 -6
- package/esm/sync/polling/fetchers/splitChangesFetcher.js +1 -1
- package/esm/sync/polling/pollingManagerCS.js +4 -4
- package/esm/sync/polling/syncTasks/definitionsSyncTask.js +1 -1
- package/esm/sync/polling/updaters/definitionChangesUpdater.js +9 -9
- package/esm/sync/polling/updaters/mySegmentsUpdater.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/{SplitsUpdateWorker.js → DefinitionsUpdateWorker.js} +14 -14
- package/esm/sync/streaming/constants.js +2 -2
- package/esm/sync/streaming/pushManager.js +14 -14
- package/esm/sync/submitters/telemetrySubmitter.js +1 -2
- package/esm/sync/syncManagerOnline.js +3 -3
- package/esm/utils/Backoff.js +20 -0
- package/esm/utils/lang/sets.js +4 -4
- package/esm/utils/settingsValidation/url.js +1 -1
- package/package.json +1 -1
- package/src/dtos/types.ts +2 -2
- package/src/evaluator/index.ts +11 -11
- package/src/logger/constants.ts +1 -1
- package/src/logger/messages/warn.ts +0 -1
- package/src/readiness/constants.ts +3 -3
- package/src/readiness/readinessManager.ts +22 -22
- package/src/readiness/sdkReadinessManager.ts +1 -16
- package/src/readiness/types.ts +10 -16
- package/src/sdkClient/sdkLifecycle.ts +2 -1
- package/src/sdkClient/trackMethod.ts +2 -2
- package/src/sdkFactory/index.ts +5 -5
- package/src/sdkManager/index.ts +6 -6
- package/src/services/authProvider.ts +86 -0
- package/src/services/secureSplitHttpClient.ts +44 -0
- package/src/services/splitApi.ts +9 -3
- package/src/services/types.ts +4 -0
- package/src/storages/AbstractDefinitionsCacheAsync.ts +63 -0
- package/src/storages/AbstractDefinitionsCacheSync.ts +95 -0
- package/src/storages/KeyBuilder.ts +6 -6
- package/src/storages/KeyBuilderCS.ts +6 -6
- package/src/storages/KeyBuilderSS.ts +2 -2
- package/src/storages/getRolloutPlan.ts +3 -3
- package/src/storages/inLocalStorage/DefinitionsCacheInLocal.ts +234 -0
- package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +6 -6
- package/src/storages/inLocalStorage/index.ts +6 -6
- package/src/storages/inLocalStorage/validateCache.ts +4 -4
- package/src/storages/inMemory/DefinitionsCacheInMemory.ts +130 -0
- package/src/storages/inMemory/InMemoryStorage.ts +4 -4
- package/src/storages/inMemory/InMemoryStorageCS.ts +5 -5
- package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +1 -1
- package/src/storages/inMemory/SegmentsCacheInMemory.ts +1 -1
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +3 -3
- package/src/storages/inRedis/{SplitsCacheInRedis.ts → DefinitionsCacheInRedis.ts} +67 -67
- package/src/storages/inRedis/index.ts +2 -2
- package/src/storages/pluggable/DefinitionsCachePluggable.ts +230 -0
- package/src/storages/pluggable/index.ts +2 -2
- package/src/storages/setRolloutPlan.ts +7 -7
- package/src/storages/types.ts +19 -19
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +8 -8
- package/src/sync/polling/fetchers/splitChangesFetcher.ts +3 -3
- package/src/sync/polling/pollingManagerCS.ts +4 -4
- package/src/sync/polling/syncTasks/definitionsSyncTask.ts +1 -1
- package/src/sync/polling/types.ts +1 -1
- package/src/sync/polling/updaters/definitionChangesUpdater.ts +11 -11
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +1 -1
- package/src/sync/streaming/AuthClient/index.ts +2 -2
- package/src/sync/streaming/AuthClient/types.ts +14 -11
- package/src/sync/streaming/SSEClient/index.ts +2 -2
- package/src/sync/streaming/SSEClient/types.ts +2 -2
- package/src/sync/streaming/SSEHandler/NotificationKeeper.ts +2 -2
- package/src/sync/streaming/SSEHandler/index.ts +2 -2
- package/src/sync/streaming/UpdateWorkers/{SplitsUpdateWorker.ts → DefinitionsUpdateWorker.ts} +16 -16
- package/src/sync/streaming/constants.ts +2 -2
- package/src/sync/streaming/pushManager.ts +16 -16
- package/src/sync/streaming/types.ts +2 -2
- package/src/sync/submitters/telemetrySubmitter.ts +1 -2
- package/src/sync/syncManagerOnline.ts +3 -3
- package/src/utils/Backoff.ts +21 -0
- package/src/utils/inputValidation/trafficTypeExistence.ts +2 -2
- package/src/utils/jwt/types.ts +1 -1
- package/src/utils/lang/sets.ts +4 -2
- package/src/utils/settingsValidation/url.ts +1 -1
- package/types/splitio.d.ts +23 -5
- package/cjs/storages/AbstractSplitsCacheAsync.js +0 -51
- package/cjs/storages/AbstractSplitsCacheSync.js +0 -76
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +0 -194
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +0 -121
- package/cjs/storages/pluggable/SplitsCachePluggable.js +0 -212
- package/esm/storages/AbstractSplitsCacheAsync.js +0 -48
- package/esm/storages/AbstractSplitsCacheSync.js +0 -71
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +0 -191
- package/esm/storages/inMemory/SplitsCacheInMemory.js +0 -118
- package/esm/storages/pluggable/SplitsCachePluggable.js +0 -209
- package/src/storages/AbstractSplitsCacheAsync.ts +0 -63
- package/src/storages/AbstractSplitsCacheSync.ts +0 -95
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +0 -234
- package/src/storages/inMemory/SplitsCacheInMemory.ts +0 -130
- package/src/storages/pluggable/SplitsCachePluggable.ts +0 -230
package/esm/logger/constants.js
CHANGED
|
@@ -54,7 +54,6 @@ export var USER_CONSENT_INITIAL = 124;
|
|
|
54
54
|
export var SUBMITTERS_PUSH_PAGE_HIDDEN = 125;
|
|
55
55
|
export var ENGINE_VALUE_INVALID = 200;
|
|
56
56
|
export var ENGINE_VALUE_NO_ATTRIBUTES = 201;
|
|
57
|
-
export var CLIENT_NO_LISTENER = 202;
|
|
58
57
|
export var CLIENT_NOT_READY_FROM_CACHE = 203;
|
|
59
58
|
export var SYNC_FETCH_RETRY = 204;
|
|
60
59
|
export var SYNC_FETCH_FAILS = 205;
|
|
@@ -119,6 +118,7 @@ export var LOG_PREFIX_ENGINE_COMBINER = LOG_PREFIX_ENGINE + ':combiner: ';
|
|
|
119
118
|
export var LOG_PREFIX_ENGINE_MATCHER = LOG_PREFIX_ENGINE + ':matcher: ';
|
|
120
119
|
export var LOG_PREFIX_ENGINE_VALUE = LOG_PREFIX_ENGINE + ':value: ';
|
|
121
120
|
export var LOG_PREFIX_SYNC = 'sync: ';
|
|
121
|
+
export var LOG_PREFIX_SYNC_AUTH = 'sync:auth: ';
|
|
122
122
|
export var LOG_PREFIX_SYNC_MANAGER = 'sync:sync-manager: ';
|
|
123
123
|
export var LOG_PREFIX_SYNC_OFFLINE = 'sync:offline: ';
|
|
124
124
|
export var LOG_PREFIX_SYNC_STREAMING = 'sync:streaming: ';
|
|
@@ -14,7 +14,6 @@ export var codesWarn = codesError.concat([
|
|
|
14
14
|
[c.SUBMITTERS_PUSH_RETRY, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Failed to push %s, keeping data to retry on next iteration. Reason: %s'],
|
|
15
15
|
// client status
|
|
16
16
|
[c.CLIENT_NOT_READY_FROM_CACHE, '%s: the SDK is not ready to evaluate. Results may be incorrect. Make sure to wait for SDK readiness before using this method.'],
|
|
17
|
-
[c.CLIENT_NO_LISTENER, 'No listeners for SDK_READY event detected. Incorrect control treatments could have been logged if you called getTreatment/s while the SDK was not yet synchronized with the backend.'],
|
|
18
17
|
// input validation
|
|
19
18
|
[c.WARN_SETTING_NULL, '%s: Property "%s" is of invalid type. Setting value to null.'],
|
|
20
19
|
[c.WARN_TRIMMING_PROPERTIES, '%s: more than 300 properties were provided. Some of them will be trimmed when processed.'],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
//
|
|
2
|
-
export var
|
|
3
|
-
export var
|
|
1
|
+
// Definitions events:
|
|
2
|
+
export var SDK_DEFINITIONS_ARRIVED = 'state::splits-arrived';
|
|
3
|
+
export var SDK_DEFINITIONS_CACHE_LOADED = 'state::splits-cache-loaded';
|
|
4
4
|
// Segments events:
|
|
5
5
|
export var SDK_SEGMENTS_ARRIVED = 'state::segments-arrived';
|
|
6
6
|
// Readiness events:
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
|
-
import {
|
|
3
|
-
function
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { SDK_DEFINITIONS_ARRIVED, SDK_DEFINITIONS_CACHE_LOADED, SDK_SEGMENTS_ARRIVED, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE, SDK_READY } from './constants';
|
|
3
|
+
function definitionsEventEmitterFactory(EventEmitter) {
|
|
4
|
+
var definitionsEventEmitter = objectAssign(new EventEmitter(), {
|
|
5
|
+
definitionsArrived: false,
|
|
6
|
+
definitionsCacheLoaded: false,
|
|
7
7
|
hasInit: false,
|
|
8
8
|
initCallbacks: []
|
|
9
9
|
});
|
|
10
10
|
// `isSplitKill` condition avoids an edge-case of wrongly emitting SDK_READY if:
|
|
11
11
|
// - `/memberships` fetch and SPLIT_KILL occurs before `/splitChanges` fetch, and
|
|
12
12
|
// - storage has cached splits (for which case `splitsStorage.killLocally` can return true)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return
|
|
13
|
+
definitionsEventEmitter.on(SDK_DEFINITIONS_ARRIVED, function (metadata, isSplitKill) { if (!isSplitKill)
|
|
14
|
+
definitionsEventEmitter.definitionsArrived = true; });
|
|
15
|
+
definitionsEventEmitter.once(SDK_DEFINITIONS_CACHE_LOADED, function () { definitionsEventEmitter.definitionsCacheLoaded = true; });
|
|
16
|
+
return definitionsEventEmitter;
|
|
17
17
|
}
|
|
18
18
|
function segmentsEventEmitterFactory(EventEmitter) {
|
|
19
19
|
var segmentsEventEmitter = objectAssign(new EventEmitter(), {
|
|
@@ -25,8 +25,8 @@ function segmentsEventEmitterFactory(EventEmitter) {
|
|
|
25
25
|
/**
|
|
26
26
|
* Factory of readiness manager, which handles the ready / update event propagation.
|
|
27
27
|
*/
|
|
28
|
-
export function readinessManagerFactory(EventEmitter, settings,
|
|
29
|
-
if (
|
|
28
|
+
export function readinessManagerFactory(EventEmitter, settings, definitions, isShared) {
|
|
29
|
+
if (definitions === void 0) { definitions = definitionsEventEmitterFactory(EventEmitter); }
|
|
30
30
|
var readyTimeout = settings.startup.readyTimeout;
|
|
31
31
|
var segments = segmentsEventEmitterFactory(EventEmitter);
|
|
32
32
|
var gate = new EventEmitter();
|
|
@@ -41,10 +41,10 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
41
41
|
};
|
|
42
42
|
// emit SDK_READY_FROM_CACHE
|
|
43
43
|
var isReadyFromCache = false;
|
|
44
|
-
if (
|
|
44
|
+
if (definitions.definitionsCacheLoaded)
|
|
45
45
|
isReadyFromCache = true; // ready from cache, but doesn't emit SDK_READY_FROM_CACHE
|
|
46
46
|
else
|
|
47
|
-
|
|
47
|
+
definitions.once(SDK_DEFINITIONS_CACHE_LOADED, checkIsReadyFromCache);
|
|
48
48
|
// emit SDK_READY_TIMED_OUT
|
|
49
49
|
var hasTimedout = false;
|
|
50
50
|
function timeout() {
|
|
@@ -56,7 +56,7 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
56
56
|
}
|
|
57
57
|
// emit SDK_READY and SDK_UPDATE
|
|
58
58
|
var isReady = false;
|
|
59
|
-
|
|
59
|
+
definitions.on(SDK_DEFINITIONS_ARRIVED, checkIsReadyOrUpdate);
|
|
60
60
|
segments.on(SDK_SEGMENTS_ARRIVED, checkIsReadyOrUpdate);
|
|
61
61
|
var isDestroyed = false;
|
|
62
62
|
var readyTimeoutId;
|
|
@@ -65,8 +65,8 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
65
65
|
if (readyTimeout > 0 && !isReady)
|
|
66
66
|
readyTimeoutId = setTimeout(timeout, readyTimeout);
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
if (
|
|
68
|
+
definitions.initCallbacks.push(__init);
|
|
69
|
+
if (definitions.hasInit)
|
|
70
70
|
__init();
|
|
71
71
|
function checkIsReadyFromCache(cacheMetadata) {
|
|
72
72
|
metadataReady = cacheMetadata;
|
|
@@ -97,7 +97,7 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
else {
|
|
100
|
-
if (
|
|
100
|
+
if (definitions.definitionsArrived && segments.segmentsArrived) {
|
|
101
101
|
clearTimeout(readyTimeoutId);
|
|
102
102
|
isReady = true;
|
|
103
103
|
try {
|
|
@@ -120,11 +120,11 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
return {
|
|
123
|
-
|
|
123
|
+
definitions: definitions,
|
|
124
124
|
segments: segments,
|
|
125
125
|
gate: gate,
|
|
126
126
|
shared: function () {
|
|
127
|
-
return readinessManagerFactory(EventEmitter, settings,
|
|
127
|
+
return readinessManagerFactory(EventEmitter, settings, definitions, true);
|
|
128
128
|
},
|
|
129
129
|
// @TODO review/remove next methods when non-recoverable errors are reworked
|
|
130
130
|
// Called on consumer mode, when storage fails to connect
|
|
@@ -133,17 +133,17 @@ export function readinessManagerFactory(EventEmitter, settings, splits, isShared
|
|
|
133
133
|
// tracking and evaluations, while keeping event listeners to emit SDK_READY_TIMED_OUT event
|
|
134
134
|
setDestroyed: function () { isDestroyed = true; },
|
|
135
135
|
init: function () {
|
|
136
|
-
if (
|
|
136
|
+
if (definitions.hasInit)
|
|
137
137
|
return;
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
definitions.hasInit = true;
|
|
139
|
+
definitions.initCallbacks.forEach(function (cb) { return cb(); });
|
|
140
140
|
},
|
|
141
141
|
destroy: function () {
|
|
142
142
|
isDestroyed = true;
|
|
143
143
|
syncLastUpdate();
|
|
144
144
|
clearTimeout(readyTimeoutId);
|
|
145
145
|
if (!isShared)
|
|
146
|
-
|
|
146
|
+
definitions.hasInit = false;
|
|
147
147
|
},
|
|
148
148
|
isReady: function () { return isReady; },
|
|
149
149
|
isReadyFromCache: function () { return isReadyFromCache; },
|
|
@@ -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 { SDK_READY, SDK_READY_TIMED_OUT, SDK_READY_FROM_CACHE, SDK_UPDATE } from './constants';
|
|
5
|
-
import { ERROR_CLIENT_LISTENER, CLIENT_READY_FROM_CACHE, CLIENT_READY
|
|
5
|
+
import { ERROR_CLIENT_LISTENER, CLIENT_READY_FROM_CACHE, CLIENT_READY } from '../logger/constants';
|
|
6
6
|
var NEW_LISTENER_EVENT = 'newListener';
|
|
7
|
-
var REMOVE_LISTENER_EVENT = 'removeListener';
|
|
8
7
|
var TIMEOUT_ERROR = new Error(SDK_READY_TIMED_OUT);
|
|
9
8
|
/**
|
|
10
9
|
* SdkReadinessManager factory, which provides the public status API of SDK clients and manager: ready promise, readiness event emitter and constants (SDK_READY, etc).
|
|
@@ -16,21 +15,11 @@ var TIMEOUT_ERROR = new Error(SDK_READY_TIMED_OUT);
|
|
|
16
15
|
export function sdkReadinessManagerFactory(EventEmitter, settings, readinessManager) {
|
|
17
16
|
if (readinessManager === void 0) { readinessManager = readinessManagerFactory(EventEmitter, settings); }
|
|
18
17
|
var log = settings.log;
|
|
19
|
-
/** Ready callback warning */
|
|
20
|
-
var internalReadyCbCount = 0;
|
|
21
|
-
var readyCbCount = 0;
|
|
22
|
-
readinessManager.gate.on(REMOVE_LISTENER_EVENT, function (event) {
|
|
23
|
-
if (event === SDK_READY)
|
|
24
|
-
readyCbCount--;
|
|
25
|
-
});
|
|
26
18
|
readinessManager.gate.on(NEW_LISTENER_EVENT, function (event) {
|
|
27
19
|
if (event === SDK_READY || event === SDK_READY_TIMED_OUT) {
|
|
28
20
|
if (readinessManager.isReady()) {
|
|
29
21
|
log.error(ERROR_CLIENT_LISTENER, [event === SDK_READY ? 'SDK_READY' : 'SDK_READY_TIMED_OUT']);
|
|
30
22
|
}
|
|
31
|
-
else if (event === SDK_READY) {
|
|
32
|
-
readyCbCount++;
|
|
33
|
-
}
|
|
34
23
|
}
|
|
35
24
|
else if (event === SDK_READY_FROM_CACHE && readinessManager.isReadyFromCache()) {
|
|
36
25
|
log.error(ERROR_CLIENT_LISTENER, ['SDK_READY_FROM_CACHE']);
|
|
@@ -49,8 +38,6 @@ export function sdkReadinessManagerFactory(EventEmitter, settings, readinessMana
|
|
|
49
38
|
var promise = promiseWrapper(new Promise(function (resolve, reject) {
|
|
50
39
|
readinessManager.gate.once(SDK_READY, function () {
|
|
51
40
|
log.info(CLIENT_READY);
|
|
52
|
-
if (readyCbCount === internalReadyCbCount && !promise.hasOnFulfilled())
|
|
53
|
-
log.warn(CLIENT_NO_LISTENER);
|
|
54
41
|
resolve();
|
|
55
42
|
});
|
|
56
43
|
readinessManager.gate.once(SDK_READY_TIMED_OUT, function (message) {
|
|
@@ -75,9 +62,6 @@ export function sdkReadinessManagerFactory(EventEmitter, settings, readinessMana
|
|
|
75
62
|
shared: function () {
|
|
76
63
|
return sdkReadinessManagerFactory(EventEmitter, settings, readinessManager.shared());
|
|
77
64
|
},
|
|
78
|
-
incInternalReadyCbCount: function () {
|
|
79
|
-
internalReadyCbCount++;
|
|
80
|
-
},
|
|
81
65
|
sdkStatus: objectAssign(
|
|
82
66
|
// Expose Event Emitter functionality
|
|
83
67
|
Object.create(readinessManager.gate), {
|
|
@@ -4,7 +4,7 @@ var COOLDOWN_TIME_IN_MILLIS = 1000;
|
|
|
4
4
|
* Creates an Sdk client, i.e., a base client with status, init, flush and destroy interface
|
|
5
5
|
*/
|
|
6
6
|
export function sdkLifecycleFactory(params, isSharedClient) {
|
|
7
|
-
var sdkReadinessManager = params.sdkReadinessManager, syncManager = params.syncManager, storage = params.storage, settings = params.settings, telemetryTracker = params.telemetryTracker, impressionsTracker = params.impressionsTracker, platform = params.platform;
|
|
7
|
+
var sdkReadinessManager = params.sdkReadinessManager, syncManager = params.syncManager, storage = params.storage, settings = params.settings, telemetryTracker = params.telemetryTracker, impressionsTracker = params.impressionsTracker, platform = params.platform, splitApi = params.splitApi;
|
|
8
8
|
var hasInit = false;
|
|
9
9
|
var lastActionTime = 0;
|
|
10
10
|
var signalListener = platform.SignalListener && new platform.SignalListener(params);
|
|
@@ -57,6 +57,7 @@ export function sdkLifecycleFactory(params, isSharedClient) {
|
|
|
57
57
|
}
|
|
58
58
|
// Stop background jobs
|
|
59
59
|
syncManager && syncManager.stop();
|
|
60
|
+
splitApi && splitApi.stop();
|
|
60
61
|
return __flush().then(function () {
|
|
61
62
|
// Cleanup storage
|
|
62
63
|
return storage.destroy();
|
|
@@ -10,7 +10,7 @@ import { isConsumerMode } from '../utils/settingsValidation/mode';
|
|
|
10
10
|
*/
|
|
11
11
|
export function trackMethodFactory(params, warnTTExistence) {
|
|
12
12
|
if (warnTTExistence === void 0) { warnTTExistence = true; }
|
|
13
|
-
var settings = params.settings,
|
|
13
|
+
var settings = params.settings, definitions = params.storage.definitions, telemetryTracker = params.telemetryTracker, eventTracker = params.eventTracker, readinessManager = params.sdkReadinessManager.readinessManager;
|
|
14
14
|
var log = settings.log, mode = settings.mode;
|
|
15
15
|
var isAsync = isConsumerMode(mode);
|
|
16
16
|
return function track(maybeKey, maybeTT, maybeEvent, maybeEventValue, maybeProperties) {
|
|
@@ -36,7 +36,7 @@ export function trackMethodFactory(params, warnTTExistence) {
|
|
|
36
36
|
};
|
|
37
37
|
// This may be async but we only warn, we don't actually care if it is valid or not in terms of queueing the event.
|
|
38
38
|
if (warnTTExistence)
|
|
39
|
-
validateTrafficTypeExistence(log, readinessManager,
|
|
39
|
+
validateTrafficTypeExistence(log, readinessManager, definitions, mode, trafficTypeName, TRACK_FN_LABEL);
|
|
40
40
|
var result = eventTracker.track(eventData, size);
|
|
41
41
|
if (thenable(result)) {
|
|
42
42
|
return result.then(function (result) {
|
package/esm/sdkFactory/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { eventTrackerFactory } from '../trackers/eventTracker';
|
|
|
4
4
|
import { telemetryTrackerFactory } from '../trackers/telemetryTracker';
|
|
5
5
|
import { createLoggerAPI } from '../logger/sdkLogger';
|
|
6
6
|
import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
|
|
7
|
-
import {
|
|
7
|
+
import { SDK_DEFINITIONS_ARRIVED, SDK_SEGMENTS_ARRIVED, SDK_DEFINITIONS_CACHE_LOADED } from '../readiness/constants';
|
|
8
8
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
9
9
|
import { setRolloutPlan } from '../storages/setRolloutPlan';
|
|
10
10
|
import { getMatching } from '../utils/key';
|
|
@@ -27,18 +27,18 @@ export function sdkFactory(params) {
|
|
|
27
27
|
readiness.timeout();
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
|
-
readiness.
|
|
30
|
+
readiness.definitions.emit(SDK_DEFINITIONS_ARRIVED);
|
|
31
31
|
readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
32
32
|
},
|
|
33
33
|
onReadyFromCacheCb: function () {
|
|
34
|
-
readiness.
|
|
34
|
+
readiness.definitions.emit(SDK_DEFINITIONS_CACHE_LOADED);
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
var fallbackCalculator = FallbackTreatmentsCalculator(settings.fallbackTreatments);
|
|
38
38
|
if (initialRolloutPlan) {
|
|
39
39
|
setRolloutPlan(log, initialRolloutPlan, storage, key && getMatching(key));
|
|
40
|
-
if (storage.
|
|
41
|
-
readiness.
|
|
40
|
+
if (storage.definitions.getChangeNumber() > -1)
|
|
41
|
+
readiness.definitions.emit(SDK_DEFINITIONS_CACHE_LOADED, { initialCacheLoad: false /* Not an initial load, cache exists */ });
|
|
42
42
|
}
|
|
43
43
|
var clients = {};
|
|
44
44
|
var telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
|
|
@@ -51,7 +51,7 @@ export function sdkFactory(params) {
|
|
|
51
51
|
ctx.syncManager = syncManagerFactory && syncManagerFactory(ctx);
|
|
52
52
|
// SDK client and manager
|
|
53
53
|
var clientMethod = sdkClientMethodFactory(ctx);
|
|
54
|
-
var managerInstance = sdkManagerFactory(settings, storage.
|
|
54
|
+
var managerInstance = sdkManagerFactory(settings, storage.definitions, sdkReadinessManager);
|
|
55
55
|
function init() {
|
|
56
56
|
Object.keys(clients).map(function (key) { return clients[key].init(); });
|
|
57
57
|
}
|
package/esm/sdkManager/index.js
CHANGED
|
@@ -54,7 +54,7 @@ export function sdkManagerFactory(settings, splits, _a) {
|
|
|
54
54
|
if (!validateIfOperational(log, readinessManager, SPLIT_FN_LABEL) || !splitName) {
|
|
55
55
|
return isAsync ? Promise.resolve(null) : null;
|
|
56
56
|
}
|
|
57
|
-
var split = splits.
|
|
57
|
+
var split = splits.get(splitName);
|
|
58
58
|
if (thenable(split)) {
|
|
59
59
|
return split.catch(function () { return null; }).then(function (result) {
|
|
60
60
|
validateDefinitionExistence(log, readinessManager, splitName, result, SPLIT_FN_LABEL);
|
|
@@ -83,7 +83,7 @@ export function sdkManagerFactory(settings, splits, _a) {
|
|
|
83
83
|
if (!validateIfOperational(log, readinessManager, NAMES_FN_LABEL)) {
|
|
84
84
|
return isAsync ? Promise.resolve([]) : [];
|
|
85
85
|
}
|
|
86
|
-
var splitNames = splits.
|
|
86
|
+
var splitNames = splits.getNames();
|
|
87
87
|
return thenable(splitNames) ?
|
|
88
88
|
splitNames.catch(function () { return []; }) : // handle possible rejections when using pluggable storage
|
|
89
89
|
splitNames;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { authenticateFactory } from '../sync/streaming/AuthClient';
|
|
2
|
+
import { Backoff } from '../utils/Backoff';
|
|
3
|
+
import { LOG_PREFIX_SYNC_AUTH } from '../logger/constants';
|
|
4
|
+
import { TOKEN } from '../utils/constants';
|
|
5
|
+
var SKEW_SECONDS = 30;
|
|
6
|
+
function isExpired(credential) {
|
|
7
|
+
return Date.now() / 1000 + SKEW_SECONDS >= credential.decodedToken.exp;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Factory of AuthProvider, which provides JWT credentials for authenticated HTTP requests.
|
|
11
|
+
* Credentials are fetched lazily on demand, cached in memory, and retried with backoff on failure.
|
|
12
|
+
*/
|
|
13
|
+
export function authProviderFactory(settings, splitHttpClient, telemetryTracker) {
|
|
14
|
+
var urls = settings.urls, log = settings.log;
|
|
15
|
+
function fetchAuth() {
|
|
16
|
+
var url = "".concat(urls.auth, "/v3/auth?capabilities=config");
|
|
17
|
+
return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN));
|
|
18
|
+
}
|
|
19
|
+
var authenticate = authenticateFactory(fetchAuth);
|
|
20
|
+
var backoff = new Backoff(fetchCredential);
|
|
21
|
+
var cachedCredential;
|
|
22
|
+
var inFlightPromise;
|
|
23
|
+
var stopped = false;
|
|
24
|
+
function fetchCredential() {
|
|
25
|
+
return authenticate().then(function (credential) {
|
|
26
|
+
log.info(LOG_PREFIX_SYNC_AUTH + 'credential fetched successfully');
|
|
27
|
+
cachedCredential = credential;
|
|
28
|
+
inFlightPromise = undefined;
|
|
29
|
+
backoff.reset();
|
|
30
|
+
return credential;
|
|
31
|
+
}).catch(function (error) {
|
|
32
|
+
// Avoid rejected promises and unnecessary retries after stop()
|
|
33
|
+
if (stopped)
|
|
34
|
+
return cachedCredential;
|
|
35
|
+
if (error.statusCode && error.statusCode >= 400 && error.statusCode < 500) {
|
|
36
|
+
log.error(LOG_PREFIX_SYNC_AUTH + 'non-retryable error fetching credential (status ' + error.statusCode + '): ' + error.message);
|
|
37
|
+
inFlightPromise = undefined;
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
log.warn(LOG_PREFIX_SYNC_AUTH + 'credential fetch failed (attempt ' + (backoff.attempts + 1) + '). Error: ' + error.message);
|
|
41
|
+
return backoff.scheduleCallAsync();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
credential: function () {
|
|
46
|
+
if (cachedCredential && !isExpired(cachedCredential)) {
|
|
47
|
+
return Promise.resolve(cachedCredential);
|
|
48
|
+
}
|
|
49
|
+
if (cachedCredential)
|
|
50
|
+
log.debug(LOG_PREFIX_SYNC_AUTH + 'cached credential expired');
|
|
51
|
+
return inFlightPromise || (inFlightPromise = fetchCredential());
|
|
52
|
+
},
|
|
53
|
+
invalidate: function () {
|
|
54
|
+
cachedCredential = undefined;
|
|
55
|
+
},
|
|
56
|
+
stop: function () {
|
|
57
|
+
stopped = true;
|
|
58
|
+
cachedCredential = undefined;
|
|
59
|
+
inFlightPromise = undefined;
|
|
60
|
+
backoff.reset();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { __assign } from "tslib";
|
|
2
|
+
import { splitHttpClientFactory } from './splitHttpClient';
|
|
3
|
+
import { authProviderFactory } from './authProvider';
|
|
4
|
+
/**
|
|
5
|
+
* Factory of Secure HTTP client, which authenticates requests using a JWT token.
|
|
6
|
+
* On 401 responses, invalidates the cached credential and retries once with a fresh token.
|
|
7
|
+
*
|
|
8
|
+
* @param settings - SDK settings
|
|
9
|
+
* @param platform - object containing environment-specific dependencies
|
|
10
|
+
* @param fetchAuth - function to fetch auth credentials from the /v2/auth endpoint
|
|
11
|
+
*/
|
|
12
|
+
export function secureSplitHttpClientFactory(settings, platform, telemetryTracker) {
|
|
13
|
+
var splitHttpClient = splitHttpClientFactory(settings, platform);
|
|
14
|
+
var authProvider = authProviderFactory(settings, splitHttpClient, telemetryTracker);
|
|
15
|
+
function makeRequest(url, options, latencyTracker, logErrorsAsInfo, token) {
|
|
16
|
+
return splitHttpClient(url, __assign(__assign({}, options), { headers: __assign(__assign({}, options === null || options === void 0 ? void 0 : options.headers), { Authorization: "Bearer ".concat(token) }) }), latencyTracker, logErrorsAsInfo);
|
|
17
|
+
}
|
|
18
|
+
var httpClient = function (url, options, latencyTracker, logErrorsAsInfo) {
|
|
19
|
+
return authProvider.credential().then(function (credential) {
|
|
20
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, credential.token)
|
|
21
|
+
.catch(function (error) {
|
|
22
|
+
if (error.statusCode === 401) {
|
|
23
|
+
// retry once for 401, in case the token has just expired
|
|
24
|
+
authProvider.invalidate();
|
|
25
|
+
return authProvider.credential().then(function (newCredential) {
|
|
26
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newCredential.token);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
throw error;
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
httpClient.stop = function () { return authProvider.stop(); };
|
|
34
|
+
return httpClient;
|
|
35
|
+
}
|
package/esm/services/splitApi.js
CHANGED
|
@@ -13,11 +13,12 @@ function userKeyToQueryParam(userKey) {
|
|
|
13
13
|
* @param platform - object containing environment-specific dependencies
|
|
14
14
|
* @param telemetryTracker - telemetry tracker
|
|
15
15
|
*/
|
|
16
|
-
export function splitApiFactory(settings, platform, telemetryTracker) {
|
|
16
|
+
export function splitApiFactory(settings, platform, telemetryTracker, secureSplitHttpClientFactory) {
|
|
17
17
|
var urls = settings.urls;
|
|
18
18
|
var filterQueryString = settings.sync.__splitFiltersValidation && settings.sync.__splitFiltersValidation.queryString;
|
|
19
19
|
var SplitSDKImpressionsMode = settings.sync.impressionsMode;
|
|
20
20
|
var splitHttpClient = splitHttpClientFactory(settings, platform);
|
|
21
|
+
var secureSplitHttpClient = secureSplitHttpClientFactory ? secureSplitHttpClientFactory(settings, platform, telemetryTracker) : undefined;
|
|
21
22
|
return {
|
|
22
23
|
// @TODO throw errors if health check requests fail, to log them in the Synchronizer
|
|
23
24
|
getSdkAPIHealthCheck: function () {
|
|
@@ -49,7 +50,7 @@ export function splitApiFactory(settings, platform, telemetryTracker) {
|
|
|
49
50
|
// @TODO support filterQueryString and handle ERROR_TOO_MANY_SETS error
|
|
50
51
|
fetchConfigs: function (since, noCache, till) {
|
|
51
52
|
var url = "".concat(urls.sdk, "/v1/configs?since=").concat(since).concat(filterQueryString || '').concat(till ? '&till=' + till : '');
|
|
52
|
-
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined);
|
|
53
|
+
return (secureSplitHttpClient || splitHttpClient)(url, noCache ? noCacheHeaderOptions : undefined);
|
|
53
54
|
},
|
|
54
55
|
fetchSegmentChanges: function (since, segmentName, noCache, till) {
|
|
55
56
|
var url = "".concat(urls.sdk, "/segmentChanges/").concat(segmentName, "?since=").concat(since).concat(till ? '&till=' + till : '');
|
|
@@ -127,6 +128,10 @@ export function splitApiFactory(settings, platform, telemetryTracker) {
|
|
|
127
128
|
postMetricsUsage: function (body, headers) {
|
|
128
129
|
var url = "".concat(urls.telemetry, "/v1/metrics/usage");
|
|
129
130
|
return splitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(TELEMETRY), true);
|
|
131
|
+
},
|
|
132
|
+
stop: function () {
|
|
133
|
+
if (secureSplitHttpClient)
|
|
134
|
+
secureSplitHttpClient.stop();
|
|
130
135
|
}
|
|
131
136
|
};
|
|
132
137
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
|
+
/**
|
|
3
|
+
* This class provides a skeletal implementation of the IDefinitionsCacheAsync interface
|
|
4
|
+
* to minimize the effort required to implement this interface.
|
|
5
|
+
*/
|
|
6
|
+
var AbstractDefinitionsCacheAsync = /** @class */ (function () {
|
|
7
|
+
function AbstractDefinitionsCacheAsync() {
|
|
8
|
+
}
|
|
9
|
+
AbstractDefinitionsCacheAsync.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
10
|
+
var _this = this;
|
|
11
|
+
return Promise.all([
|
|
12
|
+
this.setChangeNumber(changeNumber),
|
|
13
|
+
Promise.all(toAdd.map(function (addedFF) { return _this.add(addedFF); })),
|
|
14
|
+
Promise.all(toRemove.map(function (removedFF) { return _this.remove(removedFF); }))
|
|
15
|
+
]).then(function (_a) {
|
|
16
|
+
var added = _a[1], removed = _a[2];
|
|
17
|
+
return added.some(function (result) { return result; }) || removed.some(function (result) { return result; });
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
// @TODO revisit segment-related methods ('usesSegments', 'getRegisteredSegments', 'registerSegments')
|
|
21
|
+
// noop, just keeping the interface. This is used by standalone client-side API only, and so only implemented by InMemory and InLocalStorage.
|
|
22
|
+
AbstractDefinitionsCacheAsync.prototype.usesSegments = function () {
|
|
23
|
+
return Promise.resolve(true);
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Kill `name` definition and set `defaultTreatment` and `changeNumber`.
|
|
27
|
+
* Used for SPLIT_KILL push notifications.
|
|
28
|
+
*
|
|
29
|
+
* @returns a promise that is resolved once the definition kill operation is performed. The fulfillment value is a boolean: `true` if the operation succeeded updating the definition or `false` if no definition is updated,
|
|
30
|
+
* for instance, if the `changeNumber` is old, or if the definition is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
|
|
31
|
+
* The promise will never be rejected.
|
|
32
|
+
*/
|
|
33
|
+
AbstractDefinitionsCacheAsync.prototype.killLocally = function (name, defaultTreatment, changeNumber) {
|
|
34
|
+
var _this = this;
|
|
35
|
+
return this.get(name).then(function (definition) {
|
|
36
|
+
if (definition && (!definition.changeNumber || definition.changeNumber < changeNumber)) {
|
|
37
|
+
var newDefinition = objectAssign({}, definition);
|
|
38
|
+
newDefinition.killed = true;
|
|
39
|
+
newDefinition.defaultTreatment = defaultTreatment;
|
|
40
|
+
newDefinition.changeNumber = changeNumber;
|
|
41
|
+
return _this.add(newDefinition);
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
}).catch(function () { return false; });
|
|
45
|
+
};
|
|
46
|
+
return AbstractDefinitionsCacheAsync;
|
|
47
|
+
}());
|
|
48
|
+
export { AbstractDefinitionsCacheAsync };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
|
+
import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
|
|
3
|
+
/**
|
|
4
|
+
* This class provides a skeletal implementation of the IDefinitionsCacheSync interface
|
|
5
|
+
* to minimize the effort required to implement this interface.
|
|
6
|
+
*/
|
|
7
|
+
var AbstractDefinitionsCacheSync = /** @class */ (function () {
|
|
8
|
+
function AbstractDefinitionsCacheSync() {
|
|
9
|
+
}
|
|
10
|
+
AbstractDefinitionsCacheSync.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
11
|
+
var _this = this;
|
|
12
|
+
var updated = toAdd.map(function (addedFF) { return _this.add(addedFF); }).some(function (result) { return result; });
|
|
13
|
+
updated = toRemove.map(function (removedFF) { return _this.remove(removedFF); }).some(function (result) { return result; }) || updated;
|
|
14
|
+
this.setChangeNumber(changeNumber);
|
|
15
|
+
return updated;
|
|
16
|
+
};
|
|
17
|
+
AbstractDefinitionsCacheSync.prototype.getMany = function (names) {
|
|
18
|
+
var _this = this;
|
|
19
|
+
var definitions = {};
|
|
20
|
+
names.forEach(function (name) {
|
|
21
|
+
definitions[name] = _this.get(name);
|
|
22
|
+
});
|
|
23
|
+
return definitions;
|
|
24
|
+
};
|
|
25
|
+
AbstractDefinitionsCacheSync.prototype.getAll = function () {
|
|
26
|
+
var _this = this;
|
|
27
|
+
return this.getNames().map(function (key) { return _this.get(key); });
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Kill `name` definition and set `defaultTreatment` and `changeNumber`.
|
|
31
|
+
* Used for SPLIT_KILL push notifications.
|
|
32
|
+
*
|
|
33
|
+
* @returns `true` if the operation successed updating the definition, or `false` if no definition is updated,
|
|
34
|
+
* for instance, if the `changeNumber` is old, or if the definition is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
|
|
35
|
+
*/
|
|
36
|
+
AbstractDefinitionsCacheSync.prototype.killLocally = function (name, defaultTreatment, changeNumber) {
|
|
37
|
+
var definition = this.get(name);
|
|
38
|
+
if (definition && (!definition.changeNumber || definition.changeNumber < changeNumber)) {
|
|
39
|
+
var newDefinition = objectAssign({}, definition);
|
|
40
|
+
newDefinition.killed = true;
|
|
41
|
+
newDefinition.defaultTreatment = defaultTreatment;
|
|
42
|
+
newDefinition.changeNumber = changeNumber;
|
|
43
|
+
return this.add(newDefinition);
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
};
|
|
47
|
+
return AbstractDefinitionsCacheSync;
|
|
48
|
+
}());
|
|
49
|
+
export { AbstractDefinitionsCacheSync };
|
|
50
|
+
/**
|
|
51
|
+
* Given a parsed definition, it returns a boolean flagging if its conditions use segments matchers (rules & whitelists).
|
|
52
|
+
* This util is intended to simplify the implementation of `definitionsCache::usesSegments` method
|
|
53
|
+
*/
|
|
54
|
+
export function usesSegments(ruleEntity) {
|
|
55
|
+
var conditions = ruleEntity.conditions || [];
|
|
56
|
+
for (var i = 0; i < conditions.length; i++) {
|
|
57
|
+
var matchers = conditions[i].matcherGroup.matchers;
|
|
58
|
+
for (var j = 0; j < matchers.length; j++) {
|
|
59
|
+
var matcher = matchers[j].matcherType;
|
|
60
|
+
if (matcher === IN_SEGMENT || matcher === IN_LARGE_SEGMENT)
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
var excluded = ruleEntity.excluded;
|
|
65
|
+
if (excluded && excluded.segments && excluded.segments.length > 0)
|
|
66
|
+
return true;
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
export function usesSegmentsSync(storage) {
|
|
70
|
+
return storage.definitions.usesSegments() || storage.rbSegments.usesSegments();
|
|
71
|
+
}
|
|
@@ -12,16 +12,16 @@ var KeyBuilder = /** @class */ (function () {
|
|
|
12
12
|
KeyBuilder.prototype.buildTrafficTypeKey = function (trafficType) {
|
|
13
13
|
return "".concat(this.prefix, ".trafficType.").concat(trafficType);
|
|
14
14
|
};
|
|
15
|
-
KeyBuilder.prototype.
|
|
16
|
-
return "".concat(this.prefix, ".flagSet.").concat(
|
|
15
|
+
KeyBuilder.prototype.buildSetKey = function (set) {
|
|
16
|
+
return "".concat(this.prefix, ".flagSet.").concat(set);
|
|
17
17
|
};
|
|
18
|
-
KeyBuilder.prototype.
|
|
19
|
-
return "".concat(this.prefix, ".split.").concat(
|
|
18
|
+
KeyBuilder.prototype.buildDefinitionKey = function (definitionName) {
|
|
19
|
+
return "".concat(this.prefix, ".split.").concat(definitionName);
|
|
20
20
|
};
|
|
21
|
-
KeyBuilder.prototype.
|
|
21
|
+
KeyBuilder.prototype.buildDefinitionsTillKey = function () {
|
|
22
22
|
return "".concat(this.prefix, ".splits.till");
|
|
23
23
|
};
|
|
24
|
-
KeyBuilder.prototype.
|
|
24
|
+
KeyBuilder.prototype.buildDefinitionKeyPrefix = function () {
|
|
25
25
|
return "".concat(this.prefix, ".split.");
|
|
26
26
|
};
|
|
27
27
|
KeyBuilder.prototype.buildRBSegmentKey = function (rbsegmentName) {
|
|
@@ -6,7 +6,7 @@ var KeyBuilderCS = /** @class */ (function (_super) {
|
|
|
6
6
|
function KeyBuilderCS(prefix, matchingKey) {
|
|
7
7
|
var _this = _super.call(this, prefix) || this;
|
|
8
8
|
_this.matchingKey = matchingKey;
|
|
9
|
-
_this.
|
|
9
|
+
_this.regexDefinitionsCacheKey = new RegExp("^".concat(prefix, "\\.(splits?|trafficType|flagSet)\\."));
|
|
10
10
|
return _this;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
@@ -23,19 +23,19 @@ var KeyBuilderCS = /** @class */ (function (_super) {
|
|
|
23
23
|
KeyBuilderCS.prototype.buildLastUpdatedKey = function () {
|
|
24
24
|
return "".concat(this.prefix, ".splits.lastUpdated");
|
|
25
25
|
};
|
|
26
|
-
KeyBuilderCS.prototype.
|
|
27
|
-
return this.
|
|
26
|
+
KeyBuilderCS.prototype.isDefinitionsCacheKey = function (key) {
|
|
27
|
+
return this.regexDefinitionsCacheKey.test(key);
|
|
28
28
|
};
|
|
29
29
|
KeyBuilderCS.prototype.buildTillKey = function () {
|
|
30
30
|
return "".concat(this.prefix, ".").concat(this.matchingKey, ".segments.till");
|
|
31
31
|
};
|
|
32
|
-
KeyBuilderCS.prototype.
|
|
32
|
+
KeyBuilderCS.prototype.isDefinitionKey = function (key) {
|
|
33
33
|
return startsWith(key, "".concat(this.prefix, ".split."));
|
|
34
34
|
};
|
|
35
35
|
KeyBuilderCS.prototype.isRBSegmentKey = function (key) {
|
|
36
36
|
return startsWith(key, "".concat(this.prefix, ".rbsegment."));
|
|
37
37
|
};
|
|
38
|
-
KeyBuilderCS.prototype.
|
|
38
|
+
KeyBuilderCS.prototype.buildDefinitionsWithSegmentCountKey = function () {
|
|
39
39
|
return "".concat(this.prefix, ".splits.usingSegments");
|
|
40
40
|
};
|
|
41
41
|
KeyBuilderCS.prototype.buildLastClear = function () {
|
|
@@ -36,8 +36,8 @@ var KeyBuilderSS = /** @class */ (function (_super) {
|
|
|
36
36
|
KeyBuilderSS.prototype.buildEventsKey = function () {
|
|
37
37
|
return "".concat(this.prefix, ".events");
|
|
38
38
|
};
|
|
39
|
-
KeyBuilderSS.prototype.
|
|
40
|
-
return "".concat(this.
|
|
39
|
+
KeyBuilderSS.prototype.searchPatternForDefinitionKeys = function () {
|
|
40
|
+
return "".concat(this.buildDefinitionKeyPrefix(), "*");
|
|
41
41
|
};
|
|
42
42
|
KeyBuilderSS.prototype.searchPatternForRBSegmentKeys = function () {
|
|
43
43
|
return "".concat(this.buildRBSegmentKeyPrefix(), "*");
|