@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
|
@@ -6,17 +6,17 @@ import { Backoff } from '../../utils/Backoff';
|
|
|
6
6
|
import { SSEHandlerFactory } from './SSEHandler';
|
|
7
7
|
import { MySegmentsUpdateWorker } from './UpdateWorkers/MySegmentsUpdateWorker';
|
|
8
8
|
import { SegmentsUpdateWorker } from './UpdateWorkers/SegmentsUpdateWorker';
|
|
9
|
-
import {
|
|
9
|
+
import { DefinitionsUpdateWorker } from './UpdateWorkers/DefinitionsUpdateWorker';
|
|
10
10
|
import { authenticateFactory, hashUserKey } from './AuthClient';
|
|
11
11
|
import { forOwn } from '../../utils/lang';
|
|
12
12
|
import { SSEClient } from './SSEClient';
|
|
13
13
|
import { checkIfServerSide, getMatching } from '../../utils/key';
|
|
14
|
-
import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE,
|
|
14
|
+
import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NON_RETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, RB_SEGMENT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
|
|
15
15
|
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE } from '../../logger/constants';
|
|
16
16
|
import { IMembershipMSUpdateData, IMembershipLSUpdateData, KeyList, UpdateStrategy } from './SSEHandler/types';
|
|
17
17
|
import { getDelay, isInBitmap, parseBitmap, parseCompressedData } from './parseUtils';
|
|
18
18
|
import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
|
|
19
|
-
import {
|
|
19
|
+
import { IJwtCredentialV2 } from './AuthClient/types';
|
|
20
20
|
import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
|
|
21
21
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
22
22
|
|
|
@@ -55,8 +55,8 @@ export function pushManagerFactory(
|
|
|
55
55
|
// init workers
|
|
56
56
|
// MySegmentsUpdateWorker (client-side) are initiated in `add` method
|
|
57
57
|
const segmentsUpdateWorker = userKey ? undefined : SegmentsUpdateWorker(log, pollingManager.segmentsSyncTask as ISegmentsSyncTask, storage.segments);
|
|
58
|
-
// For server-side we pass the segmentsSyncTask, used by
|
|
59
|
-
const
|
|
58
|
+
// For server-side we pass the segmentsSyncTask, used by DefinitionsUpdateWorker to fetch new segments
|
|
59
|
+
const definitionsUpdateWorker = DefinitionsUpdateWorker(log, storage, pollingManager.definitionsSyncTask, readiness.definitions, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
|
|
60
60
|
|
|
61
61
|
// [Only for client-side] map of hashes to user keys, to dispatch membership update events to the corresponding MySegmentsUpdateWorker
|
|
62
62
|
const userKeyHashes: Record<string, string> = {};
|
|
@@ -67,10 +67,10 @@ export function pushManagerFactory(
|
|
|
67
67
|
// [Only for client-side] variable to flag that a new client was added. It is needed to reconnect streaming.
|
|
68
68
|
let connectForNewClient = false;
|
|
69
69
|
|
|
70
|
-
// flag that indicates if `stop/disconnectPush` was called, either by the SyncManager, when the client is destroyed, or due to a
|
|
70
|
+
// flag that indicates if `stop/disconnectPush` was called, either by the SyncManager, when the client is destroyed, or due to a PUSH_NON_RETRYABLE_ERROR error.
|
|
71
71
|
// It is used to halt the `connectPush` process if it was in progress.
|
|
72
72
|
let disconnected: boolean | undefined;
|
|
73
|
-
// flag that indicates a
|
|
73
|
+
// flag that indicates a PUSH_NON_RETRYABLE_ERROR, condition with which starting pushManager again is ignored.
|
|
74
74
|
// true if STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE or Auth errors.
|
|
75
75
|
let disabled: boolean | undefined; // `disabled` implies `disconnected === true`
|
|
76
76
|
|
|
@@ -81,7 +81,7 @@ export function pushManagerFactory(
|
|
|
81
81
|
let timeoutIdTokenRefresh: ReturnType<typeof setTimeout>;
|
|
82
82
|
let timeoutIdSseOpen: ReturnType<typeof setTimeout>;
|
|
83
83
|
|
|
84
|
-
function scheduleTokenRefreshAndSse(authData:
|
|
84
|
+
function scheduleTokenRefreshAndSse(authData: IJwtCredentialV2) {
|
|
85
85
|
// clear scheduled tasks if exist
|
|
86
86
|
if (timeoutIdTokenRefresh) clearTimeout(timeoutIdTokenRefresh);
|
|
87
87
|
if (timeoutIdSseOpen) clearTimeout(timeoutIdSseOpen);
|
|
@@ -117,11 +117,11 @@ export function pushManagerFactory(
|
|
|
117
117
|
function (authData) {
|
|
118
118
|
if (disconnected) return;
|
|
119
119
|
|
|
120
|
-
// 'pushEnabled: false' is handled as a
|
|
120
|
+
// 'pushEnabled: false' is handled as a PUSH_NON_RETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
|
|
121
121
|
// close the sseClient in case the org has been bloqued while the instance was connected to streaming
|
|
122
122
|
if (!authData.pushEnabled) {
|
|
123
123
|
log.info(STREAMING_DISABLED);
|
|
124
|
-
pushEmitter.emit(
|
|
124
|
+
pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -140,7 +140,7 @@ export function pushManagerFactory(
|
|
|
140
140
|
// Handle 4XX HTTP errors: 401 (invalid SDK Key) or 400 (using incorrect SDK Key, i.e., client-side SDK Key on server-side)
|
|
141
141
|
if (error.statusCode >= 400 && error.statusCode < 500) {
|
|
142
142
|
telemetryTracker.streamingEvent(AUTH_REJECTION);
|
|
143
|
-
pushEmitter.emit(
|
|
143
|
+
pushEmitter.emit(PUSH_NON_RETRYABLE_ERROR);
|
|
144
144
|
return;
|
|
145
145
|
}
|
|
146
146
|
|
|
@@ -168,7 +168,7 @@ export function pushManagerFactory(
|
|
|
168
168
|
|
|
169
169
|
// cancel scheduled fetch retries of Splits, Segments, and MySegments Update Workers
|
|
170
170
|
function stopWorkers() {
|
|
171
|
-
|
|
171
|
+
definitionsUpdateWorker.stop();
|
|
172
172
|
if (userKey) forOwn(clients, ({ worker }) => worker.stop());
|
|
173
173
|
else segmentsUpdateWorker!.stop();
|
|
174
174
|
}
|
|
@@ -183,7 +183,7 @@ export function pushManagerFactory(
|
|
|
183
183
|
|
|
184
184
|
/** Fallback to polling without retry due to: STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE and Authentication errors */
|
|
185
185
|
|
|
186
|
-
pushEmitter.on(
|
|
186
|
+
pushEmitter.on(PUSH_NON_RETRYABLE_ERROR, function handleNonRetryableError() {
|
|
187
187
|
disabled = true;
|
|
188
188
|
// Note: `stopWorkers` is been called twice, but it is not harmful
|
|
189
189
|
disconnectPush();
|
|
@@ -218,9 +218,9 @@ export function pushManagerFactory(
|
|
|
218
218
|
|
|
219
219
|
/** Functions related to synchronization (Queues and Workers in the spec) */
|
|
220
220
|
|
|
221
|
-
pushEmitter.on(SPLIT_KILL,
|
|
222
|
-
pushEmitter.on(SPLIT_UPDATE,
|
|
223
|
-
pushEmitter.on(RB_SEGMENT_UPDATE,
|
|
221
|
+
pushEmitter.on(SPLIT_KILL, definitionsUpdateWorker.killDefinition);
|
|
222
|
+
pushEmitter.on(SPLIT_UPDATE, definitionsUpdateWorker.put);
|
|
223
|
+
pushEmitter.on(RB_SEGMENT_UPDATE, definitionsUpdateWorker.put);
|
|
224
224
|
|
|
225
225
|
function handleMySegmentsUpdate(parsedData: IMembershipMSUpdateData | IMembershipLSUpdateData) {
|
|
226
226
|
switch (parsedData.u) {
|
|
@@ -7,7 +7,7 @@ import { ControlType } from './constants';
|
|
|
7
7
|
// Internal SDK events, subscribed by SyncManager and PushManager
|
|
8
8
|
export type PUSH_SUBSYSTEM_UP = 'PUSH_SUBSYSTEM_UP'
|
|
9
9
|
export type PUSH_SUBSYSTEM_DOWN = 'PUSH_SUBSYSTEM_DOWN'
|
|
10
|
-
export type
|
|
10
|
+
export type PUSH_NON_RETRYABLE_ERROR = 'PUSH_NON_RETRYABLE_ERROR'
|
|
11
11
|
export type PUSH_RETRYABLE_ERROR = 'PUSH_RETRYABLE_ERROR'
|
|
12
12
|
|
|
13
13
|
// Update-type push notifications, handled by NotificationProcessor
|
|
@@ -22,7 +22,7 @@ export type RB_SEGMENT_UPDATE = 'RB_SEGMENT_UPDATE';
|
|
|
22
22
|
export type CONTROL = 'CONTROL';
|
|
23
23
|
export type OCCUPANCY = 'OCCUPANCY';
|
|
24
24
|
|
|
25
|
-
export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN |
|
|
25
|
+
export type IPushEvent = PUSH_SUBSYSTEM_UP | PUSH_SUBSYSTEM_DOWN | PUSH_NON_RETRYABLE_ERROR | PUSH_RETRYABLE_ERROR | MEMBERSHIPS_MS_UPDATE | MEMBERSHIPS_LS_UPDATE | SEGMENT_UPDATE | SPLIT_UPDATE | SPLIT_KILL | RB_SEGMENT_UPDATE | ControlType.STREAMING_RESET
|
|
26
26
|
|
|
27
27
|
type IParsedData<T extends IPushEvent> =
|
|
28
28
|
T extends MEMBERSHIPS_MS_UPDATE ? IMembershipMSUpdateData :
|
|
@@ -119,7 +119,7 @@ export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
|
|
|
119
119
|
const { storage: { telemetry }, platform: { now } } = params;
|
|
120
120
|
if (!telemetry || !now) return; // No submitter created if telemetry cache is not defined
|
|
121
121
|
|
|
122
|
-
const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, readiness
|
|
122
|
+
const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, readiness } = params;
|
|
123
123
|
const stopTimer = timer(now);
|
|
124
124
|
|
|
125
125
|
const submitter = firstPushWindowDecorator(
|
|
@@ -135,7 +135,6 @@ export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
|
|
|
135
135
|
telemetry.recordTimeUntilReadyFromCache(stopTimer());
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
-
sdkReadinessManager.incInternalReadyCbCount();
|
|
139
138
|
readiness.gate.once(SDK_READY, () => {
|
|
140
139
|
telemetry.recordTimeUntilReady(stopTimer());
|
|
141
140
|
|
|
@@ -9,8 +9,8 @@ import { SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING } from '..
|
|
|
9
9
|
import { isConsentGranted } from '../consent';
|
|
10
10
|
import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
|
|
11
11
|
import { ISdkFactoryContextSync } from '../sdkFactory/types';
|
|
12
|
-
import {
|
|
13
|
-
import { usesSegmentsSync } from '../storages/
|
|
12
|
+
import { SDK_DEFINITIONS_CACHE_LOADED } from '../readiness/constants';
|
|
13
|
+
import { usesSegmentsSync } from '../storages/AbstractDefinitionsCacheSync';
|
|
14
14
|
import { splitChangesFetcherFactory } from './polling/fetchers/splitChangesFetcher';
|
|
15
15
|
import { IDefinitionChangesFetcher } from './polling/fetchers/types';
|
|
16
16
|
|
|
@@ -102,7 +102,7 @@ export function syncManagerOnlineFactory(
|
|
|
102
102
|
if (startFirstTime) {
|
|
103
103
|
// Emits SDK_READY_FROM_CACHE
|
|
104
104
|
if (!cacheMetadata.initialCacheLoad) {
|
|
105
|
-
readiness.
|
|
105
|
+
readiness.definitions.emit(SDK_DEFINITIONS_CACHE_LOADED, cacheMetadata);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
}
|
package/src/utils/Backoff.ts
CHANGED
|
@@ -40,6 +40,27 @@ export class Backoff {
|
|
|
40
40
|
return delayInMillis;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Schedule a delayed call to `cb`
|
|
45
|
+
* @returns a promise that resolves/rejects with the result of the `cb` function, which must return a promise.
|
|
46
|
+
*/
|
|
47
|
+
scheduleCallAsync<T>(): Promise<T> {
|
|
48
|
+
const delayInMillis = Math.min(this.baseMillis * Math.pow(2, this.attempts), this.maxMillis);
|
|
49
|
+
|
|
50
|
+
if (this.timeoutID) clearTimeout(this.timeoutID);
|
|
51
|
+
this.attempts++;
|
|
52
|
+
|
|
53
|
+
return new Promise<T>((resolve, reject) => {
|
|
54
|
+
this.timeoutID = setTimeout(() => {
|
|
55
|
+
this.timeoutID = undefined;
|
|
56
|
+
this.cb().then(resolve, reject);
|
|
57
|
+
}, delayInMillis);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Reset the backoff attempts
|
|
63
|
+
*/
|
|
43
64
|
reset() {
|
|
44
65
|
this.attempts = 0;
|
|
45
66
|
if (this.timeoutID) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { thenable } from '../promise/thenable';
|
|
2
2
|
import { LOCALHOST_MODE } from '../constants';
|
|
3
|
-
import {
|
|
3
|
+
import { IDefinitionsCacheBase } from '../../storages/types';
|
|
4
4
|
import { IReadinessManager } from '../../readiness/types';
|
|
5
5
|
import SplitIO from '../../../types/splitio';
|
|
6
6
|
import { MaybeThenable } from '../../dtos/types';
|
|
@@ -14,7 +14,7 @@ function logTTExistenceWarning(log: ILogger, maybeTT: string, method: string) {
|
|
|
14
14
|
/**
|
|
15
15
|
* Separated from the previous method since on some cases it'll be async.
|
|
16
16
|
*/
|
|
17
|
-
export function validateTrafficTypeExistence(log: ILogger, readinessManager: IReadinessManager, splitsCache:
|
|
17
|
+
export function validateTrafficTypeExistence(log: ILogger, readinessManager: IReadinessManager, splitsCache: IDefinitionsCacheBase, mode: SplitIO.SDKMode, maybeTT: string, method: string): MaybeThenable<boolean> {
|
|
18
18
|
|
|
19
19
|
// If not ready or in localhost mode, we won't run the validation
|
|
20
20
|
if (!readinessManager.isReady() || mode === LOCALHOST_MODE) return true;
|
package/src/utils/jwt/types.ts
CHANGED
package/src/utils/lang/sets.ts
CHANGED
|
@@ -12,6 +12,8 @@ export function returnSetsUnion<T>(set: Set<T>, set2: Set<T>): Set<T> {
|
|
|
12
12
|
return new Set(setToArray(set).concat(setToArray(set2)));
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export function returnDifference<T>(
|
|
16
|
-
|
|
15
|
+
export function returnDifference<T>(list1?: T[] | null, list2?: T[] | null): T[] {
|
|
16
|
+
list1 = list1 || [];
|
|
17
|
+
list2 = list2 || [];
|
|
18
|
+
return list1.filter(item => list2!.indexOf(item) === -1);
|
|
17
19
|
}
|
|
@@ -2,7 +2,7 @@ import { ISettings } from '../../types';
|
|
|
2
2
|
|
|
3
3
|
const telemetryEndpointMatcher = /^\/v1\/metrics\/(config|usage)/;
|
|
4
4
|
const eventsEndpointMatcher = /^\/(testImpressions|metrics|events)/;
|
|
5
|
-
const authEndpointMatcher = /^\/v2\/auth/;
|
|
5
|
+
const authEndpointMatcher = /^\/(v2|v3)\/auth/;
|
|
6
6
|
const streamingEndpointMatcher = /^\/(sse|event-stream)/;
|
|
7
7
|
|
|
8
8
|
/**
|
package/types/splitio.d.ts
CHANGED
|
@@ -495,7 +495,7 @@ declare namespace SplitIO {
|
|
|
495
495
|
}
|
|
496
496
|
|
|
497
497
|
/**
|
|
498
|
-
* Metadata for the update event emitted when the SDK cache is updated with new data for flags or segments.
|
|
498
|
+
* Metadata for the update event emitted when the SDK cache is updated with new data for flags, configs, or segments.
|
|
499
499
|
*/
|
|
500
500
|
type SdkUpdateMetadata = {
|
|
501
501
|
/**
|
|
@@ -503,7 +503,7 @@ declare namespace SplitIO {
|
|
|
503
503
|
*/
|
|
504
504
|
type: SdkUpdateMetadataType;
|
|
505
505
|
/**
|
|
506
|
-
* The names of the flags or
|
|
506
|
+
* The names of the flags or configs that were updated. Empty array if the update is of type 'SEGMENTS_UPDATE'.
|
|
507
507
|
*/
|
|
508
508
|
names: string[];
|
|
509
509
|
}
|
|
@@ -2316,11 +2316,23 @@ declare namespace SplitIO {
|
|
|
2316
2316
|
*/
|
|
2317
2317
|
authorizationKey: string;
|
|
2318
2318
|
/**
|
|
2319
|
-
*
|
|
2319
|
+
* Polling rate for configs and segments refresh, in seconds. Minimum value: 5.
|
|
2320
2320
|
*
|
|
2321
2321
|
* @defaultValue `60`
|
|
2322
2322
|
*/
|
|
2323
|
-
|
|
2323
|
+
pollingRate?: number;
|
|
2324
|
+
/**
|
|
2325
|
+
* Push rate for events and impressions, in seconds. Minimum value: 60.
|
|
2326
|
+
*
|
|
2327
|
+
* @defaultValue `60`
|
|
2328
|
+
*/
|
|
2329
|
+
pushRate?: number;
|
|
2330
|
+
/**
|
|
2331
|
+
* Maximum queue size for events and impressions. When the queue reaches this size, a flush is triggered. Minimum value: 1000.
|
|
2332
|
+
*
|
|
2333
|
+
* @defaultValue `10000`
|
|
2334
|
+
*/
|
|
2335
|
+
queueSize?: number;
|
|
2324
2336
|
/**
|
|
2325
2337
|
* Logging level.
|
|
2326
2338
|
*
|
|
@@ -2337,6 +2349,12 @@ declare namespace SplitIO {
|
|
|
2337
2349
|
* Custom endpoints to replace the default ones used by the SDK.
|
|
2338
2350
|
*/
|
|
2339
2351
|
urls?: {
|
|
2352
|
+
/**
|
|
2353
|
+
* String property to override the base URL where the SDK will get JWT authentication credentials.
|
|
2354
|
+
*
|
|
2355
|
+
* @defaultValue `'https://auth.split.io/api'`
|
|
2356
|
+
*/
|
|
2357
|
+
auth?: string;
|
|
2340
2358
|
/**
|
|
2341
2359
|
* String property to override the base URL where the SDK will get rollout plan related data, like feature flags and segments definitions.
|
|
2342
2360
|
*
|
|
@@ -2449,7 +2467,7 @@ declare namespace SplitIO {
|
|
|
2449
2467
|
/**
|
|
2450
2468
|
* Configs SDK client interface.
|
|
2451
2469
|
*/
|
|
2452
|
-
interface ConfigsClient extends IStatusInterface {
|
|
2470
|
+
interface ConfigsClient extends Omit<IStatusInterface, 'ready'> {
|
|
2453
2471
|
/**
|
|
2454
2472
|
* Destroys the client.
|
|
2455
2473
|
*
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AbstractSplitsCacheAsync = void 0;
|
|
4
|
-
var objectAssign_1 = require("../utils/lang/objectAssign");
|
|
5
|
-
/**
|
|
6
|
-
* This class provides a skeletal implementation of the ISplitsCacheAsync interface
|
|
7
|
-
* to minimize the effort required to implement this interface.
|
|
8
|
-
*/
|
|
9
|
-
var AbstractSplitsCacheAsync = /** @class */ (function () {
|
|
10
|
-
function AbstractSplitsCacheAsync() {
|
|
11
|
-
}
|
|
12
|
-
AbstractSplitsCacheAsync.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
13
|
-
var _this = this;
|
|
14
|
-
return Promise.all([
|
|
15
|
-
this.setChangeNumber(changeNumber),
|
|
16
|
-
Promise.all(toAdd.map(function (addedFF) { return _this.addSplit(addedFF); })),
|
|
17
|
-
Promise.all(toRemove.map(function (removedFF) { return _this.removeSplit(removedFF); }))
|
|
18
|
-
]).then(function (_a) {
|
|
19
|
-
var added = _a[1], removed = _a[2];
|
|
20
|
-
return added.some(function (result) { return result; }) || removed.some(function (result) { return result; });
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
|
-
// @TODO revisit segment-related methods ('usesSegments', 'getRegisteredSegments', 'registerSegments')
|
|
24
|
-
// noop, just keeping the interface. This is used by standalone client-side API only, and so only implemented by InMemory and InLocalStorage.
|
|
25
|
-
AbstractSplitsCacheAsync.prototype.usesSegments = function () {
|
|
26
|
-
return Promise.resolve(true);
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
30
|
-
* Used for SPLIT_KILL push notifications.
|
|
31
|
-
*
|
|
32
|
-
* @returns a promise that is resolved once the split kill operation is performed. The fulfillment value is a boolean: `true` if the operation successed updating the split or `false` if no split is updated,
|
|
33
|
-
* for instance, if the `changeNumber` is old, or if the split is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
|
|
34
|
-
* The promise will never be rejected.
|
|
35
|
-
*/
|
|
36
|
-
AbstractSplitsCacheAsync.prototype.killLocally = function (name, defaultTreatment, changeNumber) {
|
|
37
|
-
var _this = this;
|
|
38
|
-
return this.getSplit(name).then(function (split) {
|
|
39
|
-
if (split && (!split.changeNumber || split.changeNumber < changeNumber)) {
|
|
40
|
-
var newSplit = (0, objectAssign_1.objectAssign)({}, split);
|
|
41
|
-
newSplit.killed = true;
|
|
42
|
-
newSplit.defaultTreatment = defaultTreatment;
|
|
43
|
-
newSplit.changeNumber = changeNumber;
|
|
44
|
-
return _this.addSplit(newSplit);
|
|
45
|
-
}
|
|
46
|
-
return false;
|
|
47
|
-
}).catch(function () { return false; });
|
|
48
|
-
};
|
|
49
|
-
return AbstractSplitsCacheAsync;
|
|
50
|
-
}());
|
|
51
|
-
exports.AbstractSplitsCacheAsync = AbstractSplitsCacheAsync;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.usesSegmentsSync = exports.usesSegments = exports.AbstractSplitsCacheSync = void 0;
|
|
4
|
-
var objectAssign_1 = require("../utils/lang/objectAssign");
|
|
5
|
-
var constants_1 = require("../utils/constants");
|
|
6
|
-
/**
|
|
7
|
-
* This class provides a skeletal implementation of the ISplitsCacheSync interface
|
|
8
|
-
* to minimize the effort required to implement this interface.
|
|
9
|
-
*/
|
|
10
|
-
var AbstractSplitsCacheSync = /** @class */ (function () {
|
|
11
|
-
function AbstractSplitsCacheSync() {
|
|
12
|
-
}
|
|
13
|
-
AbstractSplitsCacheSync.prototype.update = function (toAdd, toRemove, changeNumber) {
|
|
14
|
-
var _this = this;
|
|
15
|
-
var updated = toAdd.map(function (addedFF) { return _this.addSplit(addedFF); }).some(function (result) { return result; });
|
|
16
|
-
updated = toRemove.map(function (removedFF) { return _this.removeSplit(removedFF); }).some(function (result) { return result; }) || updated;
|
|
17
|
-
this.setChangeNumber(changeNumber);
|
|
18
|
-
return updated;
|
|
19
|
-
};
|
|
20
|
-
AbstractSplitsCacheSync.prototype.getSplits = function (names) {
|
|
21
|
-
var _this = this;
|
|
22
|
-
var splits = {};
|
|
23
|
-
names.forEach(function (name) {
|
|
24
|
-
splits[name] = _this.getSplit(name);
|
|
25
|
-
});
|
|
26
|
-
return splits;
|
|
27
|
-
};
|
|
28
|
-
AbstractSplitsCacheSync.prototype.getAll = function () {
|
|
29
|
-
var _this = this;
|
|
30
|
-
return this.getSplitNames().map(function (key) { return _this.getSplit(key); });
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Kill `name` split and set `defaultTreatment` and `changeNumber`.
|
|
34
|
-
* Used for SPLIT_KILL push notifications.
|
|
35
|
-
*
|
|
36
|
-
* @returns `true` if the operation successed updating the split, or `false` if no split is updated,
|
|
37
|
-
* for instance, if the `changeNumber` is old, or if the split is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
|
|
38
|
-
*/
|
|
39
|
-
AbstractSplitsCacheSync.prototype.killLocally = function (name, defaultTreatment, changeNumber) {
|
|
40
|
-
var split = this.getSplit(name);
|
|
41
|
-
if (split && (!split.changeNumber || split.changeNumber < changeNumber)) {
|
|
42
|
-
var newSplit = (0, objectAssign_1.objectAssign)({}, split);
|
|
43
|
-
newSplit.killed = true;
|
|
44
|
-
newSplit.defaultTreatment = defaultTreatment;
|
|
45
|
-
newSplit.changeNumber = changeNumber;
|
|
46
|
-
return this.addSplit(newSplit);
|
|
47
|
-
}
|
|
48
|
-
return false;
|
|
49
|
-
};
|
|
50
|
-
return AbstractSplitsCacheSync;
|
|
51
|
-
}());
|
|
52
|
-
exports.AbstractSplitsCacheSync = AbstractSplitsCacheSync;
|
|
53
|
-
/**
|
|
54
|
-
* Given a parsed split, it returns a boolean flagging if its conditions use segments matchers (rules & whitelists).
|
|
55
|
-
* This util is intended to simplify the implementation of `splitsCache::usesSegments` method
|
|
56
|
-
*/
|
|
57
|
-
function usesSegments(ruleEntity) {
|
|
58
|
-
var conditions = ruleEntity.conditions || [];
|
|
59
|
-
for (var i = 0; i < conditions.length; i++) {
|
|
60
|
-
var matchers = conditions[i].matcherGroup.matchers;
|
|
61
|
-
for (var j = 0; j < matchers.length; j++) {
|
|
62
|
-
var matcher = matchers[j].matcherType;
|
|
63
|
-
if (matcher === constants_1.IN_SEGMENT || matcher === constants_1.IN_LARGE_SEGMENT)
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
var excluded = ruleEntity.excluded;
|
|
68
|
-
if (excluded && excluded.segments && excluded.segments.length > 0)
|
|
69
|
-
return true;
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
exports.usesSegments = usesSegments;
|
|
73
|
-
function usesSegmentsSync(storage) {
|
|
74
|
-
return storage.splits.usesSegments() || storage.rbSegments.usesSegments();
|
|
75
|
-
}
|
|
76
|
-
exports.usesSegmentsSync = usesSegmentsSync;
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SplitsCacheInLocal = void 0;
|
|
4
|
-
var tslib_1 = require("tslib");
|
|
5
|
-
var AbstractSplitsCacheSync_1 = require("../AbstractSplitsCacheSync");
|
|
6
|
-
var lang_1 = require("../../utils/lang");
|
|
7
|
-
var constants_1 = require("./constants");
|
|
8
|
-
var sets_1 = require("../../utils/lang/sets");
|
|
9
|
-
var SplitsCacheInLocal = /** @class */ (function (_super) {
|
|
10
|
-
tslib_1.__extends(SplitsCacheInLocal, _super);
|
|
11
|
-
function SplitsCacheInLocal(settings, keys, storage) {
|
|
12
|
-
var _this = _super.call(this) || this;
|
|
13
|
-
_this.keys = keys;
|
|
14
|
-
_this.log = settings.log;
|
|
15
|
-
_this.flagSetsFilter = settings.sync.__splitFiltersValidation.groupedFilters.bySet;
|
|
16
|
-
_this.storage = storage;
|
|
17
|
-
return _this;
|
|
18
|
-
}
|
|
19
|
-
SplitsCacheInLocal.prototype._decrementCount = function (key) {
|
|
20
|
-
var count = (0, lang_1.toNumber)(this.storage.getItem(key)) - 1;
|
|
21
|
-
if (count > 0)
|
|
22
|
-
this.storage.setItem(key, count + '');
|
|
23
|
-
else
|
|
24
|
-
this.storage.removeItem(key);
|
|
25
|
-
};
|
|
26
|
-
SplitsCacheInLocal.prototype._decrementCounts = function (split) {
|
|
27
|
-
try {
|
|
28
|
-
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
29
|
-
this._decrementCount(ttKey);
|
|
30
|
-
if ((0, AbstractSplitsCacheSync_1.usesSegments)(split)) {
|
|
31
|
-
var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
32
|
-
this._decrementCount(segmentsCountKey);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
catch (e) {
|
|
36
|
-
this.log.error(constants_1.LOG_PREFIX + e);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
SplitsCacheInLocal.prototype._incrementCounts = function (split) {
|
|
40
|
-
try {
|
|
41
|
-
var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
|
|
42
|
-
this.storage.setItem(ttKey, ((0, lang_1.toNumber)(this.storage.getItem(ttKey)) + 1) + '');
|
|
43
|
-
if ((0, AbstractSplitsCacheSync_1.usesSegments)(split)) {
|
|
44
|
-
var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
|
|
45
|
-
this.storage.setItem(segmentsCountKey, ((0, lang_1.toNumber)(this.storage.getItem(segmentsCountKey)) + 1) + '');
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
catch (e) {
|
|
49
|
-
this.log.error(constants_1.LOG_PREFIX + e);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* Removes all splits cache related data from localStorage (splits, counters, changeNumber and lastUpdated).
|
|
54
|
-
* We cannot simply call `localStorage.clear()` since that implies removing user items from the storage.
|
|
55
|
-
*/
|
|
56
|
-
SplitsCacheInLocal.prototype.clear = function () {
|
|
57
|
-
var _this = this;
|
|
58
|
-
// collect item keys
|
|
59
|
-
var len = this.storage.length;
|
|
60
|
-
var accum = [];
|
|
61
|
-
for (var cur = 0; cur < len; cur++) {
|
|
62
|
-
var key = this.storage.key(cur);
|
|
63
|
-
if (key != null && this.keys.isSplitsCacheKey(key))
|
|
64
|
-
accum.push(key);
|
|
65
|
-
}
|
|
66
|
-
// remove items
|
|
67
|
-
accum.forEach(function (key) {
|
|
68
|
-
_this.storage.removeItem(key);
|
|
69
|
-
});
|
|
70
|
-
this.hasSync = false;
|
|
71
|
-
};
|
|
72
|
-
SplitsCacheInLocal.prototype.addSplit = function (split) {
|
|
73
|
-
var name = split.name;
|
|
74
|
-
var splitKey = this.keys.buildSplitKey(name);
|
|
75
|
-
var splitFromStorage = this.storage.getItem(splitKey);
|
|
76
|
-
var previousSplit = splitFromStorage ? JSON.parse(splitFromStorage) : null;
|
|
77
|
-
if (previousSplit) {
|
|
78
|
-
this._decrementCounts(previousSplit);
|
|
79
|
-
this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
|
|
80
|
-
}
|
|
81
|
-
this.storage.setItem(splitKey, JSON.stringify(split));
|
|
82
|
-
this._incrementCounts(split);
|
|
83
|
-
this.addToFlagSets(split);
|
|
84
|
-
return true;
|
|
85
|
-
};
|
|
86
|
-
SplitsCacheInLocal.prototype.removeSplit = function (name) {
|
|
87
|
-
var split = this.getSplit(name);
|
|
88
|
-
if (!split)
|
|
89
|
-
return false;
|
|
90
|
-
this.storage.removeItem(this.keys.buildSplitKey(name));
|
|
91
|
-
this._decrementCounts(split);
|
|
92
|
-
this.removeFromFlagSets(split.name, split.sets);
|
|
93
|
-
return true;
|
|
94
|
-
};
|
|
95
|
-
SplitsCacheInLocal.prototype.getSplit = function (name) {
|
|
96
|
-
var item = this.storage.getItem(this.keys.buildSplitKey(name));
|
|
97
|
-
return item && JSON.parse(item);
|
|
98
|
-
};
|
|
99
|
-
SplitsCacheInLocal.prototype.setChangeNumber = function (changeNumber) {
|
|
100
|
-
try {
|
|
101
|
-
this.storage.setItem(this.keys.buildSplitsTillKey(), changeNumber + '');
|
|
102
|
-
// update "last updated" timestamp with current time
|
|
103
|
-
this.storage.setItem(this.keys.buildLastUpdatedKey(), Date.now() + '');
|
|
104
|
-
this.hasSync = true;
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
catch (e) {
|
|
108
|
-
this.log.error(constants_1.LOG_PREFIX + e);
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
SplitsCacheInLocal.prototype.getChangeNumber = function () {
|
|
113
|
-
var n = -1;
|
|
114
|
-
var value = this.storage.getItem(this.keys.buildSplitsTillKey());
|
|
115
|
-
if (value !== null) {
|
|
116
|
-
value = parseInt(value, 10);
|
|
117
|
-
return (0, lang_1.isNaNNumber)(value) ? n : value;
|
|
118
|
-
}
|
|
119
|
-
return n;
|
|
120
|
-
};
|
|
121
|
-
SplitsCacheInLocal.prototype.getSplitNames = function () {
|
|
122
|
-
var len = this.storage.length;
|
|
123
|
-
var accum = [];
|
|
124
|
-
var cur = 0;
|
|
125
|
-
while (cur < len) {
|
|
126
|
-
var key = this.storage.key(cur);
|
|
127
|
-
if (key != null && this.keys.isSplitKey(key))
|
|
128
|
-
accum.push(this.keys.extractKey(key));
|
|
129
|
-
cur++;
|
|
130
|
-
}
|
|
131
|
-
return accum;
|
|
132
|
-
};
|
|
133
|
-
SplitsCacheInLocal.prototype.trafficTypeExists = function (trafficType) {
|
|
134
|
-
var ttCount = (0, lang_1.toNumber)(this.storage.getItem(this.keys.buildTrafficTypeKey(trafficType)));
|
|
135
|
-
return (0, lang_1.isFiniteNumber)(ttCount) && ttCount > 0;
|
|
136
|
-
};
|
|
137
|
-
SplitsCacheInLocal.prototype.usesSegments = function () {
|
|
138
|
-
// If cache hasn't been synchronized with the cloud, assume we need them.
|
|
139
|
-
if (!this.hasSync)
|
|
140
|
-
return true;
|
|
141
|
-
var storedCount = this.storage.getItem(this.keys.buildSplitsWithSegmentCountKey());
|
|
142
|
-
var splitsWithSegmentsCount = storedCount === null ? 0 : (0, lang_1.toNumber)(storedCount);
|
|
143
|
-
return (0, lang_1.isFiniteNumber)(splitsWithSegmentsCount) ?
|
|
144
|
-
splitsWithSegmentsCount > 0 :
|
|
145
|
-
true;
|
|
146
|
-
};
|
|
147
|
-
SplitsCacheInLocal.prototype.getNamesByFlagSets = function (flagSets) {
|
|
148
|
-
var _this = this;
|
|
149
|
-
return flagSets.map(function (flagSet) {
|
|
150
|
-
var flagSetKey = _this.keys.buildFlagSetKey(flagSet);
|
|
151
|
-
var flagSetFromStorage = _this.storage.getItem(flagSetKey);
|
|
152
|
-
return new Set(flagSetFromStorage ? JSON.parse(flagSetFromStorage) : []);
|
|
153
|
-
});
|
|
154
|
-
};
|
|
155
|
-
SplitsCacheInLocal.prototype.addToFlagSets = function (featureFlag) {
|
|
156
|
-
var _this = this;
|
|
157
|
-
if (!featureFlag.sets)
|
|
158
|
-
return;
|
|
159
|
-
featureFlag.sets.forEach(function (featureFlagSet) {
|
|
160
|
-
if (_this.flagSetsFilter.length > 0 && !_this.flagSetsFilter.some(function (filterFlagSet) { return filterFlagSet === featureFlagSet; }))
|
|
161
|
-
return;
|
|
162
|
-
var flagSetKey = _this.keys.buildFlagSetKey(featureFlagSet);
|
|
163
|
-
var flagSetFromStorage = _this.storage.getItem(flagSetKey);
|
|
164
|
-
var flagSetCache = new Set(flagSetFromStorage ? JSON.parse(flagSetFromStorage) : []);
|
|
165
|
-
if (flagSetCache.has(featureFlag.name))
|
|
166
|
-
return;
|
|
167
|
-
flagSetCache.add(featureFlag.name);
|
|
168
|
-
_this.storage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
|
|
169
|
-
});
|
|
170
|
-
};
|
|
171
|
-
SplitsCacheInLocal.prototype.removeFromFlagSets = function (featureFlagName, flagSets) {
|
|
172
|
-
var _this = this;
|
|
173
|
-
if (!flagSets)
|
|
174
|
-
return;
|
|
175
|
-
flagSets.forEach(function (flagSet) {
|
|
176
|
-
_this.removeNames(flagSet, featureFlagName);
|
|
177
|
-
});
|
|
178
|
-
};
|
|
179
|
-
SplitsCacheInLocal.prototype.removeNames = function (flagSetName, featureFlagName) {
|
|
180
|
-
var flagSetKey = this.keys.buildFlagSetKey(flagSetName);
|
|
181
|
-
var flagSetFromStorage = this.storage.getItem(flagSetKey);
|
|
182
|
-
if (!flagSetFromStorage)
|
|
183
|
-
return;
|
|
184
|
-
var flagSetCache = new Set(JSON.parse(flagSetFromStorage));
|
|
185
|
-
flagSetCache.delete(featureFlagName);
|
|
186
|
-
if (flagSetCache.size === 0) {
|
|
187
|
-
this.storage.removeItem(flagSetKey);
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
this.storage.setItem(flagSetKey, JSON.stringify((0, sets_1.setToArray)(flagSetCache)));
|
|
191
|
-
};
|
|
192
|
-
return SplitsCacheInLocal;
|
|
193
|
-
}(AbstractSplitsCacheSync_1.AbstractSplitsCacheSync));
|
|
194
|
-
exports.SplitsCacheInLocal = SplitsCacheInLocal;
|