@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
|
@@ -1,40 +1,52 @@
|
|
|
1
1
|
import { IPlatform } from '../sdkFactory/types';
|
|
2
2
|
import { ISettings } from '../types';
|
|
3
3
|
import { splitHttpClientFactory } from './splitHttpClient';
|
|
4
|
-
import {
|
|
4
|
+
import { IServiceApi } from './types';
|
|
5
5
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
6
6
|
import { ITelemetryTracker } from '../trackers/types';
|
|
7
|
-
import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY,
|
|
7
|
+
import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, SEGMENT, MEMBERSHIPS } from '../utils/constants';
|
|
8
8
|
import { ERROR_TOO_MANY_SETS } from '../logger/constants';
|
|
9
|
+
import { authProviderFactory } from './authProvider';
|
|
10
|
+
import { secureSplitHttpClientFactory } from './secureSplitHttpClient';
|
|
9
11
|
|
|
10
12
|
const noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
|
|
11
13
|
|
|
12
|
-
function userKeyToQueryParam(userKey: string) {
|
|
13
|
-
return 'users=' + encodeURIComponent(userKey); // no need to check availability of `encodeURIComponent`, since it is a global highly supported.
|
|
14
|
-
}
|
|
15
|
-
|
|
16
14
|
/**
|
|
17
15
|
* Factory of ServiceApi objects, which group the collection of HTTP endpoints used by the SDKs
|
|
18
16
|
*
|
|
19
17
|
* @param settings - validated settings object
|
|
20
18
|
* @param platform - object containing environment-specific dependencies
|
|
21
19
|
* @param telemetryTracker - telemetry tracker
|
|
22
|
-
* @param secureSplitHttpClientFactory - factory of SecureSplitHttpClient objects
|
|
23
20
|
*/
|
|
24
21
|
export function serviceApiFactory(
|
|
25
22
|
settings: ISettings,
|
|
26
23
|
platform: Pick<IPlatform, 'getOptions' | 'getFetch'>,
|
|
27
24
|
telemetryTracker: ITelemetryTracker,
|
|
28
|
-
secureSplitHttpClientFactory?: (settings: ISettings, platform: Pick<IPlatform, 'getOptions' | 'getFetch'>, telemetryTracker: ITelemetryTracker) => ISecureSplitHttpClient,
|
|
29
25
|
): IServiceApi {
|
|
30
26
|
|
|
31
27
|
const urls = settings.urls;
|
|
32
28
|
const filterQueryString = settings.sync.__splitFiltersValidation && settings.sync.__splitFiltersValidation.queryString;
|
|
33
29
|
const SplitSDKImpressionsMode = settings.sync.impressionsMode;
|
|
30
|
+
|
|
34
31
|
const splitHttpClient = splitHttpClientFactory(settings, platform);
|
|
35
|
-
|
|
32
|
+
|
|
33
|
+
// Shared authProvider so that the SSE authentication (via `fetchAuth`,
|
|
34
|
+
// used by `pushManager`) and every authenticated HTTP request to the Configs
|
|
35
|
+
// API reuse the same cached credential instead of each fetching their own.
|
|
36
|
+
const authProvider = authProviderFactory(settings, splitHttpClient, telemetryTracker);
|
|
37
|
+
const secureSplitHttpClient = secureSplitHttpClientFactory(splitHttpClient, authProvider);
|
|
38
|
+
|
|
39
|
+
let initialAuth = true;
|
|
36
40
|
|
|
37
41
|
return {
|
|
42
|
+
fetchAuth() {
|
|
43
|
+
// Guard condition to avoid invalidating the cached credential on the first pushManager authentication
|
|
44
|
+
if (initialAuth) initialAuth = false;
|
|
45
|
+
else authProvider.invalidate();
|
|
46
|
+
|
|
47
|
+
return authProvider.credential();
|
|
48
|
+
},
|
|
49
|
+
|
|
38
50
|
// @TODO throw errors if health check requests fail, to log them in the Synchronizer
|
|
39
51
|
getSdkAPIHealthCheck() {
|
|
40
52
|
const url = `${urls.sdk}/api/version`;
|
|
@@ -46,15 +58,6 @@ export function serviceApiFactory(
|
|
|
46
58
|
return splitHttpClient(url).then(() => true).catch(() => false);
|
|
47
59
|
},
|
|
48
60
|
|
|
49
|
-
fetchAuth(userMatchingKeys?: string[]) {
|
|
50
|
-
let url = `${urls.auth}/api/v2/auth?s=${settings.sync.flagSpecVersion}`;
|
|
51
|
-
if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
|
|
52
|
-
const queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
|
|
53
|
-
if (queryParams) url += '&' + queryParams;
|
|
54
|
-
}
|
|
55
|
-
return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN));
|
|
56
|
-
},
|
|
57
|
-
|
|
58
61
|
fetchSplitChanges(since: number, noCache?: boolean, till?: number, rbSince?: number) {
|
|
59
62
|
const url = `${urls.sdk}/api/splitChanges?s=${settings.sync.flagSpecVersion}&since=${since}${rbSince ? '&rbSince=' + rbSince : ''}${filterQueryString || ''}${till ? '&till=' + till : ''}`;
|
|
60
63
|
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SPLITS))
|
|
@@ -99,7 +102,7 @@ export function serviceApiFactory(
|
|
|
99
102
|
*/
|
|
100
103
|
postEventsBulk(body: string, headers?: Record<string, string>) {
|
|
101
104
|
const url = `${urls.events}/api/events/bulk`;
|
|
102
|
-
return
|
|
105
|
+
return secureSplitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(EVENTS), false, false, false);
|
|
103
106
|
},
|
|
104
107
|
|
|
105
108
|
/**
|
|
@@ -110,10 +113,10 @@ export function serviceApiFactory(
|
|
|
110
113
|
*/
|
|
111
114
|
postTestImpressionsBulk(body: string, headers?: Record<string, string>) {
|
|
112
115
|
const url = `${urls.events}/api/testImpressions/bulk`;
|
|
113
|
-
return
|
|
116
|
+
return secureSplitHttpClient(url, {
|
|
114
117
|
// Adding extra headers to send impressions in OPTIMIZED or DEBUG modes.
|
|
115
118
|
method: 'POST', body, headers: objectAssign({ SplitSDKImpressionsMode }, headers)
|
|
116
|
-
}, telemetryTracker.trackHttp(IMPRESSIONS));
|
|
119
|
+
}, telemetryTracker.trackHttp(IMPRESSIONS), false, false, false);
|
|
117
120
|
},
|
|
118
121
|
|
|
119
122
|
/**
|
|
@@ -124,7 +127,7 @@ export function serviceApiFactory(
|
|
|
124
127
|
*/
|
|
125
128
|
postTestImpressionsCount(body: string, headers?: Record<string, string>) {
|
|
126
129
|
const url = `${urls.events}/api/testImpressions/count`;
|
|
127
|
-
return
|
|
130
|
+
return secureSplitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(IMPRESSIONS_COUNT), false, false, false);
|
|
128
131
|
},
|
|
129
132
|
|
|
130
133
|
/**
|
|
@@ -135,7 +138,7 @@ export function serviceApiFactory(
|
|
|
135
138
|
*/
|
|
136
139
|
postUniqueKeysBulkCs(body: string, headers?: Record<string, string>) {
|
|
137
140
|
const url = `${urls.telemetry}/api/v1/keys/cs`;
|
|
138
|
-
return
|
|
141
|
+
return secureSplitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY), false, false, false);
|
|
139
142
|
},
|
|
140
143
|
|
|
141
144
|
/**
|
|
@@ -146,7 +149,7 @@ export function serviceApiFactory(
|
|
|
146
149
|
*/
|
|
147
150
|
postUniqueKeysBulkSs(body: string, headers?: Record<string, string>) {
|
|
148
151
|
const url = `${urls.telemetry}/api/v1/keys/ss`;
|
|
149
|
-
return
|
|
152
|
+
return secureSplitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY), false, false, false);
|
|
150
153
|
},
|
|
151
154
|
|
|
152
155
|
postMetricsConfig(body: string, headers?: Record<string, string>) {
|
package/src/services/splitApi.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { objectAssign } from '../utils/lang/objectAssign';
|
|
|
6
6
|
import { ITelemetryTracker } from '../trackers/types';
|
|
7
7
|
import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MEMBERSHIPS } from '../utils/constants';
|
|
8
8
|
import { ERROR_TOO_MANY_SETS } from '../logger/constants';
|
|
9
|
+
import { fetchAuthFactory } from '../sync/streaming/AuthClient';
|
|
9
10
|
|
|
10
11
|
const noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
|
|
11
12
|
|
|
@@ -33,6 +34,15 @@ export function splitApiFactory(
|
|
|
33
34
|
const splitHttpClient = splitHttpClientFactory(settings, platform);
|
|
34
35
|
|
|
35
36
|
return {
|
|
37
|
+
fetchAuth: fetchAuthFactory((userMatchingKeys?: string[]) => {
|
|
38
|
+
let url = `${urls.auth}/v2/auth?s=${settings.sync.flagSpecVersion}`;
|
|
39
|
+
if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
|
|
40
|
+
const queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
|
|
41
|
+
if (queryParams) url += '&' + queryParams;
|
|
42
|
+
}
|
|
43
|
+
return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN));
|
|
44
|
+
}),
|
|
45
|
+
|
|
36
46
|
// @TODO throw errors if health check requests fail, to log them in the Synchronizer
|
|
37
47
|
getSdkAPIHealthCheck() {
|
|
38
48
|
const url = `${urls.sdk}/version`;
|
|
@@ -44,15 +54,6 @@ export function splitApiFactory(
|
|
|
44
54
|
return splitHttpClient(url).then(() => true).catch(() => false);
|
|
45
55
|
},
|
|
46
56
|
|
|
47
|
-
fetchAuth(userMatchingKeys?: string[]) {
|
|
48
|
-
let url = `${urls.auth}/v2/auth?s=${settings.sync.flagSpecVersion}`;
|
|
49
|
-
if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
|
|
50
|
-
const queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
|
|
51
|
-
if (queryParams) url += '&' + queryParams;
|
|
52
|
-
}
|
|
53
|
-
return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN));
|
|
54
|
-
},
|
|
55
|
-
|
|
56
57
|
fetchSplitChanges(since: number, noCache?: boolean, till?: number, rbSince?: number) {
|
|
57
58
|
const url = `${urls.sdk}/splitChanges?s=${settings.sync.flagSpecVersion}&since=${since}${rbSince ? '&rbSince=' + rbSince : ''}${filterQueryString || ''}${till ? '&till=' + till : ''}`;
|
|
58
59
|
return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SPLITS))
|
package/src/services/types.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { IFetchAuth } from '../sync/streaming/AuthClient/types';
|
|
2
|
+
|
|
1
3
|
export type IRequestOptions = {
|
|
2
4
|
method?: string,
|
|
3
5
|
headers?: Record<string, string>,
|
|
@@ -33,9 +35,8 @@ export type IHealthCheckAPI = () => Promise<boolean>
|
|
|
33
35
|
|
|
34
36
|
export type ISplitHttpClient = (url: string, options?: IRequestOptions, latencyTracker?: (error?: NetworkError) => void, logErrorsAsInfo?: boolean, newVersionHeader?: boolean) => Promise<IResponse>
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
export type IFetchAuth = (userKeys?: string[]) => Promise<IResponse>
|
|
38
|
+
// @TODO: remove `newVersionHeader` and `useJwt` arguments when all service endpoints are migrated to the new auth mechanism
|
|
39
|
+
export type ISecureSplitHttpClient = ((url: string, options?: IRequestOptions, latencyTracker?: (error?: NetworkError) => void, logErrorsAsInfo?: boolean, newVersionHeader?: boolean, useJwt?: boolean) => Promise<IResponse>) & { stop(): void }
|
|
39
40
|
|
|
40
41
|
export type IFetchDefinitionChanges = (since: number, noCache?: boolean, till?: number, rbSince?: number) => Promise<IResponse>
|
|
41
42
|
|
|
@@ -73,7 +74,7 @@ export interface IServiceApi {
|
|
|
73
74
|
postTestImpressionsCount: IPostTestImpressionsCount
|
|
74
75
|
postMetricsConfig: IPostMetricsConfig
|
|
75
76
|
postMetricsUsage: IPostMetricsUsage
|
|
76
|
-
// lifecycle
|
|
77
|
+
// lifecycle: stops authProvider backoff retries
|
|
77
78
|
stop(): void
|
|
78
79
|
}
|
|
79
80
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// Dynamically require ioredis to prevent strict TypeScript binding
|
|
2
|
-
// and handle module export differences between v4 and
|
|
2
|
+
// and handle module export differences between v4 and later major versions.
|
|
3
3
|
let RedisConstructor: any;
|
|
4
4
|
try {
|
|
5
5
|
const ioredisLib = require('ioredis');
|
|
6
6
|
RedisConstructor = ioredisLib.default || ioredisLib;
|
|
7
7
|
} catch (e) {
|
|
8
8
|
// If we reach here, the peer dependency is missing
|
|
9
|
-
throw new Error('ioredis is missing. Please install ioredis v4 or
|
|
9
|
+
throw new Error('ioredis is missing. Please install ioredis v4, v5 or v6.');
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
import { ILogger } from '../../logger/types';
|
|
@@ -31,9 +31,12 @@ const DEFAULT_LIBRARY_OPTIONS = {
|
|
|
31
31
|
enableOfflineQueue: false,
|
|
32
32
|
connectTimeout: DEFAULT_OPTIONS.connectionTimeout,
|
|
33
33
|
lazyConnect: false,
|
|
34
|
-
// CRITICAL: v5
|
|
35
|
-
// v4 defaulted to 5000. We explicitly set it here to ensure v5
|
|
34
|
+
// CRITICAL: v5 and v6 default this to 0 (disabled), which breaks dynamic clusters.
|
|
35
|
+
// v4 defaulted to 5000. We explicitly set it here to ensure v5 and v6 work like v4.
|
|
36
36
|
slotsRefreshInterval: 5000,
|
|
37
|
+
// v6 defaults to RESP3 (`protocol: 3`). The SDK doesn't use any RESP3 feature,
|
|
38
|
+
// so we stick to RESP2 to keep the v4 and v5 behavior. Ignored by v4 and v5.
|
|
39
|
+
protocol: 2,
|
|
37
40
|
};
|
|
38
41
|
|
|
39
42
|
interface IRedisCommand {
|
|
@@ -45,7 +48,7 @@ interface IRedisCommand {
|
|
|
45
48
|
|
|
46
49
|
/**
|
|
47
50
|
* Redis adapter on top of the library of choice (written with ioredis) for some extra control.
|
|
48
|
-
* Refactored to use Composition instead of Inheritance to support
|
|
51
|
+
* Refactored to use Composition instead of Inheritance to support v4, v5 and v6.
|
|
49
52
|
*/
|
|
50
53
|
export class RedisAdapter {
|
|
51
54
|
// eslint-disable-next-line no-undef -- Index signature to allow proxying dynamic ioredis methods without TS errors
|
|
@@ -10,110 +10,112 @@ import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger
|
|
|
10
10
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
11
11
|
import { usesSegmentsSync } from '../../storages/AbstractDefinitionsCacheSync';
|
|
12
12
|
import { SdkUpdateMetadata } from '../../../types/splitio';
|
|
13
|
-
import {
|
|
13
|
+
import { splitChangesFetcherFactory } from './fetchers/splitChangesFetcher';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Expose start / stop mechanism for polling data from services.
|
|
17
17
|
* For client-side API with multiple clients.
|
|
18
18
|
*/
|
|
19
19
|
export function pollingManagerCSFactory(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
): IPollingManagerCS {
|
|
20
|
+
definitionFetcherFactory = splitChangesFetcherFactory,
|
|
21
|
+
): (params: ISdkFactoryContextSync) => IPollingManagerCS {
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
return function (params: ISdkFactoryContextSync): IPollingManagerCS {
|
|
24
|
+
const { serviceApi, storage, readiness, settings } = params;
|
|
25
|
+
const log = settings.log;
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
const definitionChangesFetcher = definitionFetcherFactory(params);
|
|
28
|
+
const definitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings);
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
// Map of matching keys to their corresponding MySegmentsSyncTask.
|
|
31
|
+
const mySegmentsSyncTasks: Record<string, IMySegmentsSyncTask> = {};
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const matchingKey = getMatching(settings.core.key);
|
|
34
|
+
const mySegmentsSyncTask = add(matchingKey, readiness, storage);
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
function startMySegmentsSyncTasks() {
|
|
37
|
+
forOwn(mySegmentsSyncTasks, (mySegmentsSyncTask) => {
|
|
38
|
+
mySegmentsSyncTask.start();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// smart pausing
|
|
48
|
-
readiness.definitions.on(SDK_DEFINITIONS_ARRIVED, () => {
|
|
49
|
-
if (!definitionsSyncTask.isRunning()) return; // noop if not doing polling
|
|
50
|
-
const usingSegments = usesSegmentsSync(storage);
|
|
51
|
-
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
52
|
-
log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
53
|
-
if (usingSegments) {
|
|
54
|
-
startMySegmentsSyncTasks();
|
|
55
|
-
} else {
|
|
56
|
-
stopMySegmentsSyncTasks();
|
|
57
|
-
}
|
|
42
|
+
function stopMySegmentsSyncTasks() {
|
|
43
|
+
forOwn(mySegmentsSyncTasks, (mySegmentsSyncTask) => {
|
|
44
|
+
if (mySegmentsSyncTask.isRunning()) mySegmentsSyncTask.stop();
|
|
45
|
+
});
|
|
58
46
|
}
|
|
59
|
-
});
|
|
60
47
|
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
// smart pausing
|
|
49
|
+
readiness.definitions.on(SDK_DEFINITIONS_ARRIVED, () => {
|
|
50
|
+
if (!definitionsSyncTask.isRunning()) return; // noop if not doing polling
|
|
51
|
+
const usingSegments = usesSegmentsSync(storage);
|
|
52
|
+
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
53
|
+
log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
|
|
54
|
+
if (usingSegments) {
|
|
55
|
+
startMySegmentsSyncTasks();
|
|
56
|
+
} else {
|
|
57
|
+
stopMySegmentsSyncTasks();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
function add(matchingKey: string, readiness: IReadinessManager, storage: IStorageSync) {
|
|
63
|
+
const mySegmentsSyncTask = mySegmentsSyncTaskFactory(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
// smart ready
|
|
66
|
+
function smartReady(metadata: SdkUpdateMetadata) {
|
|
67
|
+
if (!readiness.isReady() && !usesSegmentsSync(storage)) readiness.segments.emit(SDK_SEGMENTS_ARRIVED, metadata);
|
|
68
|
+
}
|
|
69
|
+
if (!usesSegmentsSync(storage)) setTimeout(smartReady, 0);
|
|
70
|
+
else readiness.definitions.once(SDK_DEFINITIONS_ARRIVED, smartReady);
|
|
71
|
+
|
|
72
|
+
mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
|
|
73
|
+
return mySegmentsSyncTask;
|
|
67
74
|
}
|
|
68
|
-
if (!usesSegmentsSync(storage)) setTimeout(smartReady, 0);
|
|
69
|
-
else readiness.definitions.once(SDK_DEFINITIONS_ARRIVED, smartReady);
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
return {
|
|
77
|
+
definitionsSyncTask,
|
|
78
|
+
segmentsSyncTask: mySegmentsSyncTask,
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
80
|
+
// Start periodic fetching (polling)
|
|
81
|
+
start() {
|
|
82
|
+
log.info(POLLING_START);
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
definitionsSyncTask.start();
|
|
85
|
+
if (usesSegmentsSync(storage)) startMySegmentsSyncTasks();
|
|
86
|
+
},
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
// Stop periodic fetching (polling)
|
|
89
|
+
stop() {
|
|
90
|
+
log.info(POLLING_STOP);
|
|
86
91
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
if (definitionsSyncTask.isRunning()) definitionsSyncTask.stop();
|
|
93
|
+
stopMySegmentsSyncTasks();
|
|
94
|
+
},
|
|
90
95
|
|
|
91
|
-
if
|
|
92
|
-
|
|
93
|
-
},
|
|
96
|
+
// Used by SyncManager to know if running in polling mode.
|
|
97
|
+
isRunning: definitionsSyncTask.isRunning,
|
|
94
98
|
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
// fetch definitions and segments
|
|
100
|
+
syncAll() {
|
|
101
|
+
const promises = [definitionsSyncTask.execute()];
|
|
102
|
+
forOwn(mySegmentsSyncTasks, (mySegmentsSyncTask) => {
|
|
103
|
+
promises.push(mySegmentsSyncTask.execute());
|
|
104
|
+
});
|
|
105
|
+
return Promise.all(promises);
|
|
106
|
+
},
|
|
97
107
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const promises = [definitionsSyncTask.execute()];
|
|
101
|
-
forOwn(mySegmentsSyncTasks, (mySegmentsSyncTask) => {
|
|
102
|
-
promises.push(mySegmentsSyncTask.execute());
|
|
103
|
-
});
|
|
104
|
-
return Promise.all(promises);
|
|
105
|
-
},
|
|
108
|
+
// Support for handling mySegments sync of multiple clients
|
|
109
|
+
add,
|
|
106
110
|
|
|
107
|
-
|
|
108
|
-
|
|
111
|
+
remove(matchingKey: string) {
|
|
112
|
+
delete mySegmentsSyncTasks[matchingKey];
|
|
113
|
+
},
|
|
109
114
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
get(matchingKey: string) {
|
|
116
|
+
return mySegmentsSyncTasks[matchingKey];
|
|
117
|
+
}
|
|
118
|
+
};
|
|
113
119
|
|
|
114
|
-
get(matchingKey: string) {
|
|
115
|
-
return mySegmentsSyncTasks[matchingKey];
|
|
116
|
-
}
|
|
117
120
|
};
|
|
118
|
-
|
|
119
121
|
}
|
|
@@ -3,57 +3,61 @@ import { segmentsSyncTaskFactory } from './syncTasks/segmentsSyncTask';
|
|
|
3
3
|
import { IPollingManager, ISegmentsSyncTask, IDefinitionsSyncTask } from './types';
|
|
4
4
|
import { POLLING_START, POLLING_STOP, LOG_PREFIX_SYNC_POLLING } from '../../logger/constants';
|
|
5
5
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
6
|
-
import {
|
|
6
|
+
import { segmentChangesFetcherFactory } from './fetchers/segmentChangesFetcher';
|
|
7
|
+
import { splitChangesFetcherFactory } from './fetchers/splitChangesFetcher';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Expose start / stop mechanism for pulling data from services.
|
|
10
11
|
*/
|
|
11
12
|
export function pollingManagerSSFactory(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
startingUp.
|
|
36
|
-
|
|
13
|
+
definitionFetcherFactory = splitChangesFetcherFactory,
|
|
14
|
+
segmentFetcherFactory = (params: ISdkFactoryContextSync) => segmentChangesFetcherFactory(params.serviceApi.fetchSegmentChanges)
|
|
15
|
+
): (params: ISdkFactoryContextSync) => IPollingManager {
|
|
16
|
+
|
|
17
|
+
return function (params: ISdkFactoryContextSync): IPollingManager {
|
|
18
|
+
const { storage, readiness, settings } = params;
|
|
19
|
+
const log = settings.log;
|
|
20
|
+
|
|
21
|
+
const definitionChangesFetcher = definitionFetcherFactory(params);
|
|
22
|
+
const segmentChangesFetcher = segmentFetcherFactory(params);
|
|
23
|
+
const segmentsSyncTask: ISegmentsSyncTask = segmentsSyncTaskFactory(segmentChangesFetcher, storage, readiness, settings);
|
|
24
|
+
const definitionsSyncTask: IDefinitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings, segmentsSyncTask);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
definitionsSyncTask,
|
|
28
|
+
segmentsSyncTask,
|
|
29
|
+
|
|
30
|
+
// Start periodic fetching (polling)
|
|
31
|
+
start() {
|
|
32
|
+
log.info(POLLING_START);
|
|
33
|
+
log.debug(LOG_PREFIX_SYNC_POLLING + `${definitionChangesFetcher.type} will be refreshed each ${settings.scheduler.featuresRefreshRate} millis`);
|
|
34
|
+
log.debug(LOG_PREFIX_SYNC_POLLING + `segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`);
|
|
35
|
+
|
|
36
|
+
const startingUp = definitionsSyncTask.start();
|
|
37
|
+
if (startingUp) {
|
|
38
|
+
startingUp.then(() => {
|
|
39
|
+
if (definitionsSyncTask.isRunning()) segmentsSyncTask.start();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
// Stop periodic fetching (polling)
|
|
45
|
+
stop() {
|
|
46
|
+
log.info(POLLING_STOP);
|
|
47
|
+
|
|
48
|
+
if (definitionsSyncTask.isRunning()) definitionsSyncTask.stop();
|
|
49
|
+
if (segmentsSyncTask.isRunning()) segmentsSyncTask.stop();
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
// Used by SyncManager to know if running in polling mode.
|
|
53
|
+
isRunning: definitionsSyncTask.isRunning,
|
|
54
|
+
|
|
55
|
+
syncAll() {
|
|
56
|
+
// fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
|
|
57
|
+
return definitionsSyncTask.execute().then(() => {
|
|
58
|
+
return segmentsSyncTask.execute();
|
|
37
59
|
});
|
|
38
60
|
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Stop periodic fetching (polling)
|
|
42
|
-
stop() {
|
|
43
|
-
log.info(POLLING_STOP);
|
|
44
|
-
|
|
45
|
-
if (definitionsSyncTask.isRunning()) definitionsSyncTask.stop();
|
|
46
|
-
if (segmentsSyncTask.isRunning()) segmentsSyncTask.stop();
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
// Used by SyncManager to know if running in polling mode.
|
|
50
|
-
isRunning: definitionsSyncTask.isRunning,
|
|
51
|
-
|
|
52
|
-
syncAll() {
|
|
53
|
-
// fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
|
|
54
|
-
return definitionsSyncTask.execute().then(() => {
|
|
55
|
-
return segmentsSyncTask.execute();
|
|
56
|
-
});
|
|
57
|
-
}
|
|
61
|
+
};
|
|
58
62
|
};
|
|
59
63
|
}
|
|
@@ -9,7 +9,7 @@ import { SYNC_FETCH, SYNC_UPDATE, SYNC_FETCH_FAILS, SYNC_FETCH_RETRY } from '../
|
|
|
9
9
|
import { startsWith } from '../../../utils/lang';
|
|
10
10
|
import { IN_RULE_BASED_SEGMENT, IN_SEGMENT, RULE_BASED_SEGMENT, STANDARD_SEGMENT } from '../../../utils/constants';
|
|
11
11
|
import { setToArray } from '../../../utils/lang/sets';
|
|
12
|
-
import {
|
|
12
|
+
import { RB_SEGMENT_UPDATE } from '../../streaming/constants';
|
|
13
13
|
import { SdkUpdateMetadata } from '../../../../types/splitio';
|
|
14
14
|
import { ISplit } from '../fetchers/splitChangesFetcher';
|
|
15
15
|
import { ISegmentsSyncTask } from '../types';
|
|
@@ -154,14 +154,14 @@ export function definitionChangesUpdaterFactory(
|
|
|
154
154
|
|
|
155
155
|
return Promise.resolve(
|
|
156
156
|
instantUpdate ?
|
|
157
|
-
instantUpdate.type ===
|
|
157
|
+
instantUpdate.type === RB_SEGMENT_UPDATE ?
|
|
158
|
+
{ rbs: convertInstantUpdateToDefinitionChanges(instantUpdate) as IDefinitionChangesResponse['rbs'] } :
|
|
158
159
|
// IFFU edge case: a change to definition that adds an IN_RULE_BASED_SEGMENT matcher that is not present yet
|
|
159
160
|
Promise.resolve(rbSegments.contains(parseSegments(instantUpdate.payload, IN_RULE_BASED_SEGMENT))).then((contains) => {
|
|
160
161
|
return contains ?
|
|
161
162
|
{ d: convertInstantUpdateToDefinitionChanges(instantUpdate) as IDefinitionChangesResponse['d'] } :
|
|
162
163
|
definitionChangesFetcher(since, noCache, till, rbSince, _promiseDecorator);
|
|
163
164
|
}) :
|
|
164
|
-
{ rbs: convertInstantUpdateToDefinitionChanges(instantUpdate) as IDefinitionChangesResponse['rbs'] } :
|
|
165
165
|
definitionChangesFetcher(since, noCache, till, rbSince, _promiseDecorator)
|
|
166
166
|
)
|
|
167
167
|
.then((definitionChanges: IDefinitionChangesResponse) => {
|
|
@@ -47,7 +47,7 @@ export function segmentChangesUpdaterFactory(
|
|
|
47
47
|
false :
|
|
48
48
|
segmentChangesFetcher(since || -1, segmentName, noCache, till, _promiseDecorator).then((changes) => {
|
|
49
49
|
return Promise.all(changes.map(x => {
|
|
50
|
-
log.debug(`${LOG_PREFIX_SYNC}Processing ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
|
|
50
|
+
log.debug(`${LOG_PREFIX_SYNC}Processing ${segmentName} with since = ${x.since} and till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
|
|
51
51
|
return segments.update(segmentName, x.added, x.removed, x.till);
|
|
52
52
|
})).then((updates) => {
|
|
53
53
|
return updates.some(update => update);
|
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
import { IFetchAuth } from '
|
|
2
|
-
import { IAuthenticate, IJwtCredentialV2 } from './types';
|
|
1
|
+
import { IJwtCredential, IFetchAuth } from './types';
|
|
3
2
|
import { objectAssign } from '../../../utils/lang/objectAssign';
|
|
4
|
-
import { encodeToBase64 } from '../../../utils/base64';
|
|
5
3
|
import { decodeJWTtoken } from '../../../utils/jwt';
|
|
6
|
-
import {
|
|
4
|
+
import { IResponse } from '../../../services/types';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* Factory of authentication function.
|
|
10
8
|
*
|
|
11
|
-
* @param fetchAuth -
|
|
9
|
+
* @param fetchAuth - /auth endpoint
|
|
12
10
|
*/
|
|
13
|
-
export function
|
|
11
|
+
export function fetchAuthFactory(fetchAuth: (userKeys?: string[]) => Promise<IResponse>): IFetchAuth {
|
|
14
12
|
|
|
15
13
|
/**
|
|
16
14
|
* Run authentication requests to Auth Server, and returns a promise that resolves with the decoded JTW token.
|
|
17
15
|
* @param userKeys - set of user Keys to track membership updates. It is undefined for server-side API.
|
|
18
16
|
*/
|
|
19
|
-
return function authenticate(userKeys?: string[]): Promise<
|
|
17
|
+
return function authenticate(userKeys?: string[]): Promise<IJwtCredential> {
|
|
20
18
|
return fetchAuth(userKeys)
|
|
21
19
|
.then(resp => resp.json())
|
|
22
20
|
.then(json => {
|
|
@@ -24,19 +22,20 @@ export function authenticateFactory(fetchAuth: IFetchAuth): IAuthenticate {
|
|
|
24
22
|
const decodedToken = decodeJWTtoken(json.token);
|
|
25
23
|
if (typeof decodedToken.iat !== 'number' || typeof decodedToken.exp !== 'number') throw new Error('token properties "issuedAt" (iat) or "expiration" (exp) are missing or invalid');
|
|
26
24
|
const channels = JSON.parse(decodedToken['x-ably-capability']);
|
|
27
|
-
|
|
25
|
+
const credential = objectAssign({
|
|
28
26
|
decodedToken,
|
|
29
27
|
channels
|
|
30
28
|
}, json);
|
|
29
|
+
// The `/api/v3/auth` endpoint nests the streaming settings under `config.streaming`. Normalize
|
|
30
|
+
// them into the flat `pushEnabled`/`connDelay` properties used by the PushManager.
|
|
31
|
+
const streaming = credential.config && credential.config.streaming;
|
|
32
|
+
if (streaming) {
|
|
33
|
+
credential.pushEnabled = streaming.enabled;
|
|
34
|
+
credential.connDelay = streaming.delay;
|
|
35
|
+
}
|
|
36
|
+
return credential;
|
|
31
37
|
}
|
|
32
38
|
return json;
|
|
33
39
|
});
|
|
34
40
|
};
|
|
35
41
|
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Returns the hash of a given user key
|
|
39
|
-
*/
|
|
40
|
-
export function hashUserKey(userKey: string): string {
|
|
41
|
-
return encodeToBase64(hash(userKey, 0).toString());
|
|
42
|
-
}
|