@splitsoftware/splitio-commons 0.1.1-canary.6 → 0.1.1-rc.18
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/cjs/evaluator/matchers/matcherTypes.js +4 -4
- package/cjs/evaluator/matchersTransform/index.js +11 -11
- package/cjs/evaluator/value/sanitize.js +6 -6
- package/cjs/listeners/browser.js +5 -2
- package/cjs/listeners/node.js +9 -2
- package/cjs/logger/constants.js +3 -1
- package/cjs/logger/messages/error.js +3 -2
- package/cjs/logger/messages/info.js +2 -2
- package/cjs/logger/messages/warn.js +2 -1
- package/cjs/readiness/readinessManager.js +10 -7
- package/cjs/sdkFactory/index.js +1 -1
- package/cjs/services/splitApi.js +9 -1
- package/cjs/services/splitHttpClient.js +5 -4
- package/cjs/storages/AbstractSplitsCacheSync.js +1 -1
- package/cjs/storages/inLocalStorage/index.js +5 -2
- package/cjs/storages/inMemory/InMemoryStorage.js +2 -0
- package/cjs/storages/inMemory/InMemoryStorageCS.js +2 -0
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +6 -2
- package/cjs/storages/inRedis/index.js +5 -2
- package/cjs/storages/pluggable/SplitsCachePluggable.js +6 -2
- package/cjs/storages/pluggable/inMemoryWrapper.js +6 -7
- package/cjs/storages/pluggable/index.js +5 -2
- package/cjs/storages/pluggable/wrapperAdapter.js +0 -1
- package/cjs/sync/offline/splitsParser/splitsParserFromFile.js +92 -89
- package/cjs/sync/offline/splitsParser/splitsParserFromSettings.js +45 -42
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +14 -4
- package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +0 -8
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +30 -10
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +2 -4
- package/cjs/sync/streaming/SSEClient/index.js +38 -20
- package/cjs/sync/streaming/SSEHandler/NotificationKeeper.js +7 -0
- package/cjs/sync/streaming/SSEHandler/NotificationParser.js +4 -1
- package/cjs/sync/streaming/SSEHandler/index.js +8 -9
- package/cjs/sync/streaming/SSEHandler/types.js +14 -0
- package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +5 -5
- package/cjs/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -1
- package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +5 -3
- package/cjs/sync/streaming/constants.js +3 -1
- package/cjs/sync/streaming/mySegmentsV2utils.js +75 -0
- package/cjs/sync/streaming/pushManager.js +148 -40
- package/cjs/sync/submitters/metricsSyncTask.js +1 -1
- package/cjs/sync/submitters/submitterSyncTask.js +2 -2
- package/cjs/sync/syncManagerFromFile.js +15 -0
- package/cjs/sync/syncManagerFromObject.js +14 -0
- package/cjs/sync/syncManagerOffline.js +3 -3
- package/cjs/sync/syncManagerOnline.js +18 -5
- package/cjs/sync/syncTask.js +1 -1
- package/cjs/trackers/impressionObserver/ImpressionObserver.js +0 -2
- package/cjs/trackers/impressionObserver/buildKey.js +3 -9
- package/cjs/trackers/impressionObserver/impressionObserverCS.js +2 -2
- package/cjs/trackers/impressionObserver/impressionObserverSS.js +3 -3
- package/cjs/utils/constants/index.js +4 -1
- package/cjs/utils/decompress/index.js +427 -0
- package/cjs/utils/murmur3/{commons.js → common.js} +2 -6
- package/cjs/utils/murmur3/murmur3.js +11 -12
- package/cjs/utils/murmur3/murmur3_128.js +7 -142
- package/cjs/utils/murmur3/murmur3_128_x86.js +154 -0
- package/cjs/utils/murmur3/murmur3_64.js +36 -0
- package/cjs/utils/murmur3/utfx.js +100 -106
- package/cjs/utils/promise/wrapper.js +14 -11
- package/cjs/utils/settingsValidation/index.js +5 -2
- package/cjs/utils/settingsValidation/localhost/index.js +20 -0
- package/cjs/utils/settingsValidation/splitFilters.js +0 -1
- package/cjs/utils/settingsValidation/storage/storageCS.js +18 -8
- package/cjs/utils/settingsValidation/url.js +1 -1
- package/esm/evaluator/matchers/matcherTypes.js +2 -2
- package/esm/evaluator/matchersTransform/index.js +12 -12
- package/esm/evaluator/value/sanitize.js +7 -7
- package/esm/listeners/browser.js +5 -2
- package/esm/listeners/node.js +9 -2
- package/esm/logger/constants.js +2 -0
- package/esm/logger/messages/error.js +3 -2
- package/esm/logger/messages/info.js +2 -2
- package/esm/logger/messages/warn.js +2 -1
- package/esm/readiness/readinessManager.js +10 -7
- package/esm/sdkFactory/index.js +1 -1
- package/esm/services/splitApi.js +9 -1
- package/esm/services/splitHttpClient.js +5 -4
- package/esm/storages/AbstractSplitsCacheSync.js +1 -1
- package/esm/storages/inLocalStorage/index.js +5 -2
- package/esm/storages/inMemory/InMemoryStorage.js +2 -0
- package/esm/storages/inMemory/InMemoryStorageCS.js +2 -0
- package/esm/storages/inRedis/SplitsCacheInRedis.js +6 -2
- package/esm/storages/inRedis/index.js +5 -2
- package/esm/storages/pluggable/SplitsCachePluggable.js +6 -2
- package/esm/storages/pluggable/inMemoryWrapper.js +6 -7
- package/esm/storages/pluggable/index.js +5 -2
- package/esm/storages/pluggable/wrapperAdapter.js +0 -1
- package/esm/sync/offline/splitsParser/splitsParserFromFile.js +90 -88
- package/esm/sync/offline/splitsParser/splitsParserFromSettings.js +43 -41
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +15 -5
- package/esm/sync/polling/fetchers/segmentChangesFetcher.js +0 -8
- package/esm/sync/polling/updaters/mySegmentsUpdater.js +30 -10
- package/esm/sync/polling/updaters/segmentChangesUpdater.js +2 -4
- package/esm/sync/streaming/SSEClient/index.js +38 -20
- package/esm/sync/streaming/SSEHandler/NotificationKeeper.js +7 -0
- package/esm/sync/streaming/SSEHandler/NotificationParser.js +4 -1
- package/esm/sync/streaming/SSEHandler/index.js +9 -10
- package/esm/sync/streaming/SSEHandler/types.js +13 -1
- package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +5 -5
- package/esm/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -1
- package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +5 -3
- package/esm/sync/streaming/constants.js +2 -0
- package/esm/sync/streaming/mySegmentsV2utils.js +69 -0
- package/esm/sync/streaming/pushManager.js +150 -42
- package/esm/sync/submitters/metricsSyncTask.js +1 -1
- package/esm/sync/submitters/submitterSyncTask.js +2 -2
- package/esm/sync/syncManagerFromFile.js +11 -0
- package/esm/sync/syncManagerFromObject.js +10 -0
- package/esm/sync/syncManagerOffline.js +3 -3
- package/esm/sync/syncManagerOnline.js +18 -5
- package/esm/sync/syncTask.js +1 -1
- package/esm/trackers/impressionObserver/ImpressionObserver.js +0 -2
- package/esm/trackers/impressionObserver/buildKey.js +2 -9
- package/esm/trackers/impressionObserver/impressionObserverCS.js +2 -2
- package/esm/trackers/impressionObserver/impressionObserverSS.js +3 -3
- package/esm/utils/constants/index.js +3 -0
- package/esm/utils/decompress/index.js +424 -0
- package/esm/utils/murmur3/{commons.js → common.js} +1 -4
- package/esm/utils/murmur3/murmur3.js +1 -2
- package/esm/utils/murmur3/murmur3_128.js +7 -142
- package/esm/utils/murmur3/murmur3_128_x86.js +150 -0
- package/esm/utils/murmur3/murmur3_64.js +32 -0
- package/esm/utils/murmur3/utfx.js +96 -106
- package/esm/utils/promise/wrapper.js +14 -11
- package/esm/utils/settingsValidation/index.js +5 -2
- package/esm/utils/settingsValidation/localhost/index.js +16 -0
- package/esm/utils/settingsValidation/splitFilters.js +0 -1
- package/esm/utils/settingsValidation/storage/storageCS.js +16 -7
- package/esm/utils/settingsValidation/url.js +1 -1
- package/package.json +5 -5
- package/src/evaluator/matchers/matcherTypes.ts +2 -2
- package/src/evaluator/matchersTransform/index.ts +12 -12
- package/src/evaluator/value/sanitize.ts +7 -7
- package/src/listeners/browser.ts +5 -2
- package/src/listeners/node.ts +14 -2
- package/src/logger/constants.ts +2 -0
- package/src/logger/messages/error.ts +3 -2
- package/src/logger/messages/info.ts +2 -2
- package/src/logger/messages/warn.ts +3 -1
- package/src/readiness/readinessManager.ts +9 -7
- package/src/sdkFactory/index.ts +1 -1
- package/src/sdkFactory/types.ts +4 -5
- package/src/services/splitApi.ts +12 -3
- package/src/services/splitHttpClient.ts +6 -5
- package/src/services/types.ts +7 -3
- package/src/storages/AbstractSplitsCacheSync.ts +1 -1
- package/src/storages/inLocalStorage/index.ts +8 -4
- package/src/storages/inMemory/InMemoryStorage.ts +3 -0
- package/src/storages/inMemory/InMemoryStorageCS.ts +3 -0
- package/src/storages/inRedis/SplitsCacheInRedis.ts +3 -1
- package/src/storages/inRedis/index.ts +8 -4
- package/src/storages/pluggable/SegmentsCachePluggable.ts +1 -1
- package/src/storages/pluggable/SplitsCachePluggable.ts +3 -1
- package/src/storages/pluggable/inMemoryWrapper.ts +6 -7
- package/src/storages/pluggable/index.ts +8 -4
- package/src/storages/pluggable/wrapperAdapter.ts +0 -1
- package/src/storages/types.ts +18 -15
- package/src/sync/offline/splitsParser/splitsParserFromFile.ts +110 -105
- package/src/sync/offline/splitsParser/splitsParserFromSettings.ts +45 -41
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +15 -5
- package/src/sync/polling/fetchers/segmentChangesFetcher.ts +0 -7
- package/src/sync/polling/types.ts +2 -1
- package/src/sync/polling/updaters/mySegmentsUpdater.ts +28 -10
- package/src/sync/polling/updaters/segmentChangesUpdater.ts +2 -3
- package/src/sync/streaming/AuthClient/types.ts +3 -0
- package/src/sync/streaming/SSEClient/index.ts +43 -23
- package/src/sync/streaming/SSEClient/types.ts +0 -1
- package/src/sync/streaming/SSEHandler/NotificationKeeper.ts +8 -0
- package/src/sync/streaming/SSEHandler/NotificationParser.ts +4 -2
- package/src/sync/streaming/SSEHandler/index.ts +11 -20
- package/src/sync/streaming/SSEHandler/types.ts +37 -3
- package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +7 -6
- package/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts +2 -1
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +4 -3
- package/src/sync/streaming/UpdateWorkers/types.ts +1 -1
- package/src/sync/streaming/constants.ts +2 -0
- package/src/sync/streaming/mySegmentsV2utils.ts +77 -0
- package/src/sync/streaming/pushManager.ts +145 -42
- package/src/sync/streaming/types.ts +14 -22
- package/src/sync/submitters/metricsSyncTask.ts +1 -1
- package/src/sync/submitters/submitterSyncTask.ts +2 -1
- package/src/sync/syncManagerFromFile.ts +13 -0
- package/src/sync/syncManagerFromObject.ts +12 -0
- package/src/sync/syncManagerOffline.ts +3 -3
- package/src/sync/syncManagerOnline.ts +19 -5
- package/src/sync/syncTask.ts +1 -1
- package/src/sync/types.ts +3 -1
- package/src/trackers/impressionObserver/ImpressionObserver.ts +4 -6
- package/src/trackers/impressionObserver/buildKey.ts +2 -16
- package/src/trackers/impressionObserver/impressionObserverCS.ts +2 -2
- package/src/trackers/impressionObserver/impressionObserverSS.ts +3 -3
- package/src/types.ts +16 -2
- package/src/utils/constants/index.ts +6 -1
- package/src/utils/decompress/index.ts +429 -0
- package/src/utils/lang/index.ts +1 -1
- package/src/utils/murmur3/{commons.ts → common.ts} +1 -5
- package/src/utils/murmur3/murmur3.ts +5 -5
- package/src/utils/murmur3/murmur3_128.ts +7 -180
- package/src/utils/murmur3/murmur3_128_x86.ts +188 -0
- package/src/utils/murmur3/murmur3_64.ts +36 -0
- package/src/utils/murmur3/utfx.ts +92 -110
- package/src/utils/promise/wrapper.ts +12 -9
- package/src/utils/settingsValidation/index.ts +8 -4
- package/src/utils/settingsValidation/localhost/index.ts +19 -0
- package/src/utils/settingsValidation/splitFilters.ts +0 -1
- package/src/utils/settingsValidation/storage/storageCS.ts +21 -8
- package/src/utils/settingsValidation/types.ts +2 -11
- package/src/utils/settingsValidation/url.ts +1 -1
- package/types/evaluator/matchers/matcherTypes.d.ts +2 -2
- package/types/listeners/browser.d.ts +3 -3
- package/types/listeners/node.d.ts +3 -2
- package/types/logger/constants.d.ts +2 -0
- package/types/sdkFactory/types.d.ts +4 -5
- package/types/services/types.d.ts +4 -0
- package/types/storages/inLocalStorage/index.d.ts +2 -2
- package/types/storages/inMemory/InMemoryStorage.d.ts +3 -0
- package/types/storages/inMemory/InMemoryStorageCS.d.ts +3 -0
- package/types/storages/inRedis/index.d.ts +2 -2
- package/types/storages/pluggable/index.d.ts +2 -2
- package/types/storages/types.d.ts +15 -15
- package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +2 -7
- package/types/sync/offline/splitsParser/splitsParserFromSettings.d.ts +1 -5
- package/types/sync/polling/types.d.ts +2 -1
- package/types/sync/streaming/AuthClient/indexV1.d.ts +12 -0
- package/types/sync/streaming/AuthClient/indexV2.d.ts +8 -0
- package/types/sync/streaming/AuthClient/types.d.ts +2 -0
- package/types/sync/streaming/SSEClient/index.d.ts +9 -12
- package/types/sync/streaming/SSEClient/types.d.ts +0 -1
- package/types/sync/streaming/SSEHandler/NotificationParser.d.ts +3 -2
- package/types/sync/streaming/SSEHandler/types.d.ts +30 -2
- package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +4 -3
- package/types/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.d.ts +2 -1
- package/types/sync/streaming/UpdateWorkers/SplitsUpdateWorker.d.ts +3 -2
- package/types/sync/streaming/UpdateWorkers/types.d.ts +1 -1
- package/types/sync/streaming/constants.d.ts +3 -1
- package/types/sync/streaming/mySegmentsV2utils.d.ts +27 -0
- package/types/sync/streaming/pushManagerNoUsers.d.ts +13 -0
- package/types/sync/streaming/types.d.ts +9 -5
- package/types/sync/submitters/submitterSyncTask.d.ts +1 -1
- package/types/sync/syncManagerFromFile.d.ts +2 -0
- package/types/sync/syncManagerFromObject.d.ts +2 -0
- package/types/sync/syncManagerOffline.d.ts +1 -1
- package/types/sync/syncTask.d.ts +1 -1
- package/types/sync/types.d.ts +2 -0
- package/types/trackers/impressionObserver/ImpressionObserver.d.ts +2 -2
- package/types/trackers/impressionObserver/buildKey.d.ts +1 -1
- package/types/trackers/impressionObserver/impressionObserverCS.d.ts +2 -2
- package/types/trackers/impressionObserver/impressionObserverSS.d.ts +2 -2
- package/types/types.d.ts +16 -2
- package/types/utils/constants/index.d.ts +5 -1
- package/types/utils/decompress/index.d.ts +16 -0
- package/types/utils/lang/index.d.ts +1 -1
- package/types/utils/murmur3/common.d.ts +12 -0
- package/types/utils/murmur3/murmur3.d.ts +2 -2
- package/types/utils/murmur3/murmur3_128.d.ts +5 -0
- package/types/utils/murmur3/murmur3_128_x86.d.ts +7 -0
- package/types/utils/murmur3/murmur3_64.d.ts +10 -0
- package/types/utils/murmur3/utfx.d.ts +24 -6
- package/types/utils/settingsValidation/index.d.ts +3 -2
- package/types/utils/settingsValidation/localhost/index.d.ts +9 -0
- package/types/utils/settingsValidation/storage/storageCS.d.ts +7 -1
- package/types/utils/settingsValidation/types.d.ts +2 -10
- package/cjs/sync/streaming/pushManagerCS.js +0 -178
- package/cjs/sync/streaming/pushManagerSS.js +0 -128
- package/esm/sync/streaming/pushManagerCS.js +0 -174
- package/esm/sync/streaming/pushManagerSS.js +0 -124
- package/src/sync/streaming/pushManagerCS.ts +0 -237
- package/src/sync/streaming/pushManagerSS.ts +0 -177
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var tslib_1 = require("tslib");
|
|
4
|
-
var object_assign_1 = tslib_1.__importDefault(require("object-assign"));
|
|
5
|
-
var constants_1 = require("./constants");
|
|
6
|
-
var Backoff_1 = tslib_1.__importDefault(require("../../utils/Backoff"));
|
|
7
|
-
var SSEHandler_1 = tslib_1.__importDefault(require("./SSEHandler"));
|
|
8
|
-
var MySegmentsUpdateWorker_1 = tslib_1.__importDefault(require("./UpdateWorkers/MySegmentsUpdateWorker"));
|
|
9
|
-
var SplitsUpdateWorker_1 = tslib_1.__importDefault(require("./UpdateWorkers/SplitsUpdateWorker"));
|
|
10
|
-
var AuthClient_1 = require("./AuthClient");
|
|
11
|
-
var lang_1 = require("../../utils/lang");
|
|
12
|
-
var SSEClient_1 = tslib_1.__importDefault(require("./SSEClient"));
|
|
13
|
-
var key_1 = require("../../utils/key");
|
|
14
|
-
var constants_2 = require("../../logger/constants");
|
|
15
|
-
/**
|
|
16
|
-
* PushManager factory for client-side, with support for multiple clients.
|
|
17
|
-
* It assumes settings contains a key.
|
|
18
|
-
*/
|
|
19
|
-
function pushManagerCSFactory(pollingManager, storage, readiness, fetchAuth, platform, settings) {
|
|
20
|
-
var log = settings.log;
|
|
21
|
-
var sseClient;
|
|
22
|
-
try {
|
|
23
|
-
sseClient = new SSEClient_1.default(settings.urls.streaming, platform.getEventSource);
|
|
24
|
-
}
|
|
25
|
-
catch (e) {
|
|
26
|
-
log.warn(constants_2.STREAMING_FALLBACK, [e]);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
var authenticate = AuthClient_1.authenticateFactory(fetchAuth);
|
|
30
|
-
// init feedback loop
|
|
31
|
-
var pushEmitter = new platform.EventEmitter();
|
|
32
|
-
var sseHandler = SSEHandler_1.default(log, pushEmitter);
|
|
33
|
-
sseClient.setEventHandler(sseHandler);
|
|
34
|
-
// [Only for client-side] map of hashes to user keys, to dispatch MY_SEGMENTS_UPDATE events to the corresponding MySegmentsUpdateWorker
|
|
35
|
-
var userKeyHashes = {};
|
|
36
|
-
var userKey = key_1.getMatching(settings.core.key); // matching key of main client
|
|
37
|
-
var hash = AuthClient_1.hashUserKey(userKey);
|
|
38
|
-
userKeyHashes[hash] = userKey;
|
|
39
|
-
// [Only for client-side] map of user keys to their corresponding MySegmentsUpdateWorkers. It has a two-fold intention:
|
|
40
|
-
// - stop workers all together when push is disconnected
|
|
41
|
-
// - keep the current list of user keys to authenticate
|
|
42
|
-
var workers = {};
|
|
43
|
-
// init workers
|
|
44
|
-
var mySegmentsUpdateWorker = new MySegmentsUpdateWorker_1.default(pollingManager.segmentsSyncTask);
|
|
45
|
-
workers[userKey] = mySegmentsUpdateWorker;
|
|
46
|
-
var splitsUpdateWorker = new SplitsUpdateWorker_1.default(storage.splits, pollingManager.splitsSyncTask, readiness.splits);
|
|
47
|
-
// [Only for client-side] variable to flag that a new client was added. It is needed to reconnect streaming.
|
|
48
|
-
var connectForNewClient = false;
|
|
49
|
-
// flag that indicates if `disconnectPush` was called, either by the SyncManager (when the client is destroyed) or by a PUSH_NONRETRYABLE_ERROR error.
|
|
50
|
-
// It is used to halt the `connectPush` process if it was in progress.
|
|
51
|
-
var disconnected;
|
|
52
|
-
/** PushManager functions related to initialization */
|
|
53
|
-
var connectPushRetryBackoff = new Backoff_1.default(connectPush, settings.scheduler.pushRetryBackoffBase);
|
|
54
|
-
var timeoutId;
|
|
55
|
-
function scheduleTokenRefresh(issuedAt, expirationTime) {
|
|
56
|
-
// clear scheduled token refresh if exists (needed when resuming PUSH)
|
|
57
|
-
if (timeoutId)
|
|
58
|
-
clearTimeout(timeoutId);
|
|
59
|
-
// Set token refresh 10 minutes before expirationTime
|
|
60
|
-
var delayInSeconds = expirationTime - issuedAt - constants_1.SECONDS_BEFORE_EXPIRATION;
|
|
61
|
-
log.info(constants_2.STREAMING_REFRESH_TOKEN, [delayInSeconds]);
|
|
62
|
-
timeoutId = setTimeout(connectPush, delayInSeconds * 1000);
|
|
63
|
-
}
|
|
64
|
-
function connectPush() {
|
|
65
|
-
disconnected = false;
|
|
66
|
-
log.info(constants_2.STREAMING_CONNECTING);
|
|
67
|
-
var userKeys = Object.keys(workers); // [Only for client-side]
|
|
68
|
-
authenticate(userKeys).then(function (authData) {
|
|
69
|
-
if (disconnected)
|
|
70
|
-
return;
|
|
71
|
-
// 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
|
|
72
|
-
// close the sseClient in case the org has been bloqued while the instance was connected to streaming
|
|
73
|
-
if (!authData.pushEnabled) {
|
|
74
|
-
log.info(constants_2.STREAMING_DISABLED);
|
|
75
|
-
pushEmitter.emit(constants_1.PUSH_NONRETRYABLE_ERROR);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
// [Only for client-side] don't open SSE connection if a new shared client was added, since it means that a new authentication is taking place
|
|
79
|
-
if (userKeys && userKeys.length < Object.keys(workers).length)
|
|
80
|
-
return;
|
|
81
|
-
// Connect to SSE and schedule refresh token
|
|
82
|
-
var decodedToken = authData.decodedToken;
|
|
83
|
-
sseClient.open(authData);
|
|
84
|
-
scheduleTokenRefresh(decodedToken.iat, decodedToken.exp);
|
|
85
|
-
}).catch(function (error) {
|
|
86
|
-
if (disconnected)
|
|
87
|
-
return;
|
|
88
|
-
log.error(constants_2.ERROR_STREAMING_AUTH, [error.message]);
|
|
89
|
-
// Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side)
|
|
90
|
-
if (error.statusCode >= 400 && error.statusCode < 500) {
|
|
91
|
-
pushEmitter.emit(constants_1.PUSH_NONRETRYABLE_ERROR);
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
// Handle other HTTP and network errors as recoverable errors
|
|
95
|
-
pushEmitter.emit(constants_1.PUSH_RETRYABLE_ERROR);
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
// close SSE connection and cancel scheduled tasks
|
|
99
|
-
function disconnectPush() {
|
|
100
|
-
disconnected = true;
|
|
101
|
-
log.info(constants_2.STREAMING_DISCONNECTING);
|
|
102
|
-
sseClient.close();
|
|
103
|
-
if (timeoutId)
|
|
104
|
-
clearTimeout(timeoutId);
|
|
105
|
-
connectPushRetryBackoff.reset();
|
|
106
|
-
stopWorkers();
|
|
107
|
-
}
|
|
108
|
-
// cancel scheduled fetch retries of Splits, Segments, and MySegments Update Workers
|
|
109
|
-
function stopWorkers() {
|
|
110
|
-
splitsUpdateWorker.backoff.reset();
|
|
111
|
-
lang_1.forOwn(workers, function (worker) { return worker.backoff.reset(); });
|
|
112
|
-
}
|
|
113
|
-
pushEmitter.on(constants_1.PUSH_SUBSYSTEM_DOWN, stopWorkers);
|
|
114
|
-
// restart backoff retry counter once push is connected
|
|
115
|
-
pushEmitter.on(constants_1.PUSH_SUBSYSTEM_UP, function () { connectPushRetryBackoff.reset(); });
|
|
116
|
-
/** Fallbacking without retry due to: STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE and Authentication errors */
|
|
117
|
-
pushEmitter.on(constants_1.PUSH_NONRETRYABLE_ERROR, function handleNonRetryableError() {
|
|
118
|
-
// Note: `stopWorkers` is been called twice, but it is not harmful
|
|
119
|
-
disconnectPush();
|
|
120
|
-
pushEmitter.emit(constants_1.PUSH_SUBSYSTEM_DOWN); // no harm if polling already
|
|
121
|
-
});
|
|
122
|
-
/** Fallbacking with retry due to recoverable SSE and Authentication errors */
|
|
123
|
-
pushEmitter.on(constants_1.PUSH_RETRYABLE_ERROR, function handleRetryableError() {
|
|
124
|
-
// SSE connection is closed to avoid repeated errors due to retries
|
|
125
|
-
sseClient.close();
|
|
126
|
-
// retry streaming reconnect with backoff algorithm
|
|
127
|
-
var delayInMillis = connectPushRetryBackoff.scheduleCall();
|
|
128
|
-
log.info(constants_2.STREAMING_RECONNECT, [delayInMillis / 1000]);
|
|
129
|
-
pushEmitter.emit(constants_1.PUSH_SUBSYSTEM_DOWN); // no harm if polling already
|
|
130
|
-
});
|
|
131
|
-
/** Functions related to synchronization (Queues and Workers in the spec) */
|
|
132
|
-
pushEmitter.on(constants_1.SPLIT_KILL, splitsUpdateWorker.killSplit);
|
|
133
|
-
pushEmitter.on(constants_1.SPLIT_UPDATE, splitsUpdateWorker.put);
|
|
134
|
-
// [Only for client-side]
|
|
135
|
-
pushEmitter.on(constants_1.MY_SEGMENTS_UPDATE, function handleMySegmentsUpdate(parsedData, channel) {
|
|
136
|
-
var userKeyHash = channel.split('_')[2];
|
|
137
|
-
var userKey = userKeyHashes[userKeyHash];
|
|
138
|
-
if (userKey && workers[userKey]) { // check context since it can be undefined if client has been destroyed
|
|
139
|
-
var mySegmentsUpdateWorker_1 = workers[userKey];
|
|
140
|
-
mySegmentsUpdateWorker_1.put(parsedData.changeNumber, parsedData.includesPayload ? parsedData.segmentList ? parsedData.segmentList : [] : undefined);
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
return object_assign_1.default(
|
|
144
|
-
// Expose Event Emitter functionality and Event constants
|
|
145
|
-
Object.create(pushEmitter), {
|
|
146
|
-
// Expose functionality for starting and stoping push mode:
|
|
147
|
-
stop: disconnectPush,
|
|
148
|
-
start: function () {
|
|
149
|
-
// Run in next event-loop cycle for optimization: if multiple clients are created in the same cycle than the factory, only one authentication is performed.
|
|
150
|
-
setTimeout(connectPush);
|
|
151
|
-
},
|
|
152
|
-
// [Only for client-side]
|
|
153
|
-
add: function (userKey, mySegmentsSyncTask) {
|
|
154
|
-
var mySegmentsUpdateWorker = new MySegmentsUpdateWorker_1.default(mySegmentsSyncTask);
|
|
155
|
-
workers[userKey] = mySegmentsUpdateWorker;
|
|
156
|
-
var hash = AuthClient_1.hashUserKey(userKey);
|
|
157
|
-
if (!userKeyHashes[hash]) {
|
|
158
|
-
userKeyHashes[hash] = userKey;
|
|
159
|
-
connectForNewClient = true; // we must reconnect on start, to listen the channel for the new user key
|
|
160
|
-
}
|
|
161
|
-
// Reconnects in case of a new client.
|
|
162
|
-
// Run in next event-loop cycle to save authentication calls
|
|
163
|
-
// in case the user is creating several clients in the current cycle.
|
|
164
|
-
setTimeout(function checkForReconnect() {
|
|
165
|
-
if (connectForNewClient) {
|
|
166
|
-
connectForNewClient = false;
|
|
167
|
-
connectPush();
|
|
168
|
-
}
|
|
169
|
-
}, 0);
|
|
170
|
-
},
|
|
171
|
-
// [Only for client-side]
|
|
172
|
-
remove: function (userKey) {
|
|
173
|
-
var hash = AuthClient_1.hashUserKey(userKey);
|
|
174
|
-
delete userKeyHashes[hash];
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
exports.default = pushManagerCSFactory;
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var tslib_1 = require("tslib");
|
|
4
|
-
var object_assign_1 = tslib_1.__importDefault(require("object-assign"));
|
|
5
|
-
var constants_1 = require("./constants");
|
|
6
|
-
var Backoff_1 = tslib_1.__importDefault(require("../../utils/Backoff"));
|
|
7
|
-
var SSEHandler_1 = tslib_1.__importDefault(require("./SSEHandler"));
|
|
8
|
-
var SegmentsUpdateWorker_1 = tslib_1.__importDefault(require("./UpdateWorkers/SegmentsUpdateWorker"));
|
|
9
|
-
var SplitsUpdateWorker_1 = tslib_1.__importDefault(require("./UpdateWorkers/SplitsUpdateWorker"));
|
|
10
|
-
var AuthClient_1 = require("./AuthClient");
|
|
11
|
-
var SSEClient_1 = tslib_1.__importDefault(require("./SSEClient"));
|
|
12
|
-
var constants_2 = require("../../logger/constants");
|
|
13
|
-
/**
|
|
14
|
-
* PushManager factory for server-side
|
|
15
|
-
*/
|
|
16
|
-
function pushManagerSSFactory(pollingManager, storage, readiness, fetchAuth, platform, settings) {
|
|
17
|
-
var log = settings.log;
|
|
18
|
-
var sseClient;
|
|
19
|
-
try {
|
|
20
|
-
sseClient = new SSEClient_1.default(settings.urls.streaming, platform.getEventSource);
|
|
21
|
-
}
|
|
22
|
-
catch (e) {
|
|
23
|
-
log.warn(constants_2.STREAMING_FALLBACK, [e]);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
var authenticate = AuthClient_1.authenticateFactory(fetchAuth);
|
|
27
|
-
// init feedback loop (pushEmitter)
|
|
28
|
-
var pushEmitter = new platform.EventEmitter();
|
|
29
|
-
var sseHandler = SSEHandler_1.default(log, pushEmitter);
|
|
30
|
-
sseClient.setEventHandler(sseHandler);
|
|
31
|
-
// init workers
|
|
32
|
-
var splitsUpdateWorker = new SplitsUpdateWorker_1.default(storage.splits, pollingManager.splitsSyncTask, readiness.splits, pollingManager.segmentsSyncTask);
|
|
33
|
-
var segmentsUpdateWorker = new SegmentsUpdateWorker_1.default(storage.segments, pollingManager.segmentsSyncTask);
|
|
34
|
-
// flag that indicates if `disconnectPush` was called, either by the SyncManager (when the client is destroyed) or by a PUSH_NONRETRYABLE_ERROR error.
|
|
35
|
-
// It is used to halt the `connectPush` process if it was in progress.
|
|
36
|
-
var disconnected;
|
|
37
|
-
/** PushManager functions related to initialization */
|
|
38
|
-
var connectPushRetryBackoff = new Backoff_1.default(connectPush, settings.scheduler.pushRetryBackoffBase);
|
|
39
|
-
var timeoutId;
|
|
40
|
-
function scheduleTokenRefresh(issuedAt, expirationTime) {
|
|
41
|
-
// clear scheduled token refresh if exists (needed when resuming PUSH)
|
|
42
|
-
if (timeoutId)
|
|
43
|
-
clearTimeout(timeoutId);
|
|
44
|
-
// Set token refresh 10 minutes before expirationTime
|
|
45
|
-
var delayInSeconds = expirationTime - issuedAt - constants_1.SECONDS_BEFORE_EXPIRATION;
|
|
46
|
-
log.info(constants_2.STREAMING_REFRESH_TOKEN, [delayInSeconds]);
|
|
47
|
-
timeoutId = setTimeout(connectPush, delayInSeconds * 1000);
|
|
48
|
-
}
|
|
49
|
-
function connectPush() {
|
|
50
|
-
disconnected = false;
|
|
51
|
-
log.info(constants_2.STREAMING_CONNECTING);
|
|
52
|
-
authenticate().then(function (authData) {
|
|
53
|
-
if (disconnected)
|
|
54
|
-
return;
|
|
55
|
-
// 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
|
|
56
|
-
// close the sseClient in case the org has been bloqued while the instance was connected to streaming
|
|
57
|
-
if (!authData.pushEnabled) {
|
|
58
|
-
log.info(constants_2.STREAMING_DISABLED);
|
|
59
|
-
pushEmitter.emit(constants_1.PUSH_NONRETRYABLE_ERROR);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
// Connect to SSE and schedule refresh token
|
|
63
|
-
var decodedToken = authData.decodedToken;
|
|
64
|
-
sseClient.open(authData);
|
|
65
|
-
scheduleTokenRefresh(decodedToken.iat, decodedToken.exp);
|
|
66
|
-
}).catch(function (error) {
|
|
67
|
-
if (disconnected)
|
|
68
|
-
return;
|
|
69
|
-
log.error(constants_2.ERROR_STREAMING_AUTH, [error.message]);
|
|
70
|
-
// Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side)
|
|
71
|
-
if (error.statusCode >= 400 && error.statusCode < 500) {
|
|
72
|
-
pushEmitter.emit(constants_1.PUSH_NONRETRYABLE_ERROR);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
// Handle other HTTP and network errors as recoverable errors
|
|
76
|
-
pushEmitter.emit(constants_1.PUSH_RETRYABLE_ERROR);
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
// close SSE connection and cancel scheduled tasks
|
|
80
|
-
function disconnectPush() {
|
|
81
|
-
disconnected = true;
|
|
82
|
-
log.info(constants_2.STREAMING_DISCONNECTING);
|
|
83
|
-
sseClient.close();
|
|
84
|
-
if (timeoutId)
|
|
85
|
-
clearTimeout(timeoutId);
|
|
86
|
-
connectPushRetryBackoff.reset();
|
|
87
|
-
stopWorkers();
|
|
88
|
-
}
|
|
89
|
-
// cancel scheduled fetch retries of Splits, Segments, and MySegments Update Workers
|
|
90
|
-
function stopWorkers() {
|
|
91
|
-
splitsUpdateWorker.backoff.reset();
|
|
92
|
-
segmentsUpdateWorker.backoff.reset();
|
|
93
|
-
}
|
|
94
|
-
pushEmitter.on(constants_1.PUSH_SUBSYSTEM_DOWN, stopWorkers);
|
|
95
|
-
// restart backoff retry counter once push is connected
|
|
96
|
-
pushEmitter.on(constants_1.PUSH_SUBSYSTEM_UP, function () { connectPushRetryBackoff.reset(); });
|
|
97
|
-
/** Fallbacking without retry due to: STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE and Authentication errors */
|
|
98
|
-
pushEmitter.on(constants_1.PUSH_NONRETRYABLE_ERROR, function handleNonRetryableError() {
|
|
99
|
-
// Note: `stopWorkers` is been called twice, but it is not harmful
|
|
100
|
-
disconnectPush();
|
|
101
|
-
pushEmitter.emit(constants_1.PUSH_SUBSYSTEM_DOWN); // no harm if polling already
|
|
102
|
-
});
|
|
103
|
-
/** Fallbacking with retry due to recoverable SSE and Authentication errors */
|
|
104
|
-
pushEmitter.on(constants_1.PUSH_RETRYABLE_ERROR, function handleRetryableError() {
|
|
105
|
-
// SSE connection is closed to avoid repeated errors due to retries
|
|
106
|
-
sseClient.close();
|
|
107
|
-
// retry streaming reconnect with backoff algorithm
|
|
108
|
-
var delayInMillis = connectPushRetryBackoff.scheduleCall();
|
|
109
|
-
log.info(constants_2.STREAMING_RECONNECT, [delayInMillis / 1000]);
|
|
110
|
-
pushEmitter.emit(constants_1.PUSH_SUBSYSTEM_DOWN); // no harm if polling already
|
|
111
|
-
});
|
|
112
|
-
/** Functions related to synchronization (Queues and Workers in the spec) */
|
|
113
|
-
pushEmitter.on(constants_1.SPLIT_KILL, splitsUpdateWorker.killSplit);
|
|
114
|
-
pushEmitter.on(constants_1.SPLIT_UPDATE, splitsUpdateWorker.put);
|
|
115
|
-
// [Only for server-side]
|
|
116
|
-
pushEmitter.on(constants_1.SEGMENT_UPDATE, segmentsUpdateWorker.put);
|
|
117
|
-
return object_assign_1.default(
|
|
118
|
-
// Expose Event Emitter functionality and Event constants
|
|
119
|
-
Object.create(pushEmitter), {
|
|
120
|
-
// Expose functionality for starting and stoping push mode:
|
|
121
|
-
stop: disconnectPush,
|
|
122
|
-
start: function () {
|
|
123
|
-
// Run in next event-loop cycle as in browser
|
|
124
|
-
setTimeout(connectPush);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
exports.default = pushManagerSSFactory;
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import objectAssign from 'object-assign';
|
|
2
|
-
import { MY_SEGMENTS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP } from './constants';
|
|
3
|
-
import Backoff from '../../utils/Backoff';
|
|
4
|
-
import SSEHandlerFactory from './SSEHandler';
|
|
5
|
-
import MySegmentsUpdateWorker from './UpdateWorkers/MySegmentsUpdateWorker';
|
|
6
|
-
import SplitsUpdateWorker from './UpdateWorkers/SplitsUpdateWorker';
|
|
7
|
-
import { authenticateFactory, hashUserKey } from './AuthClient';
|
|
8
|
-
import { forOwn } from '../../utils/lang';
|
|
9
|
-
import SSEClient from './SSEClient';
|
|
10
|
-
import { getMatching } from '../../utils/key';
|
|
11
|
-
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT } from '../../logger/constants';
|
|
12
|
-
/**
|
|
13
|
-
* PushManager factory for client-side, with support for multiple clients.
|
|
14
|
-
* It assumes settings contains a key.
|
|
15
|
-
*/
|
|
16
|
-
export default function pushManagerCSFactory(pollingManager, storage, readiness, fetchAuth, platform, settings) {
|
|
17
|
-
var log = settings.log;
|
|
18
|
-
var sseClient;
|
|
19
|
-
try {
|
|
20
|
-
sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource);
|
|
21
|
-
}
|
|
22
|
-
catch (e) {
|
|
23
|
-
log.warn(STREAMING_FALLBACK, [e]);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
var authenticate = authenticateFactory(fetchAuth);
|
|
27
|
-
// init feedback loop
|
|
28
|
-
var pushEmitter = new platform.EventEmitter();
|
|
29
|
-
var sseHandler = SSEHandlerFactory(log, pushEmitter);
|
|
30
|
-
sseClient.setEventHandler(sseHandler);
|
|
31
|
-
// [Only for client-side] map of hashes to user keys, to dispatch MY_SEGMENTS_UPDATE events to the corresponding MySegmentsUpdateWorker
|
|
32
|
-
var userKeyHashes = {};
|
|
33
|
-
var userKey = getMatching(settings.core.key); // matching key of main client
|
|
34
|
-
var hash = hashUserKey(userKey);
|
|
35
|
-
userKeyHashes[hash] = userKey;
|
|
36
|
-
// [Only for client-side] map of user keys to their corresponding MySegmentsUpdateWorkers. It has a two-fold intention:
|
|
37
|
-
// - stop workers all together when push is disconnected
|
|
38
|
-
// - keep the current list of user keys to authenticate
|
|
39
|
-
var workers = {};
|
|
40
|
-
// init workers
|
|
41
|
-
var mySegmentsUpdateWorker = new MySegmentsUpdateWorker(pollingManager.segmentsSyncTask);
|
|
42
|
-
workers[userKey] = mySegmentsUpdateWorker;
|
|
43
|
-
var splitsUpdateWorker = new SplitsUpdateWorker(storage.splits, pollingManager.splitsSyncTask, readiness.splits);
|
|
44
|
-
// [Only for client-side] variable to flag that a new client was added. It is needed to reconnect streaming.
|
|
45
|
-
var connectForNewClient = false;
|
|
46
|
-
// flag that indicates if `disconnectPush` was called, either by the SyncManager (when the client is destroyed) or by a PUSH_NONRETRYABLE_ERROR error.
|
|
47
|
-
// It is used to halt the `connectPush` process if it was in progress.
|
|
48
|
-
var disconnected;
|
|
49
|
-
/** PushManager functions related to initialization */
|
|
50
|
-
var connectPushRetryBackoff = new Backoff(connectPush, settings.scheduler.pushRetryBackoffBase);
|
|
51
|
-
var timeoutId;
|
|
52
|
-
function scheduleTokenRefresh(issuedAt, expirationTime) {
|
|
53
|
-
// clear scheduled token refresh if exists (needed when resuming PUSH)
|
|
54
|
-
if (timeoutId)
|
|
55
|
-
clearTimeout(timeoutId);
|
|
56
|
-
// Set token refresh 10 minutes before expirationTime
|
|
57
|
-
var delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION;
|
|
58
|
-
log.info(STREAMING_REFRESH_TOKEN, [delayInSeconds]);
|
|
59
|
-
timeoutId = setTimeout(connectPush, delayInSeconds * 1000);
|
|
60
|
-
}
|
|
61
|
-
function connectPush() {
|
|
62
|
-
disconnected = false;
|
|
63
|
-
log.info(STREAMING_CONNECTING);
|
|
64
|
-
var userKeys = Object.keys(workers); // [Only for client-side]
|
|
65
|
-
authenticate(userKeys).then(function (authData) {
|
|
66
|
-
if (disconnected)
|
|
67
|
-
return;
|
|
68
|
-
// 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
|
|
69
|
-
// close the sseClient in case the org has been bloqued while the instance was connected to streaming
|
|
70
|
-
if (!authData.pushEnabled) {
|
|
71
|
-
log.info(STREAMING_DISABLED);
|
|
72
|
-
pushEmitter.emit(PUSH_NONRETRYABLE_ERROR);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
// [Only for client-side] don't open SSE connection if a new shared client was added, since it means that a new authentication is taking place
|
|
76
|
-
if (userKeys && userKeys.length < Object.keys(workers).length)
|
|
77
|
-
return;
|
|
78
|
-
// Connect to SSE and schedule refresh token
|
|
79
|
-
var decodedToken = authData.decodedToken;
|
|
80
|
-
sseClient.open(authData);
|
|
81
|
-
scheduleTokenRefresh(decodedToken.iat, decodedToken.exp);
|
|
82
|
-
}).catch(function (error) {
|
|
83
|
-
if (disconnected)
|
|
84
|
-
return;
|
|
85
|
-
log.error(ERROR_STREAMING_AUTH, [error.message]);
|
|
86
|
-
// Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side)
|
|
87
|
-
if (error.statusCode >= 400 && error.statusCode < 500) {
|
|
88
|
-
pushEmitter.emit(PUSH_NONRETRYABLE_ERROR);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
// Handle other HTTP and network errors as recoverable errors
|
|
92
|
-
pushEmitter.emit(PUSH_RETRYABLE_ERROR);
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
// close SSE connection and cancel scheduled tasks
|
|
96
|
-
function disconnectPush() {
|
|
97
|
-
disconnected = true;
|
|
98
|
-
log.info(STREAMING_DISCONNECTING);
|
|
99
|
-
sseClient.close();
|
|
100
|
-
if (timeoutId)
|
|
101
|
-
clearTimeout(timeoutId);
|
|
102
|
-
connectPushRetryBackoff.reset();
|
|
103
|
-
stopWorkers();
|
|
104
|
-
}
|
|
105
|
-
// cancel scheduled fetch retries of Splits, Segments, and MySegments Update Workers
|
|
106
|
-
function stopWorkers() {
|
|
107
|
-
splitsUpdateWorker.backoff.reset();
|
|
108
|
-
forOwn(workers, function (worker) { return worker.backoff.reset(); });
|
|
109
|
-
}
|
|
110
|
-
pushEmitter.on(PUSH_SUBSYSTEM_DOWN, stopWorkers);
|
|
111
|
-
// restart backoff retry counter once push is connected
|
|
112
|
-
pushEmitter.on(PUSH_SUBSYSTEM_UP, function () { connectPushRetryBackoff.reset(); });
|
|
113
|
-
/** Fallbacking without retry due to: STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE and Authentication errors */
|
|
114
|
-
pushEmitter.on(PUSH_NONRETRYABLE_ERROR, function handleNonRetryableError() {
|
|
115
|
-
// Note: `stopWorkers` is been called twice, but it is not harmful
|
|
116
|
-
disconnectPush();
|
|
117
|
-
pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already
|
|
118
|
-
});
|
|
119
|
-
/** Fallbacking with retry due to recoverable SSE and Authentication errors */
|
|
120
|
-
pushEmitter.on(PUSH_RETRYABLE_ERROR, function handleRetryableError() {
|
|
121
|
-
// SSE connection is closed to avoid repeated errors due to retries
|
|
122
|
-
sseClient.close();
|
|
123
|
-
// retry streaming reconnect with backoff algorithm
|
|
124
|
-
var delayInMillis = connectPushRetryBackoff.scheduleCall();
|
|
125
|
-
log.info(STREAMING_RECONNECT, [delayInMillis / 1000]);
|
|
126
|
-
pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already
|
|
127
|
-
});
|
|
128
|
-
/** Functions related to synchronization (Queues and Workers in the spec) */
|
|
129
|
-
pushEmitter.on(SPLIT_KILL, splitsUpdateWorker.killSplit);
|
|
130
|
-
pushEmitter.on(SPLIT_UPDATE, splitsUpdateWorker.put);
|
|
131
|
-
// [Only for client-side]
|
|
132
|
-
pushEmitter.on(MY_SEGMENTS_UPDATE, function handleMySegmentsUpdate(parsedData, channel) {
|
|
133
|
-
var userKeyHash = channel.split('_')[2];
|
|
134
|
-
var userKey = userKeyHashes[userKeyHash];
|
|
135
|
-
if (userKey && workers[userKey]) { // check context since it can be undefined if client has been destroyed
|
|
136
|
-
var mySegmentsUpdateWorker_1 = workers[userKey];
|
|
137
|
-
mySegmentsUpdateWorker_1.put(parsedData.changeNumber, parsedData.includesPayload ? parsedData.segmentList ? parsedData.segmentList : [] : undefined);
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
return objectAssign(
|
|
141
|
-
// Expose Event Emitter functionality and Event constants
|
|
142
|
-
Object.create(pushEmitter), {
|
|
143
|
-
// Expose functionality for starting and stoping push mode:
|
|
144
|
-
stop: disconnectPush,
|
|
145
|
-
start: function () {
|
|
146
|
-
// Run in next event-loop cycle for optimization: if multiple clients are created in the same cycle than the factory, only one authentication is performed.
|
|
147
|
-
setTimeout(connectPush);
|
|
148
|
-
},
|
|
149
|
-
// [Only for client-side]
|
|
150
|
-
add: function (userKey, mySegmentsSyncTask) {
|
|
151
|
-
var mySegmentsUpdateWorker = new MySegmentsUpdateWorker(mySegmentsSyncTask);
|
|
152
|
-
workers[userKey] = mySegmentsUpdateWorker;
|
|
153
|
-
var hash = hashUserKey(userKey);
|
|
154
|
-
if (!userKeyHashes[hash]) {
|
|
155
|
-
userKeyHashes[hash] = userKey;
|
|
156
|
-
connectForNewClient = true; // we must reconnect on start, to listen the channel for the new user key
|
|
157
|
-
}
|
|
158
|
-
// Reconnects in case of a new client.
|
|
159
|
-
// Run in next event-loop cycle to save authentication calls
|
|
160
|
-
// in case the user is creating several clients in the current cycle.
|
|
161
|
-
setTimeout(function checkForReconnect() {
|
|
162
|
-
if (connectForNewClient) {
|
|
163
|
-
connectForNewClient = false;
|
|
164
|
-
connectPush();
|
|
165
|
-
}
|
|
166
|
-
}, 0);
|
|
167
|
-
},
|
|
168
|
-
// [Only for client-side]
|
|
169
|
-
remove: function (userKey) {
|
|
170
|
-
var hash = hashUserKey(userKey);
|
|
171
|
-
delete userKeyHashes[hash];
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import objectAssign from 'object-assign';
|
|
2
|
-
import { PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP } from './constants';
|
|
3
|
-
import Backoff from '../../utils/Backoff';
|
|
4
|
-
import SSEHandlerFactory from './SSEHandler';
|
|
5
|
-
import SegmentsUpdateWorker from './UpdateWorkers/SegmentsUpdateWorker';
|
|
6
|
-
import SplitsUpdateWorker from './UpdateWorkers/SplitsUpdateWorker';
|
|
7
|
-
import { authenticateFactory } from './AuthClient';
|
|
8
|
-
import SSEClient from './SSEClient';
|
|
9
|
-
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT } from '../../logger/constants';
|
|
10
|
-
/**
|
|
11
|
-
* PushManager factory for server-side
|
|
12
|
-
*/
|
|
13
|
-
export default function pushManagerSSFactory(pollingManager, storage, readiness, fetchAuth, platform, settings) {
|
|
14
|
-
var log = settings.log;
|
|
15
|
-
var sseClient;
|
|
16
|
-
try {
|
|
17
|
-
sseClient = new SSEClient(settings.urls.streaming, platform.getEventSource);
|
|
18
|
-
}
|
|
19
|
-
catch (e) {
|
|
20
|
-
log.warn(STREAMING_FALLBACK, [e]);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
var authenticate = authenticateFactory(fetchAuth);
|
|
24
|
-
// init feedback loop (pushEmitter)
|
|
25
|
-
var pushEmitter = new platform.EventEmitter();
|
|
26
|
-
var sseHandler = SSEHandlerFactory(log, pushEmitter);
|
|
27
|
-
sseClient.setEventHandler(sseHandler);
|
|
28
|
-
// init workers
|
|
29
|
-
var splitsUpdateWorker = new SplitsUpdateWorker(storage.splits, pollingManager.splitsSyncTask, readiness.splits, pollingManager.segmentsSyncTask);
|
|
30
|
-
var segmentsUpdateWorker = new SegmentsUpdateWorker(storage.segments, pollingManager.segmentsSyncTask);
|
|
31
|
-
// flag that indicates if `disconnectPush` was called, either by the SyncManager (when the client is destroyed) or by a PUSH_NONRETRYABLE_ERROR error.
|
|
32
|
-
// It is used to halt the `connectPush` process if it was in progress.
|
|
33
|
-
var disconnected;
|
|
34
|
-
/** PushManager functions related to initialization */
|
|
35
|
-
var connectPushRetryBackoff = new Backoff(connectPush, settings.scheduler.pushRetryBackoffBase);
|
|
36
|
-
var timeoutId;
|
|
37
|
-
function scheduleTokenRefresh(issuedAt, expirationTime) {
|
|
38
|
-
// clear scheduled token refresh if exists (needed when resuming PUSH)
|
|
39
|
-
if (timeoutId)
|
|
40
|
-
clearTimeout(timeoutId);
|
|
41
|
-
// Set token refresh 10 minutes before expirationTime
|
|
42
|
-
var delayInSeconds = expirationTime - issuedAt - SECONDS_BEFORE_EXPIRATION;
|
|
43
|
-
log.info(STREAMING_REFRESH_TOKEN, [delayInSeconds]);
|
|
44
|
-
timeoutId = setTimeout(connectPush, delayInSeconds * 1000);
|
|
45
|
-
}
|
|
46
|
-
function connectPush() {
|
|
47
|
-
disconnected = false;
|
|
48
|
-
log.info(STREAMING_CONNECTING);
|
|
49
|
-
authenticate().then(function (authData) {
|
|
50
|
-
if (disconnected)
|
|
51
|
-
return;
|
|
52
|
-
// 'pushEnabled: false' is handled as a PUSH_NONRETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
|
|
53
|
-
// close the sseClient in case the org has been bloqued while the instance was connected to streaming
|
|
54
|
-
if (!authData.pushEnabled) {
|
|
55
|
-
log.info(STREAMING_DISABLED);
|
|
56
|
-
pushEmitter.emit(PUSH_NONRETRYABLE_ERROR);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
// Connect to SSE and schedule refresh token
|
|
60
|
-
var decodedToken = authData.decodedToken;
|
|
61
|
-
sseClient.open(authData);
|
|
62
|
-
scheduleTokenRefresh(decodedToken.iat, decodedToken.exp);
|
|
63
|
-
}).catch(function (error) {
|
|
64
|
-
if (disconnected)
|
|
65
|
-
return;
|
|
66
|
-
log.error(ERROR_STREAMING_AUTH, [error.message]);
|
|
67
|
-
// Handle 4XX HTTP errors: 401 (invalid API Key) or 400 (using incorrect API Key, i.e., client-side API Key on server-side)
|
|
68
|
-
if (error.statusCode >= 400 && error.statusCode < 500) {
|
|
69
|
-
pushEmitter.emit(PUSH_NONRETRYABLE_ERROR);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
// Handle other HTTP and network errors as recoverable errors
|
|
73
|
-
pushEmitter.emit(PUSH_RETRYABLE_ERROR);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
// close SSE connection and cancel scheduled tasks
|
|
77
|
-
function disconnectPush() {
|
|
78
|
-
disconnected = true;
|
|
79
|
-
log.info(STREAMING_DISCONNECTING);
|
|
80
|
-
sseClient.close();
|
|
81
|
-
if (timeoutId)
|
|
82
|
-
clearTimeout(timeoutId);
|
|
83
|
-
connectPushRetryBackoff.reset();
|
|
84
|
-
stopWorkers();
|
|
85
|
-
}
|
|
86
|
-
// cancel scheduled fetch retries of Splits, Segments, and MySegments Update Workers
|
|
87
|
-
function stopWorkers() {
|
|
88
|
-
splitsUpdateWorker.backoff.reset();
|
|
89
|
-
segmentsUpdateWorker.backoff.reset();
|
|
90
|
-
}
|
|
91
|
-
pushEmitter.on(PUSH_SUBSYSTEM_DOWN, stopWorkers);
|
|
92
|
-
// restart backoff retry counter once push is connected
|
|
93
|
-
pushEmitter.on(PUSH_SUBSYSTEM_UP, function () { connectPushRetryBackoff.reset(); });
|
|
94
|
-
/** Fallbacking without retry due to: STREAMING_DISABLED control event, or 'pushEnabled: false', or non-recoverable SSE and Authentication errors */
|
|
95
|
-
pushEmitter.on(PUSH_NONRETRYABLE_ERROR, function handleNonRetryableError() {
|
|
96
|
-
// Note: `stopWorkers` is been called twice, but it is not harmful
|
|
97
|
-
disconnectPush();
|
|
98
|
-
pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already
|
|
99
|
-
});
|
|
100
|
-
/** Fallbacking with retry due to recoverable SSE and Authentication errors */
|
|
101
|
-
pushEmitter.on(PUSH_RETRYABLE_ERROR, function handleRetryableError() {
|
|
102
|
-
// SSE connection is closed to avoid repeated errors due to retries
|
|
103
|
-
sseClient.close();
|
|
104
|
-
// retry streaming reconnect with backoff algorithm
|
|
105
|
-
var delayInMillis = connectPushRetryBackoff.scheduleCall();
|
|
106
|
-
log.info(STREAMING_RECONNECT, [delayInMillis / 1000]);
|
|
107
|
-
pushEmitter.emit(PUSH_SUBSYSTEM_DOWN); // no harm if polling already
|
|
108
|
-
});
|
|
109
|
-
/** Functions related to synchronization (Queues and Workers in the spec) */
|
|
110
|
-
pushEmitter.on(SPLIT_KILL, splitsUpdateWorker.killSplit);
|
|
111
|
-
pushEmitter.on(SPLIT_UPDATE, splitsUpdateWorker.put);
|
|
112
|
-
// [Only for server-side]
|
|
113
|
-
pushEmitter.on(SEGMENT_UPDATE, segmentsUpdateWorker.put);
|
|
114
|
-
return objectAssign(
|
|
115
|
-
// Expose Event Emitter functionality and Event constants
|
|
116
|
-
Object.create(pushEmitter), {
|
|
117
|
-
// Expose functionality for starting and stoping push mode:
|
|
118
|
-
stop: disconnectPush,
|
|
119
|
-
start: function () {
|
|
120
|
-
// Run in next event-loop cycle as in browser
|
|
121
|
-
setTimeout(connectPush);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}
|