@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,31 +1,22 @@
|
|
|
1
1
|
import { FLAG_SPEC_VERSION } from '../../../utils/constants';
|
|
2
2
|
import { base } from '../../../utils/settingsValidation';
|
|
3
|
-
import {
|
|
3
|
+
import { LOG_PREFIX_SYNC_SPLITS } from '../../../logger/constants';
|
|
4
4
|
import { checkIfServerSide } from '../../../utils/key';
|
|
5
5
|
var PROXY_CHECK_INTERVAL_MILLIS_CS = 60 * 60 * 1000; // 1 hour in Client Side
|
|
6
6
|
var PROXY_CHECK_INTERVAL_MILLIS_SS = 24 * PROXY_CHECK_INTERVAL_MILLIS_CS; // 24 hours in Server Side
|
|
7
7
|
function sdkEndpointOverridden(settings) {
|
|
8
8
|
return settings.urls.sdk !== base.urls.sdk;
|
|
9
9
|
}
|
|
10
|
-
function isSplitChangesLegacyResponse(data) {
|
|
11
|
-
return data.splits != null;
|
|
12
|
-
}
|
|
13
|
-
function partitionByStatus(items, till, since) {
|
|
14
|
-
var updated = [], removed = [];
|
|
15
|
-
items.forEach(function (item) { return item.status === 'ARCHIVED' ? removed.push(item.name) : updated.push(item); });
|
|
16
|
-
return { updated: updated, removed: removed, till: till, since: since };
|
|
17
|
-
}
|
|
18
10
|
/**
|
|
19
11
|
* Factory of SplitChanges fetcher.
|
|
20
12
|
* SplitChanges fetcher is a wrapper around `splitChanges` API service that parses the response and handle errors.
|
|
21
13
|
*/
|
|
22
14
|
// @TODO breaking: drop support for Split Proxy below v5.10.0 and simplify the implementation
|
|
23
|
-
export function splitChangesFetcherFactory(
|
|
24
|
-
var fetchSplitChanges = params.serviceApi.fetchSplitChanges, settings = params.settings, storage = params.storage;
|
|
15
|
+
export function splitChangesFetcherFactory(fetchSplitChanges, settings, storage) {
|
|
25
16
|
var log = settings.log;
|
|
26
17
|
var PROXY_CHECK_INTERVAL_MILLIS = checkIfServerSide(settings) ? PROXY_CHECK_INTERVAL_MILLIS_SS : PROXY_CHECK_INTERVAL_MILLIS_CS;
|
|
27
18
|
var lastProxyCheckTimestamp;
|
|
28
|
-
function splitChangesFetcher(since, noCache, till, rbSince,
|
|
19
|
+
return function splitChangesFetcher(since, noCache, till, rbSince,
|
|
29
20
|
// Optional decorator for `fetchSplitChanges` promise, such as timeout or time tracker
|
|
30
21
|
decorator) {
|
|
31
22
|
// Recheck proxy
|
|
@@ -36,7 +27,7 @@ export function splitChangesFetcherFactory(params) {
|
|
|
36
27
|
.catch(function (err) {
|
|
37
28
|
// Handle proxy error with spec 1.3
|
|
38
29
|
if ((!err.statusCode || err.statusCode === 400) && sdkEndpointOverridden(settings) && settings.sync.flagSpecVersion === FLAG_SPEC_VERSION) {
|
|
39
|
-
log.error(
|
|
30
|
+
log.error(LOG_PREFIX_SYNC_SPLITS + 'Proxy error detected. Retrying with spec 1.2. If you are using Split Proxy, please upgrade to latest version');
|
|
40
31
|
lastProxyCheckTimestamp = Date.now();
|
|
41
32
|
settings.sync.flagSpecVersion = '1.2'; // fallback to 1.2 spec
|
|
42
33
|
return fetchSplitChanges(since, noCache, till); // retry request without rbSince
|
|
@@ -49,26 +40,26 @@ export function splitChangesFetcherFactory(params) {
|
|
|
49
40
|
.then(function (resp) { return resp.json(); })
|
|
50
41
|
.then(function (data) {
|
|
51
42
|
// Using flag spec version 1.2 or below
|
|
52
|
-
if (
|
|
53
|
-
return {
|
|
43
|
+
if (data.splits) {
|
|
44
|
+
return {
|
|
45
|
+
ff: {
|
|
46
|
+
d: data.splits,
|
|
47
|
+
s: data.since,
|
|
48
|
+
t: data.till
|
|
49
|
+
}
|
|
50
|
+
};
|
|
54
51
|
}
|
|
55
52
|
// Proxy recovery
|
|
56
53
|
if (lastProxyCheckTimestamp) {
|
|
57
|
-
log.info(
|
|
54
|
+
log.info(LOG_PREFIX_SYNC_SPLITS + 'Proxy error recovered');
|
|
58
55
|
lastProxyCheckTimestamp = undefined;
|
|
59
56
|
return splitChangesFetcher(-1, undefined, undefined, -1)
|
|
60
57
|
.then(function (splitChangesResponse) {
|
|
61
|
-
return Promise.all([storage.
|
|
58
|
+
return Promise.all([storage.splits.clear(), storage.rbSegments.clear()])
|
|
62
59
|
.then(function () { return splitChangesResponse; });
|
|
63
60
|
});
|
|
64
61
|
}
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
d: (ff === null || ff === void 0 ? void 0 : ff.d) ? partitionByStatus(ff.d, ff.t, ff.s) : undefined,
|
|
68
|
-
rbs: (rbs === null || rbs === void 0 ? void 0 : rbs.d) ? partitionByStatus(rbs.d, rbs.t, rbs.s) : undefined,
|
|
69
|
-
};
|
|
62
|
+
return data;
|
|
70
63
|
});
|
|
71
|
-
}
|
|
72
|
-
splitChangesFetcher.type = 'feature flags';
|
|
73
|
-
return splitChangesFetcher;
|
|
64
|
+
};
|
|
74
65
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { forOwn } from '../../utils/lang';
|
|
2
2
|
import { mySegmentsSyncTaskFactory } from './syncTasks/mySegmentsSyncTask';
|
|
3
|
-
import {
|
|
3
|
+
import { splitsSyncTaskFactory } from './syncTasks/splitsSyncTask';
|
|
4
4
|
import { getMatching } from '../../utils/key';
|
|
5
|
-
import {
|
|
5
|
+
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants';
|
|
6
6
|
import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger/constants';
|
|
7
|
-
import { usesSegmentsSync } from '../../storages/
|
|
7
|
+
import { usesSegmentsSync } from '../../storages/AbstractSplitsCacheSync';
|
|
8
8
|
/**
|
|
9
9
|
* Expose start / stop mechanism for polling data from services.
|
|
10
10
|
* For client-side API with multiple clients.
|
|
11
11
|
*/
|
|
12
|
-
export function pollingManagerCSFactory(params
|
|
13
|
-
var
|
|
12
|
+
export function pollingManagerCSFactory(params) {
|
|
13
|
+
var splitApi = params.splitApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
|
|
14
14
|
var log = settings.log;
|
|
15
|
-
var
|
|
15
|
+
var splitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings, true);
|
|
16
16
|
// Map of matching keys to their corresponding MySegmentsSyncTask.
|
|
17
17
|
var mySegmentsSyncTasks = {};
|
|
18
18
|
var matchingKey = getMatching(settings.core.key);
|
|
@@ -29,8 +29,8 @@ export function pollingManagerCSFactory(params, definitionChangesFetcher) {
|
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
// smart pausing
|
|
32
|
-
readiness.
|
|
33
|
-
if (!
|
|
32
|
+
readiness.splits.on(SDK_SPLITS_ARRIVED, function () {
|
|
33
|
+
if (!splitsSyncTask.isRunning())
|
|
34
34
|
return; // noop if not doing polling
|
|
35
35
|
var usingSegments = usesSegmentsSync(storage);
|
|
36
36
|
if (usingSegments !== mySegmentsSyncTask.isRunning()) {
|
|
@@ -44,7 +44,7 @@ export function pollingManagerCSFactory(params, definitionChangesFetcher) {
|
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
function add(matchingKey, readiness, storage) {
|
|
47
|
-
var mySegmentsSyncTask = mySegmentsSyncTaskFactory(
|
|
47
|
+
var mySegmentsSyncTask = mySegmentsSyncTaskFactory(splitApi.fetchMemberships, storage, readiness, settings, matchingKey);
|
|
48
48
|
// smart ready
|
|
49
49
|
function smartReady(metadata) {
|
|
50
50
|
if (!readiness.isReady() && !usesSegmentsSync(storage))
|
|
@@ -53,32 +53,32 @@ export function pollingManagerCSFactory(params, definitionChangesFetcher) {
|
|
|
53
53
|
if (!usesSegmentsSync(storage))
|
|
54
54
|
setTimeout(smartReady, 0);
|
|
55
55
|
else
|
|
56
|
-
readiness.
|
|
56
|
+
readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);
|
|
57
57
|
mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
|
|
58
58
|
return mySegmentsSyncTask;
|
|
59
59
|
}
|
|
60
60
|
return {
|
|
61
|
-
|
|
61
|
+
splitsSyncTask: splitsSyncTask,
|
|
62
62
|
segmentsSyncTask: mySegmentsSyncTask,
|
|
63
63
|
// Start periodic fetching (polling)
|
|
64
64
|
start: function () {
|
|
65
65
|
log.info(POLLING_START);
|
|
66
|
-
|
|
66
|
+
splitsSyncTask.start();
|
|
67
67
|
if (usesSegmentsSync(storage))
|
|
68
68
|
startMySegmentsSyncTasks();
|
|
69
69
|
},
|
|
70
70
|
// Stop periodic fetching (polling)
|
|
71
71
|
stop: function () {
|
|
72
72
|
log.info(POLLING_STOP);
|
|
73
|
-
if (
|
|
74
|
-
|
|
73
|
+
if (splitsSyncTask.isRunning())
|
|
74
|
+
splitsSyncTask.stop();
|
|
75
75
|
stopMySegmentsSyncTasks();
|
|
76
76
|
},
|
|
77
77
|
// Used by SyncManager to know if running in polling mode.
|
|
78
|
-
isRunning:
|
|
79
|
-
// fetch
|
|
78
|
+
isRunning: splitsSyncTask.isRunning,
|
|
79
|
+
// fetch splits and segments
|
|
80
80
|
syncAll: function () {
|
|
81
|
-
var promises = [
|
|
81
|
+
var promises = [splitsSyncTask.execute()];
|
|
82
82
|
forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
|
|
83
83
|
promises.push(mySegmentsSyncTask.execute());
|
|
84
84
|
});
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { splitsSyncTaskFactory } from './syncTasks/splitsSyncTask';
|
|
2
2
|
import { segmentsSyncTaskFactory } from './syncTasks/segmentsSyncTask';
|
|
3
3
|
import { POLLING_START, POLLING_STOP, LOG_PREFIX_SYNC_POLLING } from '../../logger/constants';
|
|
4
4
|
/**
|
|
5
5
|
* Expose start / stop mechanism for pulling data from services.
|
|
6
6
|
*/
|
|
7
|
-
export function pollingManagerSSFactory(params
|
|
8
|
-
var storage = params.storage, readiness = params.readiness, settings = params.settings;
|
|
7
|
+
export function pollingManagerSSFactory(params) {
|
|
8
|
+
var splitApi = params.splitApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
|
|
9
9
|
var log = settings.log;
|
|
10
|
-
var
|
|
11
|
-
var
|
|
10
|
+
var splitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings);
|
|
11
|
+
var segmentsSyncTask = segmentsSyncTaskFactory(splitApi.fetchSegmentChanges, storage, readiness, settings);
|
|
12
12
|
return {
|
|
13
|
-
|
|
13
|
+
splitsSyncTask: splitsSyncTask,
|
|
14
14
|
segmentsSyncTask: segmentsSyncTask,
|
|
15
15
|
// Start periodic fetching (polling)
|
|
16
16
|
start: function () {
|
|
17
17
|
log.info(POLLING_START);
|
|
18
|
-
log.debug(LOG_PREFIX_SYNC_POLLING + "
|
|
19
|
-
log.debug(LOG_PREFIX_SYNC_POLLING + "
|
|
20
|
-
var startingUp =
|
|
18
|
+
log.debug(LOG_PREFIX_SYNC_POLLING + "Splits will be refreshed each ".concat(settings.scheduler.featuresRefreshRate, " millis"));
|
|
19
|
+
log.debug(LOG_PREFIX_SYNC_POLLING + "Segments will be refreshed each ".concat(settings.scheduler.segmentsRefreshRate, " millis"));
|
|
20
|
+
var startingUp = splitsSyncTask.start();
|
|
21
21
|
if (startingUp) {
|
|
22
22
|
startingUp.then(function () {
|
|
23
|
-
if (
|
|
23
|
+
if (splitsSyncTask.isRunning())
|
|
24
24
|
segmentsSyncTask.start();
|
|
25
25
|
});
|
|
26
26
|
}
|
|
@@ -28,16 +28,16 @@ export function pollingManagerSSFactory(params, definitionChangesFetcher, segmen
|
|
|
28
28
|
// Stop periodic fetching (polling)
|
|
29
29
|
stop: function () {
|
|
30
30
|
log.info(POLLING_STOP);
|
|
31
|
-
if (
|
|
32
|
-
|
|
31
|
+
if (splitsSyncTask.isRunning())
|
|
32
|
+
splitsSyncTask.stop();
|
|
33
33
|
if (segmentsSyncTask.isRunning())
|
|
34
34
|
segmentsSyncTask.stop();
|
|
35
35
|
},
|
|
36
36
|
// Used by SyncManager to know if running in polling mode.
|
|
37
|
-
isRunning:
|
|
37
|
+
isRunning: splitsSyncTask.isRunning,
|
|
38
38
|
syncAll: function () {
|
|
39
|
-
// fetch
|
|
40
|
-
return
|
|
39
|
+
// fetch splits and segments. There is no need to catch this promise (`SplitChangesUpdater` is always resolved with a boolean value)
|
|
40
|
+
return splitsSyncTask.execute().then(function () {
|
|
41
41
|
return segmentsSyncTask.execute();
|
|
42
42
|
});
|
|
43
43
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { syncTaskFactory } from '../../syncTask';
|
|
2
|
+
import { segmentChangesFetcherFactory } from '../fetchers/segmentChangesFetcher';
|
|
2
3
|
import { segmentChangesUpdaterFactory } from '../updaters/segmentChangesUpdater';
|
|
3
4
|
/**
|
|
4
5
|
* Creates a sync task that periodically executes a `segmentChangesUpdater` task
|
|
5
6
|
*/
|
|
6
|
-
export function segmentsSyncTaskFactory(
|
|
7
|
-
return syncTaskFactory(settings.log, segmentChangesUpdaterFactory(settings.log,
|
|
7
|
+
export function segmentsSyncTaskFactory(fetchSegmentChanges, storage, readiness, settings) {
|
|
8
|
+
return syncTaskFactory(settings.log, segmentChangesUpdaterFactory(settings.log, segmentChangesFetcherFactory(fetchSegmentChanges), storage.segments, readiness, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady), settings.scheduler.segmentsRefreshRate, 'segmentChangesUpdater');
|
|
8
9
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { syncTaskFactory } from '../../syncTask';
|
|
2
|
+
import { splitChangesFetcherFactory } from '../fetchers/splitChangesFetcher';
|
|
3
|
+
import { splitChangesUpdaterFactory } from '../updaters/splitChangesUpdater';
|
|
4
|
+
/**
|
|
5
|
+
* Creates a sync task that periodically executes a `splitChangesUpdater` task
|
|
6
|
+
*/
|
|
7
|
+
export function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings, isClientSide) {
|
|
8
|
+
return syncTaskFactory(settings.log, splitChangesUpdaterFactory(settings.log, splitChangesFetcherFactory(fetchSplitChanges, settings, storage), storage, settings.sync.__splitFiltersValidation, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, isClientSide), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
|
|
9
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { timeout } from '../../../utils/promise/timeout';
|
|
2
2
|
import { SDK_SEGMENTS_ARRIVED, SEGMENTS_UPDATE } from '../../../readiness/constants';
|
|
3
|
-
import {
|
|
3
|
+
import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
|
|
4
4
|
import { MEMBERSHIPS_LS_UPDATE } from '../../streaming/constants';
|
|
5
|
-
import { usesSegmentsSync } from '../../../storages/
|
|
5
|
+
import { usesSegmentsSync } from '../../../storages/AbstractSplitsCacheSync';
|
|
6
6
|
/**
|
|
7
7
|
* factory of MySegments updater, a task that:
|
|
8
8
|
* - fetches mySegments using `mySegmentsFetcher`
|
|
@@ -53,7 +53,7 @@ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmen
|
|
|
53
53
|
return updaterPromise.catch(function (error) {
|
|
54
54
|
if (startingUp && retriesOnFailureBeforeReady > retry) {
|
|
55
55
|
retry += 1;
|
|
56
|
-
log.warn(
|
|
56
|
+
log.warn(SYNC_MYSEGMENTS_FETCH_RETRY, [retry, error]);
|
|
57
57
|
return _mySegmentsUpdater(retry); // no need to forward `segmentList` and `noCache` params
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SDK_SEGMENTS_ARRIVED, SEGMENTS_UPDATE } from '../../../readiness/constants';
|
|
2
|
-
import { LOG_PREFIX_INSTANTIATION,
|
|
2
|
+
import { LOG_PREFIX_INSTANTIATION, LOG_PREFIX_SYNC_SEGMENTS } from '../../../logger/constants';
|
|
3
3
|
import { timeout } from '../../../utils/promise/timeout';
|
|
4
4
|
/**
|
|
5
5
|
* Factory of SegmentChanges updater, a task that:
|
|
@@ -20,7 +20,7 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
|
|
|
20
20
|
return promise;
|
|
21
21
|
}
|
|
22
22
|
function updateSegment(segmentName, noCache, till, fetchOnlyNew, retries) {
|
|
23
|
-
log.debug("".concat(
|
|
23
|
+
log.debug("".concat(LOG_PREFIX_SYNC_SEGMENTS, "Processing segment ").concat(segmentName));
|
|
24
24
|
var sincePromise = Promise.resolve(segments.getChangeNumber(segmentName));
|
|
25
25
|
return sincePromise.then(function (since) {
|
|
26
26
|
// if fetchOnlyNew flag, avoid processing already fetched segments
|
|
@@ -28,14 +28,14 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
|
|
|
28
28
|
false :
|
|
29
29
|
segmentChangesFetcher(since || -1, segmentName, noCache, till, _promiseDecorator).then(function (changes) {
|
|
30
30
|
return Promise.all(changes.map(function (x) {
|
|
31
|
-
log.debug("".concat(
|
|
31
|
+
log.debug("".concat(LOG_PREFIX_SYNC_SEGMENTS, "Processing ").concat(segmentName, " with till = ").concat(x.till, ". Added: ").concat(x.added.length, ". Removed: ").concat(x.removed.length));
|
|
32
32
|
return segments.update(segmentName, x.added, x.removed, x.till);
|
|
33
33
|
})).then(function (updates) {
|
|
34
34
|
return updates.some(function (update) { return update; });
|
|
35
35
|
});
|
|
36
36
|
}).catch(function (error) {
|
|
37
37
|
if (retries) {
|
|
38
|
-
log.warn("".concat(
|
|
38
|
+
log.warn("".concat(LOG_PREFIX_SYNC_SEGMENTS, "Retrying fetch of segment ").concat(segmentName, " (attempt #").concat(retries, "). Reason: ").concat(error));
|
|
39
39
|
return updateSegment(segmentName, noCache, till, fetchOnlyNew, retries - 1);
|
|
40
40
|
}
|
|
41
41
|
throw error;
|
|
@@ -54,7 +54,7 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
|
|
|
54
54
|
* @param till - till target for the provided segmentName, for CDN bypass.
|
|
55
55
|
*/
|
|
56
56
|
return function segmentChangesUpdater(fetchOnlyNew, segmentName, noCache, till) {
|
|
57
|
-
log.debug("".concat(
|
|
57
|
+
log.debug("".concat(LOG_PREFIX_SYNC_SEGMENTS, "Started segments update"));
|
|
58
58
|
// If not a segment name provided, read list of available segments names to be updated.
|
|
59
59
|
var segmentsPromise = Promise.resolve(segmentName ? [segmentName] : segments.getRegisteredSegments());
|
|
60
60
|
return segmentsPromise.then(function (segmentNames) {
|
|
@@ -63,7 +63,7 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
|
|
|
63
63
|
// if at least one segment fetch succeeded, mark segments ready
|
|
64
64
|
if (shouldUpdateFlags.some(function (update) { return update; }) || readyOnAlreadyExistentState) {
|
|
65
65
|
readyOnAlreadyExistentState = false;
|
|
66
|
-
if (readiness
|
|
66
|
+
if (readiness) {
|
|
67
67
|
var metadata = {
|
|
68
68
|
type: SEGMENTS_UPDATE,
|
|
69
69
|
names: []
|
|
@@ -84,7 +84,7 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
|
|
|
84
84
|
log.error("".concat(LOG_PREFIX_INSTANTIATION, ": you passed a client-side type authorizationKey, please grab an SDK Key from Harness FME UI that is of type server-side."));
|
|
85
85
|
}
|
|
86
86
|
else {
|
|
87
|
-
log.warn("".concat(
|
|
87
|
+
log.warn("".concat(LOG_PREFIX_SYNC_SEGMENTS, "Error while doing fetch of segments. ").concat(error));
|
|
88
88
|
}
|
|
89
89
|
return false;
|
|
90
90
|
});
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { timeout } from '../../../utils/promise/timeout';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { SDK_SPLITS_ARRIVED, FLAGS_UPDATE, SEGMENTS_UPDATE } from '../../../readiness/constants';
|
|
3
|
+
import { SYNC_SPLITS_FETCH, SYNC_SPLITS_UPDATE, SYNC_RBS_UPDATE, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants';
|
|
4
4
|
import { startsWith } from '../../../utils/lang';
|
|
5
5
|
import { IN_RULE_BASED_SEGMENT, IN_SEGMENT, RULE_BASED_SEGMENT, STANDARD_SEGMENT } from '../../../utils/constants';
|
|
6
6
|
import { setToArray } from '../../../utils/lang/sets';
|
|
7
7
|
import { SPLIT_UPDATE } from '../../streaming/constants';
|
|
8
|
+
// Checks that all registered segments have been fetched (changeNumber !== -1 for every segment).
|
|
9
|
+
// Returns a promise that could be rejected.
|
|
10
|
+
// @TODO review together with Segments and MySegments storage APIs
|
|
11
|
+
function checkAllSegmentsExist(segments) {
|
|
12
|
+
var registeredSegments = Promise.resolve(segments.getRegisteredSegments());
|
|
13
|
+
return registeredSegments.then(function (segmentNames) {
|
|
14
|
+
return Promise.all(segmentNames.map(function (segmentName) { return segments.getChangeNumber(segmentName); }))
|
|
15
|
+
.then(function (changeNumbers) { return changeNumbers.every(function (changeNumber) { return changeNumber !== undefined; }); });
|
|
16
|
+
});
|
|
17
|
+
}
|
|
8
18
|
/**
|
|
9
19
|
* Collect segments from a raw FF or RBS definition.
|
|
10
20
|
* Exported for testing purposes.
|
|
@@ -33,117 +43,110 @@ export function parseSegments(ruleEntity, matcherType) {
|
|
|
33
43
|
return segments;
|
|
34
44
|
}
|
|
35
45
|
/**
|
|
36
|
-
* If there are defined filters and one
|
|
46
|
+
* If there are defined filters and one feature flag doesn't match with them, its status is changed to 'ARCHIVE' to avoid storing it
|
|
37
47
|
* If there is `bySet` filter, `byName` and `byPrefix` filters are ignored
|
|
38
48
|
*
|
|
39
|
-
* @param
|
|
49
|
+
* @param featureFlag - feature flag to be evaluated
|
|
40
50
|
* @param filters - splitFiltersValidation bySet | byName
|
|
41
51
|
*/
|
|
42
|
-
function matchFilters(
|
|
52
|
+
function matchFilters(featureFlag, filters) {
|
|
43
53
|
var _a = filters.groupedFilters, setsFilter = _a.bySet, namesFilter = _a.byName, prefixFilter = _a.byPrefix;
|
|
44
54
|
if (setsFilter.length > 0)
|
|
45
|
-
return
|
|
55
|
+
return featureFlag.sets && featureFlag.sets.some(function (featureFlagSet) { return setsFilter.indexOf(featureFlagSet) > -1; });
|
|
46
56
|
var namesFilterConfigured = namesFilter.length > 0;
|
|
47
57
|
var prefixFilterConfigured = prefixFilter.length > 0;
|
|
48
58
|
if (!namesFilterConfigured && !prefixFilterConfigured)
|
|
49
59
|
return true;
|
|
50
|
-
var matchNames = namesFilterConfigured && namesFilter.indexOf(
|
|
51
|
-
var matchPrefix = prefixFilterConfigured && prefixFilter.some(function (prefix) { return startsWith(
|
|
60
|
+
var matchNames = namesFilterConfigured && namesFilter.indexOf(featureFlag.name) > -1;
|
|
61
|
+
var matchPrefix = prefixFilterConfigured && prefixFilter.some(function (prefix) { return startsWith(featureFlag.name, prefix); });
|
|
52
62
|
return matchNames || matchPrefix;
|
|
53
63
|
}
|
|
54
64
|
/**
|
|
55
|
-
* Given the list of
|
|
56
|
-
* i.e., an object with added
|
|
65
|
+
* Given the list of splits from /splitChanges endpoint, it returns the mutations,
|
|
66
|
+
* i.e., an object with added splits, removed splits and used segments.
|
|
57
67
|
* Exported for testing purposes.
|
|
58
68
|
*/
|
|
59
|
-
export function computeMutation(
|
|
60
|
-
return
|
|
61
|
-
if (!filters || matchFilters(ruleEntity, filters)) {
|
|
62
|
-
accum.
|
|
69
|
+
export function computeMutation(rules, segments, filters) {
|
|
70
|
+
return rules.reduce(function (accum, ruleEntity) {
|
|
71
|
+
if (ruleEntity.status !== 'ARCHIVED' && (!filters || matchFilters(ruleEntity, filters))) {
|
|
72
|
+
accum.added.push(ruleEntity);
|
|
63
73
|
parseSegments(ruleEntity).forEach(function (segmentName) {
|
|
64
74
|
segments.add(segmentName);
|
|
65
75
|
});
|
|
66
76
|
}
|
|
67
77
|
else {
|
|
68
|
-
accum.removed.push(ruleEntity
|
|
78
|
+
accum.removed.push(ruleEntity);
|
|
69
79
|
}
|
|
70
80
|
accum.names.push(ruleEntity.name);
|
|
71
81
|
return accum;
|
|
72
|
-
}, {
|
|
73
|
-
}
|
|
74
|
-
function convertInstantUpdateToDefinitionChanges(instantUpdate) {
|
|
75
|
-
var payload = instantUpdate.payload, changeNumber = instantUpdate.changeNumber;
|
|
76
|
-
return payload.status === 'ARCHIVED' ?
|
|
77
|
-
{ till: changeNumber, updated: [], removed: [payload.name] } :
|
|
78
|
-
{ till: changeNumber, updated: [payload], removed: [] };
|
|
82
|
+
}, { added: [], removed: [], names: [] });
|
|
79
83
|
}
|
|
80
84
|
/**
|
|
81
|
-
*
|
|
82
|
-
* - fetches
|
|
83
|
-
* - updates
|
|
84
|
-
* - uses `
|
|
85
|
+
* factory of SplitChanges updater, a task that:
|
|
86
|
+
* - fetches split changes using `splitChangesFetcher`
|
|
87
|
+
* - updates `splitsCache`
|
|
88
|
+
* - uses `splitsEventEmitter` to emit events related to split data updates
|
|
85
89
|
*
|
|
86
90
|
* @param log - Logger instance
|
|
87
|
-
* @param
|
|
88
|
-
* @param
|
|
91
|
+
* @param splitChangesFetcher - Fetcher of `/splitChanges`
|
|
92
|
+
* @param splits - Splits storage, with sync or async methods
|
|
89
93
|
* @param segments - Segments storage, with sync or async methods
|
|
90
|
-
* @param
|
|
94
|
+
* @param splitsEventEmitter - Optional readiness manager. Not required for synchronizer or producer mode.
|
|
91
95
|
* @param requestTimeoutBeforeReady - How long the updater will wait for the request to timeout. Default 0, i.e., never timeout.
|
|
92
|
-
* @param retriesOnFailureBeforeReady - How many retries on `/splitChanges`
|
|
96
|
+
* @param retriesOnFailureBeforeReady - How many retries on `/splitChanges` we the updater do in case of failure or timeout. Default 0, i.e., no retries.
|
|
93
97
|
*/
|
|
94
|
-
export function
|
|
95
|
-
) {
|
|
98
|
+
export function splitChangesUpdaterFactory(log, splitChangesFetcher, storage, splitFiltersValidation, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, isClientSide) {
|
|
96
99
|
if (requestTimeoutBeforeReady === void 0) { requestTimeoutBeforeReady = 0; }
|
|
97
100
|
if (retriesOnFailureBeforeReady === void 0) { retriesOnFailureBeforeReady = 0; }
|
|
98
|
-
var
|
|
101
|
+
var splits = storage.splits, rbSegments = storage.rbSegments, segments = storage.segments;
|
|
99
102
|
var startingUp = true;
|
|
100
|
-
/** timeout decorator for `
|
|
103
|
+
/** timeout decorator for `splitChangesFetcher` promise */
|
|
101
104
|
function _promiseDecorator(promise) {
|
|
102
105
|
if (startingUp && requestTimeoutBeforeReady)
|
|
103
106
|
promise = timeout(requestTimeoutBeforeReady, promise);
|
|
104
107
|
return promise;
|
|
105
108
|
}
|
|
106
109
|
/**
|
|
107
|
-
*
|
|
110
|
+
* SplitChanges updater returns a promise that resolves with a `false` boolean value if it fails to fetch splits or synchronize them with the storage.
|
|
108
111
|
* Returned promise will not be rejected.
|
|
109
112
|
*
|
|
110
113
|
* @param noCache - true to revalidate data to fetch
|
|
111
114
|
* @param till - query param to bypass CDN requests
|
|
112
115
|
*/
|
|
113
|
-
return function
|
|
116
|
+
return function splitChangesUpdater(noCache, till, instantUpdate) {
|
|
114
117
|
/**
|
|
115
|
-
* @param since - current changeNumber at
|
|
118
|
+
* @param since - current changeNumber at splitsCache
|
|
116
119
|
* @param retry - current number of retry attempts
|
|
117
120
|
*/
|
|
118
|
-
function
|
|
121
|
+
function _splitChangesUpdater(sinces, retry) {
|
|
119
122
|
if (retry === void 0) { retry = 0; }
|
|
120
123
|
var since = sinces[0], rbSince = sinces[1];
|
|
121
|
-
log.debug(
|
|
124
|
+
log.debug(SYNC_SPLITS_FETCH, sinces);
|
|
122
125
|
return Promise.resolve(instantUpdate ?
|
|
123
126
|
instantUpdate.type === SPLIT_UPDATE ?
|
|
124
|
-
// IFFU edge case: a change to
|
|
127
|
+
// IFFU edge case: a change to a flag that adds an IN_RULE_BASED_SEGMENT matcher that is not present yet
|
|
125
128
|
Promise.resolve(rbSegments.contains(parseSegments(instantUpdate.payload, IN_RULE_BASED_SEGMENT))).then(function (contains) {
|
|
126
129
|
return contains ?
|
|
127
|
-
{ d:
|
|
128
|
-
|
|
130
|
+
{ ff: { d: [instantUpdate.payload], t: instantUpdate.changeNumber } } :
|
|
131
|
+
splitChangesFetcher(since, noCache, till, rbSince, _promiseDecorator);
|
|
129
132
|
}) :
|
|
130
|
-
{ rbs:
|
|
131
|
-
|
|
132
|
-
.then(function (
|
|
133
|
+
{ rbs: { d: [instantUpdate.payload], t: instantUpdate.changeNumber } } :
|
|
134
|
+
splitChangesFetcher(since, noCache, till, rbSince, _promiseDecorator))
|
|
135
|
+
.then(function (splitChanges) {
|
|
133
136
|
var usedSegments = new Set();
|
|
134
|
-
var
|
|
137
|
+
var updatedFlags = [];
|
|
135
138
|
var ffUpdate = false;
|
|
136
|
-
if (
|
|
137
|
-
var _a = computeMutation(
|
|
138
|
-
|
|
139
|
-
log.debug(
|
|
140
|
-
ffUpdate =
|
|
139
|
+
if (splitChanges.ff) {
|
|
140
|
+
var _a = computeMutation(splitChanges.ff.d || [], usedSegments, splitFiltersValidation), added = _a.added, removed = _a.removed, names = _a.names;
|
|
141
|
+
updatedFlags = names;
|
|
142
|
+
log.debug(SYNC_SPLITS_UPDATE, [added.length, removed.length]);
|
|
143
|
+
ffUpdate = splits.update(added, removed, splitChanges.ff.t);
|
|
141
144
|
}
|
|
142
145
|
var rbsUpdate = false;
|
|
143
|
-
if (
|
|
144
|
-
var _b = computeMutation(
|
|
145
|
-
log.debug(
|
|
146
|
-
rbsUpdate = rbSegments.update(
|
|
146
|
+
if (splitChanges.rbs) {
|
|
147
|
+
var _b = computeMutation(splitChanges.rbs.d || [], usedSegments), added = _b.added, removed = _b.removed;
|
|
148
|
+
log.debug(SYNC_RBS_UPDATE, [added.length, removed.length]);
|
|
149
|
+
rbsUpdate = rbSegments.update(added, removed, splitChanges.rbs.t);
|
|
147
150
|
}
|
|
148
151
|
return Promise.all([ffUpdate, rbsUpdate,
|
|
149
152
|
// @TODO if at least 1 segment fetch fails due to 404 and other segments are updated in the storage, SDK_UPDATE is not emitted
|
|
@@ -153,18 +156,18 @@ export function definitionChangesUpdaterFactory(log, definitionChangesFetcher, s
|
|
|
153
156
|
if (storage.save)
|
|
154
157
|
storage.save();
|
|
155
158
|
startingUp = false;
|
|
156
|
-
if (
|
|
157
|
-
// To emit
|
|
158
|
-
return Promise.resolve(!
|
|
159
|
+
if (splitsEventEmitter) {
|
|
160
|
+
// To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
|
|
161
|
+
return Promise.resolve(!splitsEventEmitter.splitsArrived || ((ffChanged || rbsChanged) && (isClientSide || checkAllSegmentsExist(segments))))
|
|
159
162
|
.catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
|
|
160
163
|
.then(function (emitSplitsArrivedEvent) {
|
|
161
164
|
// emit SDK events
|
|
162
165
|
if (emitSplitsArrivedEvent) {
|
|
163
166
|
var metadata = {
|
|
164
|
-
type:
|
|
165
|
-
names:
|
|
167
|
+
type: updatedFlags.length > 0 ? FLAGS_UPDATE : SEGMENTS_UPDATE,
|
|
168
|
+
names: updatedFlags.length > 0 ? updatedFlags : []
|
|
166
169
|
};
|
|
167
|
-
|
|
170
|
+
splitsEventEmitter.emit(SDK_SPLITS_ARRIVED, metadata);
|
|
168
171
|
}
|
|
169
172
|
return true;
|
|
170
173
|
});
|
|
@@ -175,17 +178,17 @@ export function definitionChangesUpdaterFactory(log, definitionChangesFetcher, s
|
|
|
175
178
|
.catch(function (error) {
|
|
176
179
|
if (startingUp && retriesOnFailureBeforeReady > retry) {
|
|
177
180
|
retry += 1;
|
|
178
|
-
log.warn(
|
|
179
|
-
return
|
|
181
|
+
log.warn(SYNC_SPLITS_FETCH_RETRY, [retry, error]);
|
|
182
|
+
return _splitChangesUpdater(sinces, retry);
|
|
180
183
|
}
|
|
181
184
|
else {
|
|
182
185
|
startingUp = false;
|
|
183
|
-
log.warn(
|
|
186
|
+
log.warn(SYNC_SPLITS_FETCH_FAILS, [error]);
|
|
184
187
|
}
|
|
185
188
|
return false;
|
|
186
189
|
});
|
|
187
190
|
}
|
|
188
191
|
// `getChangeNumber` never rejects or throws error
|
|
189
|
-
return Promise.all([
|
|
192
|
+
return Promise.all([splits.getChangeNumber(), rbSegments.getChangeNumber()]).then(_splitChangesUpdater);
|
|
190
193
|
};
|
|
191
194
|
}
|
|
@@ -5,7 +5,7 @@ import { hash } from '../../../utils/murmur3/murmur3';
|
|
|
5
5
|
/**
|
|
6
6
|
* Factory of authentication function.
|
|
7
7
|
*
|
|
8
|
-
* @param fetchAuth - `
|
|
8
|
+
* @param fetchAuth - `SplitAPI.fetchAuth` endpoint
|
|
9
9
|
*/
|
|
10
10
|
export function authenticateFactory(fetchAuth) {
|
|
11
11
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CONNECTION_ESTABLISHED, DISABLED, ENABLED, OCCUPANCY_PRI, OCCUPANCY_SEC, PAUSED, STREAMING_STATUS } from '../../../utils/constants';
|
|
2
|
-
import { ControlType, PUSH_SUBSYSTEM_UP,
|
|
2
|
+
import { ControlType, PUSH_SUBSYSTEM_UP, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN } from '../constants';
|
|
3
3
|
var CONTROL_CHANNEL_REGEXS = [/control_pri$/, /control_sec$/];
|
|
4
4
|
var STREAMING_EVENT_TYPES = [OCCUPANCY_PRI, OCCUPANCY_SEC];
|
|
5
5
|
/**
|
|
@@ -70,7 +70,7 @@ export function notificationKeeperFactory(pushEmitter, telemetryTracker) {
|
|
|
70
70
|
c.cTime = timestamp;
|
|
71
71
|
if (controlType === ControlType.STREAMING_DISABLED) {
|
|
72
72
|
telemetryTracker.streamingEvent(STREAMING_STATUS, DISABLED);
|
|
73
|
-
pushEmitter.emit(
|
|
73
|
+
pushEmitter.emit(PUSH_NONRETRYABLE_ERROR);
|
|
74
74
|
}
|
|
75
75
|
else if (hasPublishers) {
|
|
76
76
|
if (controlType === ControlType.STREAMING_PAUSED && hasResumed) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { errorParser, messageParser } from './NotificationParser';
|
|
2
2
|
import { notificationKeeperFactory } from './NotificationKeeper';
|
|
3
|
-
import { PUSH_RETRYABLE_ERROR,
|
|
3
|
+
import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, RB_SEGMENT_UPDATE } from '../constants';
|
|
4
4
|
import { STREAMING_PARSING_ERROR_FAILS, ERROR_STREAMING_SSE, STREAMING_PARSING_MESSAGE_FAILS, STREAMING_NEW_MESSAGE } from '../../../logger/constants';
|
|
5
5
|
import { ABLY_ERROR, NON_REQUESTED, SSE_CONNECTION_ERROR } from '../../../utils/constants';
|
|
6
6
|
/**
|
|
@@ -48,7 +48,7 @@ export function SSEHandlerFactory(log, pushEmitter, telemetryTracker) {
|
|
|
48
48
|
pushEmitter.emit(PUSH_RETRYABLE_ERROR);
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
|
-
pushEmitter.emit(
|
|
51
|
+
pushEmitter.emit(PUSH_NONRETRYABLE_ERROR);
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
/* NotificationProcessor */
|