@splitsoftware/splitio-commons 3.1.1-rc.3 → 3.1.1-rc.5

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.
Files changed (54) hide show
  1. package/cjs/presets/serverSide.js +3 -3
  2. package/cjs/services/authProvider.js +3 -4
  3. package/cjs/services/secureSplitHttpClient.js +3 -8
  4. package/cjs/services/serviceApi.js +17 -15
  5. package/cjs/services/splitApi.js +10 -9
  6. package/cjs/sync/polling/pollingManagerCS.js +84 -79
  7. package/cjs/sync/polling/pollingManagerSS.js +43 -35
  8. package/cjs/sync/polling/updaters/definitionChangesUpdater.js +2 -2
  9. package/cjs/sync/polling/updaters/segmentChangesUpdater.js +1 -1
  10. package/cjs/sync/streaming/AuthClient/index.js +13 -14
  11. package/cjs/sync/streaming/SSEHandler/index.js +1 -0
  12. package/cjs/sync/streaming/constants.js +2 -1
  13. package/cjs/sync/streaming/pushManager.js +5 -10
  14. package/cjs/sync/submitters/impressionsSubmitter.js +1 -1
  15. package/cjs/sync/syncManagerOnline.js +2 -7
  16. package/esm/presets/serverSide.js +3 -3
  17. package/esm/services/authProvider.js +4 -5
  18. package/esm/services/secureSplitHttpClient.js +3 -8
  19. package/esm/services/serviceApi.js +18 -16
  20. package/esm/services/splitApi.js +10 -9
  21. package/esm/sync/polling/pollingManagerCS.js +84 -79
  22. package/esm/sync/polling/pollingManagerSS.js +43 -35
  23. package/esm/sync/polling/updaters/definitionChangesUpdater.js +3 -3
  24. package/esm/sync/polling/updaters/segmentChangesUpdater.js +1 -1
  25. package/esm/sync/streaming/AuthClient/index.js +11 -11
  26. package/esm/sync/streaming/SSEHandler/index.js +2 -1
  27. package/esm/sync/streaming/constants.js +1 -0
  28. package/esm/sync/streaming/pushManager.js +6 -11
  29. package/esm/sync/submitters/impressionsSubmitter.js +1 -1
  30. package/esm/sync/syncManagerOnline.js +2 -7
  31. package/package.json +1 -1
  32. package/src/dtos/types.ts +1 -1
  33. package/src/presets/serverSide.ts +3 -3
  34. package/src/services/authProvider.ts +19 -13
  35. package/src/services/secureSplitHttpClient.ts +5 -13
  36. package/src/services/serviceApi.ts +21 -18
  37. package/src/services/splitApi.ts +10 -9
  38. package/src/services/types.ts +2 -2
  39. package/src/sync/polling/pollingManagerCS.ts +80 -78
  40. package/src/sync/polling/pollingManagerSS.ts +49 -45
  41. package/src/sync/polling/updaters/definitionChangesUpdater.ts +3 -3
  42. package/src/sync/polling/updaters/segmentChangesUpdater.ts +1 -1
  43. package/src/sync/streaming/AuthClient/index.ts +14 -15
  44. package/src/sync/streaming/AuthClient/types.ts +9 -13
  45. package/src/sync/streaming/SSEClient/index.ts +2 -2
  46. package/src/sync/streaming/SSEClient/types.ts +2 -2
  47. package/src/sync/streaming/SSEHandler/index.ts +2 -1
  48. package/src/sync/streaming/SSEHandler/types.ts +2 -2
  49. package/src/sync/streaming/constants.ts +1 -0
  50. package/src/sync/streaming/pushManager.ts +32 -42
  51. package/src/sync/streaming/types.ts +3 -2
  52. package/src/sync/submitters/impressionsSubmitter.ts +3 -3
  53. package/src/sync/submitters/types.ts +1 -1
  54. package/src/sync/syncManagerOnline.ts +2 -8
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.serverSideModules = void 0;
4
- var serviceApi_1 = require("../services/serviceApi");
4
+ var splitApi_1 = require("../services/splitApi");
5
5
  var syncManagerOnline_1 = require("../sync/syncManagerOnline");
6
6
  var pushManager_1 = require("../sync/streaming/pushManager");
7
7
  var pollingManagerSS_1 = require("../sync/polling/pollingManagerSS");
@@ -9,10 +9,10 @@ var InMemoryStorage_1 = require("../storages/inMemory/InMemoryStorage");
9
9
  var sdkManager_1 = require("../sdkManager");
10
10
  var sdkClientMethod_1 = require("../sdkClient/sdkClientMethod");
11
11
  var impressionObserverSS_1 = require("../trackers/impressionObserver/impressionObserverSS");
12
- var syncManagerOnlineSSFactory = (0, syncManagerOnline_1.syncManagerOnlineFactory)(pollingManagerSS_1.pollingManagerSSFactory, pushManager_1.pushManagerFactory);
12
+ var syncManagerOnlineSSFactory = (0, syncManagerOnline_1.syncManagerOnlineFactory)((0, pollingManagerSS_1.pollingManagerSSFactory)(), pushManager_1.pushManagerFactory);
13
13
  exports.serverSideModules = {
14
14
  storageFactory: InMemoryStorage_1.InMemoryStorageFactory,
15
- serviceApiFactory: serviceApi_1.serviceApiFactory,
15
+ serviceApiFactory: splitApi_1.splitApiFactory,
16
16
  syncManagerFactory: syncManagerOnlineSSFactory,
17
17
  sdkManagerFactory: sdkManager_1.sdkManagerFactory,
18
18
  sdkClientMethodFactory: sdkClientMethod_1.sdkClientMethodFactory,
@@ -15,17 +15,16 @@ function isExpired(credential) {
15
15
  */
16
16
  function authProviderFactory(settings, splitHttpClient, telemetryTracker) {
17
17
  var urls = settings.urls, log = settings.log;
18
- function fetchAuth() {
18
+ var fetchAuth = (0, AuthClient_1.fetchAuthFactory)(function () {
19
19
  var url = "".concat(urls.auth, "/api/v3/auth?capabilities=config,aiconfig");
20
20
  return splitHttpClient(url, undefined, telemetryTracker.trackHttp(constants_2.TOKEN), false, true);
21
- }
22
- var authenticate = (0, AuthClient_1.authenticateFactory)(fetchAuth);
21
+ });
23
22
  var backoff = new Backoff_1.Backoff(fetchCredential);
24
23
  var cachedCredential;
25
24
  var inFlightPromise;
26
25
  var stopped = false;
27
26
  function fetchCredential() {
28
- return authenticate().then(function (credential) {
27
+ return fetchAuth().then(function (credential) {
29
28
  log.info(constants_1.LOG_PREFIX_SYNC_AUTH + 'credential fetched successfully');
30
29
  cachedCredential = credential;
31
30
  inFlightPromise = undefined;
@@ -2,19 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.secureSplitHttpClientFactory = void 0;
4
4
  var tslib_1 = require("tslib");
5
- var splitHttpClient_1 = require("./splitHttpClient");
6
- var authProvider_1 = require("./authProvider");
7
5
  /**
8
6
  * Factory of Secure HTTP client, which authenticates requests using a JWT token.
9
7
  * On 401 responses, invalidates the cached credential and retries once with a fresh token.
10
8
  *
11
- * @param settings - SDK settings
12
- * @param platform - object containing environment-specific dependencies
13
- * @param fetchAuth - function to fetch auth credentials from the /v2/auth endpoint
9
+ * @param splitHttpClient - `splitHttpClientFactory` to use for making requests
10
+ * @param authProvider - `authProviderFactory` to use for authentication
14
11
  */
15
- function secureSplitHttpClientFactory(settings, platform, telemetryTracker) {
16
- var splitHttpClient = (0, splitHttpClient_1.splitHttpClientFactory)(settings, platform);
17
- var authProvider = (0, authProvider_1.authProviderFactory)(settings, splitHttpClient, telemetryTracker);
12
+ function secureSplitHttpClientFactory(splitHttpClient, authProvider) {
18
13
  function makeRequest(url, options, latencyTracker, logErrorsAsInfo, token) {
19
14
  return splitHttpClient(url, tslib_1.__assign(tslib_1.__assign({}, options), { headers: tslib_1.__assign(tslib_1.__assign({}, options === null || options === void 0 ? void 0 : options.headers), { Authorization: "Bearer ".concat(token) }) }), latencyTracker, logErrorsAsInfo, true);
20
15
  }
@@ -5,25 +5,36 @@ var splitHttpClient_1 = require("./splitHttpClient");
5
5
  var objectAssign_1 = require("../utils/lang/objectAssign");
6
6
  var constants_1 = require("../utils/constants");
7
7
  var constants_2 = require("../logger/constants");
8
+ var authProvider_1 = require("./authProvider");
9
+ var secureSplitHttpClient_1 = require("./secureSplitHttpClient");
8
10
  var noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
9
- function userKeyToQueryParam(userKey) {
10
- return 'users=' + encodeURIComponent(userKey); // no need to check availability of `encodeURIComponent`, since it is a global highly supported.
11
- }
12
11
  /**
13
12
  * Factory of ServiceApi objects, which group the collection of HTTP endpoints used by the SDKs
14
13
  *
15
14
  * @param settings - validated settings object
16
15
  * @param platform - object containing environment-specific dependencies
17
16
  * @param telemetryTracker - telemetry tracker
18
- * @param secureSplitHttpClientFactory - factory of SecureSplitHttpClient objects
19
17
  */
20
- function serviceApiFactory(settings, platform, telemetryTracker, secureSplitHttpClientFactory) {
18
+ function serviceApiFactory(settings, platform, telemetryTracker) {
21
19
  var urls = settings.urls;
22
20
  var filterQueryString = settings.sync.__splitFiltersValidation && settings.sync.__splitFiltersValidation.queryString;
23
21
  var SplitSDKImpressionsMode = settings.sync.impressionsMode;
24
22
  var splitHttpClient = (0, splitHttpClient_1.splitHttpClientFactory)(settings, platform);
25
- var secureSplitHttpClient = secureSplitHttpClientFactory(settings, platform, telemetryTracker);
23
+ // Shared authProvider so that the SSE authentication (via `fetchAuth`,
24
+ // used by `pushManager`) and every authenticated HTTP request to the Configs
25
+ // API reuse the same cached credential instead of each fetching their own.
26
+ var authProvider = (0, authProvider_1.authProviderFactory)(settings, splitHttpClient, telemetryTracker);
27
+ var secureSplitHttpClient = (0, secureSplitHttpClient_1.secureSplitHttpClientFactory)(splitHttpClient, authProvider);
28
+ var initialAuth = true;
26
29
  return {
30
+ fetchAuth: function () {
31
+ // Guard condition to avoid invalidating the cached credential on the first pushManager authentication
32
+ if (initialAuth)
33
+ initialAuth = false;
34
+ else
35
+ authProvider.invalidate();
36
+ return authProvider.credential();
37
+ },
27
38
  // @TODO throw errors if health check requests fail, to log them in the Synchronizer
28
39
  getSdkAPIHealthCheck: function () {
29
40
  var url = "".concat(urls.sdk, "/api/version");
@@ -33,15 +44,6 @@ function serviceApiFactory(settings, platform, telemetryTracker, secureSplitHttp
33
44
  var url = "".concat(urls.events, "/api/version");
34
45
  return splitHttpClient(url).then(function () { return true; }).catch(function () { return false; });
35
46
  },
36
- fetchAuth: function (userMatchingKeys) {
37
- var url = "".concat(urls.auth, "/api/v2/auth?s=").concat(settings.sync.flagSpecVersion);
38
- if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
39
- var queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
40
- if (queryParams)
41
- url += '&' + queryParams;
42
- }
43
- return splitHttpClient(url, undefined, telemetryTracker.trackHttp(constants_1.TOKEN));
44
- },
45
47
  fetchSplitChanges: function (since, noCache, till, rbSince) {
46
48
  var url = "".concat(urls.sdk, "/api/splitChanges?s=").concat(settings.sync.flagSpecVersion, "&since=").concat(since).concat(rbSince ? '&rbSince=' + rbSince : '').concat(filterQueryString || '').concat(till ? '&till=' + till : '');
47
49
  return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(constants_1.SPLITS))
@@ -5,6 +5,7 @@ var splitHttpClient_1 = require("./splitHttpClient");
5
5
  var objectAssign_1 = require("../utils/lang/objectAssign");
6
6
  var constants_1 = require("../utils/constants");
7
7
  var constants_2 = require("../logger/constants");
8
+ var AuthClient_1 = require("../sync/streaming/AuthClient");
8
9
  var noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
9
10
  function userKeyToQueryParam(userKey) {
10
11
  return 'users=' + encodeURIComponent(userKey); // no need to check availability of `encodeURIComponent`, since it is a global highly supported.
@@ -23,6 +24,15 @@ function splitApiFactory(settings, platform, telemetryTracker) {
23
24
  var SplitSDKImpressionsMode = settings.sync.impressionsMode;
24
25
  var splitHttpClient = (0, splitHttpClient_1.splitHttpClientFactory)(settings, platform);
25
26
  return {
27
+ fetchAuth: (0, AuthClient_1.fetchAuthFactory)(function (userMatchingKeys) {
28
+ var url = "".concat(urls.auth, "/v2/auth?s=").concat(settings.sync.flagSpecVersion);
29
+ if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
30
+ var queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
31
+ if (queryParams)
32
+ url += '&' + queryParams;
33
+ }
34
+ return splitHttpClient(url, undefined, telemetryTracker.trackHttp(constants_1.TOKEN));
35
+ }),
26
36
  // @TODO throw errors if health check requests fail, to log them in the Synchronizer
27
37
  getSdkAPIHealthCheck: function () {
28
38
  var url = "".concat(urls.sdk, "/version");
@@ -32,15 +42,6 @@ function splitApiFactory(settings, platform, telemetryTracker) {
32
42
  var url = "".concat(urls.events, "/version");
33
43
  return splitHttpClient(url).then(function () { return true; }).catch(function () { return false; });
34
44
  },
35
- fetchAuth: function (userMatchingKeys) {
36
- var url = "".concat(urls.auth, "/v2/auth?s=").concat(settings.sync.flagSpecVersion);
37
- if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
38
- var queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
39
- if (queryParams)
40
- url += '&' + queryParams;
41
- }
42
- return splitHttpClient(url, undefined, telemetryTracker.trackHttp(constants_1.TOKEN));
43
- },
44
45
  fetchSplitChanges: function (since, noCache, till, rbSince) {
45
46
  var url = "".concat(urls.sdk, "/splitChanges?s=").concat(settings.sync.flagSpecVersion, "&since=").concat(since).concat(rbSince ? '&rbSince=' + rbSince : '').concat(filterQueryString || '').concat(till ? '&till=' + till : '');
46
47
  return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(constants_1.SPLITS))
@@ -8,93 +8,98 @@ var key_1 = require("../../utils/key");
8
8
  var constants_1 = require("../../readiness/constants");
9
9
  var constants_2 = require("../../logger/constants");
10
10
  var AbstractDefinitionsCacheSync_1 = require("../../storages/AbstractDefinitionsCacheSync");
11
+ var splitChangesFetcher_1 = require("./fetchers/splitChangesFetcher");
11
12
  /**
12
13
  * Expose start / stop mechanism for polling data from services.
13
14
  * For client-side API with multiple clients.
14
15
  */
15
- function pollingManagerCSFactory(params, definitionChangesFetcher) {
16
- var serviceApi = params.serviceApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
17
- var log = settings.log;
18
- var definitionsSyncTask = (0, definitionsSyncTask_1.definitionsSyncTaskFactory)(definitionChangesFetcher, storage, readiness, settings);
19
- // Map of matching keys to their corresponding MySegmentsSyncTask.
20
- var mySegmentsSyncTasks = {};
21
- var matchingKey = (0, key_1.getMatching)(settings.core.key);
22
- var mySegmentsSyncTask = add(matchingKey, readiness, storage);
23
- function startMySegmentsSyncTasks() {
24
- (0, lang_1.forOwn)(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
25
- mySegmentsSyncTask.start();
26
- });
27
- }
28
- function stopMySegmentsSyncTasks() {
29
- (0, lang_1.forOwn)(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
30
- if (mySegmentsSyncTask.isRunning())
31
- mySegmentsSyncTask.stop();
32
- });
33
- }
34
- // smart pausing
35
- readiness.definitions.on(constants_1.SDK_DEFINITIONS_ARRIVED, function () {
36
- if (!definitionsSyncTask.isRunning())
37
- return; // noop if not doing polling
38
- var usingSegments = (0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage);
39
- if (usingSegments !== mySegmentsSyncTask.isRunning()) {
40
- log.info(constants_2.POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
41
- if (usingSegments) {
42
- startMySegmentsSyncTasks();
43
- }
44
- else {
45
- stopMySegmentsSyncTasks();
46
- }
47
- }
48
- });
49
- function add(matchingKey, readiness, storage) {
50
- var mySegmentsSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
51
- // smart ready
52
- function smartReady(metadata) {
53
- if (!readiness.isReady() && !(0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
54
- readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED, metadata);
16
+ function pollingManagerCSFactory(definitionFetcherFactory) {
17
+ if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcher_1.splitChangesFetcherFactory; }
18
+ return function (params) {
19
+ var serviceApi = params.serviceApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
20
+ var log = settings.log;
21
+ var definitionChangesFetcher = definitionFetcherFactory(params);
22
+ var definitionsSyncTask = (0, definitionsSyncTask_1.definitionsSyncTaskFactory)(definitionChangesFetcher, storage, readiness, settings);
23
+ // Map of matching keys to their corresponding MySegmentsSyncTask.
24
+ var mySegmentsSyncTasks = {};
25
+ var matchingKey = (0, key_1.getMatching)(settings.core.key);
26
+ var mySegmentsSyncTask = add(matchingKey, readiness, storage);
27
+ function startMySegmentsSyncTasks() {
28
+ (0, lang_1.forOwn)(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
29
+ mySegmentsSyncTask.start();
30
+ });
55
31
  }
56
- if (!(0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
57
- setTimeout(smartReady, 0);
58
- else
59
- readiness.definitions.once(constants_1.SDK_DEFINITIONS_ARRIVED, smartReady);
60
- mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
61
- return mySegmentsSyncTask;
62
- }
63
- return {
64
- definitionsSyncTask: definitionsSyncTask,
65
- segmentsSyncTask: mySegmentsSyncTask,
66
- // Start periodic fetching (polling)
67
- start: function () {
68
- log.info(constants_2.POLLING_START);
69
- definitionsSyncTask.start();
70
- if ((0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
71
- startMySegmentsSyncTasks();
72
- },
73
- // Stop periodic fetching (polling)
74
- stop: function () {
75
- log.info(constants_2.POLLING_STOP);
76
- if (definitionsSyncTask.isRunning())
77
- definitionsSyncTask.stop();
78
- stopMySegmentsSyncTasks();
79
- },
80
- // Used by SyncManager to know if running in polling mode.
81
- isRunning: definitionsSyncTask.isRunning,
82
- // fetch definitions and segments
83
- syncAll: function () {
84
- var promises = [definitionsSyncTask.execute()];
32
+ function stopMySegmentsSyncTasks() {
85
33
  (0, lang_1.forOwn)(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
86
- promises.push(mySegmentsSyncTask.execute());
34
+ if (mySegmentsSyncTask.isRunning())
35
+ mySegmentsSyncTask.stop();
87
36
  });
88
- return Promise.all(promises);
89
- },
90
- // Support for handling mySegments sync of multiple clients
91
- add: add,
92
- remove: function (matchingKey) {
93
- delete mySegmentsSyncTasks[matchingKey];
94
- },
95
- get: function (matchingKey) {
96
- return mySegmentsSyncTasks[matchingKey];
97
37
  }
38
+ // smart pausing
39
+ readiness.definitions.on(constants_1.SDK_DEFINITIONS_ARRIVED, function () {
40
+ if (!definitionsSyncTask.isRunning())
41
+ return; // noop if not doing polling
42
+ var usingSegments = (0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage);
43
+ if (usingSegments !== mySegmentsSyncTask.isRunning()) {
44
+ log.info(constants_2.POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
45
+ if (usingSegments) {
46
+ startMySegmentsSyncTasks();
47
+ }
48
+ else {
49
+ stopMySegmentsSyncTasks();
50
+ }
51
+ }
52
+ });
53
+ function add(matchingKey, readiness, storage) {
54
+ var mySegmentsSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
55
+ // smart ready
56
+ function smartReady(metadata) {
57
+ if (!readiness.isReady() && !(0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
58
+ readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED, metadata);
59
+ }
60
+ if (!(0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
61
+ setTimeout(smartReady, 0);
62
+ else
63
+ readiness.definitions.once(constants_1.SDK_DEFINITIONS_ARRIVED, smartReady);
64
+ mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
65
+ return mySegmentsSyncTask;
66
+ }
67
+ return {
68
+ definitionsSyncTask: definitionsSyncTask,
69
+ segmentsSyncTask: mySegmentsSyncTask,
70
+ // Start periodic fetching (polling)
71
+ start: function () {
72
+ log.info(constants_2.POLLING_START);
73
+ definitionsSyncTask.start();
74
+ if ((0, AbstractDefinitionsCacheSync_1.usesSegmentsSync)(storage))
75
+ startMySegmentsSyncTasks();
76
+ },
77
+ // Stop periodic fetching (polling)
78
+ stop: function () {
79
+ log.info(constants_2.POLLING_STOP);
80
+ if (definitionsSyncTask.isRunning())
81
+ definitionsSyncTask.stop();
82
+ stopMySegmentsSyncTasks();
83
+ },
84
+ // Used by SyncManager to know if running in polling mode.
85
+ isRunning: definitionsSyncTask.isRunning,
86
+ // fetch definitions and segments
87
+ syncAll: function () {
88
+ var promises = [definitionsSyncTask.execute()];
89
+ (0, lang_1.forOwn)(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
90
+ promises.push(mySegmentsSyncTask.execute());
91
+ });
92
+ return Promise.all(promises);
93
+ },
94
+ // Support for handling mySegments sync of multiple clients
95
+ add: add,
96
+ remove: function (matchingKey) {
97
+ delete mySegmentsSyncTasks[matchingKey];
98
+ },
99
+ get: function (matchingKey) {
100
+ return mySegmentsSyncTasks[matchingKey];
101
+ }
102
+ };
98
103
  };
99
104
  }
100
105
  exports.pollingManagerCSFactory = pollingManagerCSFactory;
@@ -4,46 +4,54 @@ exports.pollingManagerSSFactory = void 0;
4
4
  var definitionsSyncTask_1 = require("./syncTasks/definitionsSyncTask");
5
5
  var segmentsSyncTask_1 = require("./syncTasks/segmentsSyncTask");
6
6
  var constants_1 = require("../../logger/constants");
7
+ var segmentChangesFetcher_1 = require("./fetchers/segmentChangesFetcher");
8
+ var splitChangesFetcher_1 = require("./fetchers/splitChangesFetcher");
7
9
  /**
8
10
  * Expose start / stop mechanism for pulling data from services.
9
11
  */
10
- function pollingManagerSSFactory(params, definitionChangesFetcher, segmentChangesFetcher) {
11
- var storage = params.storage, readiness = params.readiness, settings = params.settings;
12
- var log = settings.log;
13
- var segmentsSyncTask = (0, segmentsSyncTask_1.segmentsSyncTaskFactory)(segmentChangesFetcher, storage, readiness, settings);
14
- var definitionsSyncTask = (0, definitionsSyncTask_1.definitionsSyncTaskFactory)(definitionChangesFetcher, storage, readiness, settings, segmentsSyncTask);
15
- return {
16
- definitionsSyncTask: definitionsSyncTask,
17
- segmentsSyncTask: segmentsSyncTask,
18
- // Start periodic fetching (polling)
19
- start: function () {
20
- log.info(constants_1.POLLING_START);
21
- log.debug(constants_1.LOG_PREFIX_SYNC_POLLING + "".concat(definitionChangesFetcher.type, " will be refreshed each ").concat(settings.scheduler.featuresRefreshRate, " millis"));
22
- log.debug(constants_1.LOG_PREFIX_SYNC_POLLING + "segments will be refreshed each ".concat(settings.scheduler.segmentsRefreshRate, " millis"));
23
- var startingUp = definitionsSyncTask.start();
24
- if (startingUp) {
25
- startingUp.then(function () {
26
- if (definitionsSyncTask.isRunning())
27
- segmentsSyncTask.start();
12
+ function pollingManagerSSFactory(definitionFetcherFactory, segmentFetcherFactory) {
13
+ if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcher_1.splitChangesFetcherFactory; }
14
+ if (segmentFetcherFactory === void 0) { segmentFetcherFactory = function (params) { return (0, segmentChangesFetcher_1.segmentChangesFetcherFactory)(params.serviceApi.fetchSegmentChanges); }; }
15
+ return function (params) {
16
+ var storage = params.storage, readiness = params.readiness, settings = params.settings;
17
+ var log = settings.log;
18
+ var definitionChangesFetcher = definitionFetcherFactory(params);
19
+ var segmentChangesFetcher = segmentFetcherFactory(params);
20
+ var segmentsSyncTask = (0, segmentsSyncTask_1.segmentsSyncTaskFactory)(segmentChangesFetcher, storage, readiness, settings);
21
+ var definitionsSyncTask = (0, definitionsSyncTask_1.definitionsSyncTaskFactory)(definitionChangesFetcher, storage, readiness, settings, segmentsSyncTask);
22
+ return {
23
+ definitionsSyncTask: definitionsSyncTask,
24
+ segmentsSyncTask: segmentsSyncTask,
25
+ // Start periodic fetching (polling)
26
+ start: function () {
27
+ log.info(constants_1.POLLING_START);
28
+ log.debug(constants_1.LOG_PREFIX_SYNC_POLLING + "".concat(definitionChangesFetcher.type, " will be refreshed each ").concat(settings.scheduler.featuresRefreshRate, " millis"));
29
+ log.debug(constants_1.LOG_PREFIX_SYNC_POLLING + "segments will be refreshed each ".concat(settings.scheduler.segmentsRefreshRate, " millis"));
30
+ var startingUp = definitionsSyncTask.start();
31
+ if (startingUp) {
32
+ startingUp.then(function () {
33
+ if (definitionsSyncTask.isRunning())
34
+ segmentsSyncTask.start();
35
+ });
36
+ }
37
+ },
38
+ // Stop periodic fetching (polling)
39
+ stop: function () {
40
+ log.info(constants_1.POLLING_STOP);
41
+ if (definitionsSyncTask.isRunning())
42
+ definitionsSyncTask.stop();
43
+ if (segmentsSyncTask.isRunning())
44
+ segmentsSyncTask.stop();
45
+ },
46
+ // Used by SyncManager to know if running in polling mode.
47
+ isRunning: definitionsSyncTask.isRunning,
48
+ syncAll: function () {
49
+ // fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
50
+ return definitionsSyncTask.execute().then(function () {
51
+ return segmentsSyncTask.execute();
28
52
  });
29
53
  }
30
- },
31
- // Stop periodic fetching (polling)
32
- stop: function () {
33
- log.info(constants_1.POLLING_STOP);
34
- if (definitionsSyncTask.isRunning())
35
- definitionsSyncTask.stop();
36
- if (segmentsSyncTask.isRunning())
37
- segmentsSyncTask.stop();
38
- },
39
- // Used by SyncManager to know if running in polling mode.
40
- isRunning: definitionsSyncTask.isRunning,
41
- syncAll: function () {
42
- // fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
43
- return definitionsSyncTask.execute().then(function () {
44
- return segmentsSyncTask.execute();
45
- });
46
- }
54
+ };
47
55
  };
48
56
  }
49
57
  exports.pollingManagerSSFactory = pollingManagerSSFactory;
@@ -125,14 +125,14 @@ function definitionChangesUpdaterFactory(log, definitionChangesFetcher, storage,
125
125
  var since = sinces[0], rbSince = sinces[1];
126
126
  log.debug(constants_2.SYNC_FETCH, [definitionChangesFetcher.type, since, rbSince]);
127
127
  return Promise.resolve(instantUpdate ?
128
- instantUpdate.type === constants_4.SPLIT_UPDATE ?
128
+ instantUpdate.type === constants_4.RB_SEGMENT_UPDATE ?
129
+ { rbs: convertInstantUpdateToDefinitionChanges(instantUpdate) } :
129
130
  // IFFU edge case: a change to definition that adds an IN_RULE_BASED_SEGMENT matcher that is not present yet
130
131
  Promise.resolve(rbSegments.contains(parseSegments(instantUpdate.payload, constants_3.IN_RULE_BASED_SEGMENT))).then(function (contains) {
131
132
  return contains ?
132
133
  { d: convertInstantUpdateToDefinitionChanges(instantUpdate) } :
133
134
  definitionChangesFetcher(since, noCache, till, rbSince, _promiseDecorator);
134
135
  }) :
135
- { rbs: convertInstantUpdateToDefinitionChanges(instantUpdate) } :
136
136
  definitionChangesFetcher(since, noCache, till, rbSince, _promiseDecorator))
137
137
  .then(function (definitionChanges) {
138
138
  var usedSegments = new Set();
@@ -31,7 +31,7 @@ function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segments, read
31
31
  false :
32
32
  segmentChangesFetcher(since || -1, segmentName, noCache, till, _promiseDecorator).then(function (changes) {
33
33
  return Promise.all(changes.map(function (x) {
34
- log.debug("".concat(constants_2.LOG_PREFIX_SYNC, "Processing ").concat(segmentName, " with till = ").concat(x.till, ". Added: ").concat(x.added.length, ". Removed: ").concat(x.removed.length));
34
+ log.debug("".concat(constants_2.LOG_PREFIX_SYNC, "Processing ").concat(segmentName, " with since = ").concat(x.since, " and till = ").concat(x.till, ". Added: ").concat(x.added.length, ". Removed: ").concat(x.removed.length));
35
35
  return segments.update(segmentName, x.added, x.removed, x.till);
36
36
  })).then(function (updates) {
37
37
  return updates.some(function (update) { return update; });
@@ -1,16 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hashUserKey = exports.authenticateFactory = void 0;
3
+ exports.fetchAuthFactory = void 0;
4
4
  var objectAssign_1 = require("../../../utils/lang/objectAssign");
5
- var base64_1 = require("../../../utils/base64");
6
5
  var jwt_1 = require("../../../utils/jwt");
7
- var murmur3_1 = require("../../../utils/murmur3/murmur3");
8
6
  /**
9
7
  * Factory of authentication function.
10
8
  *
11
- * @param fetchAuth - `ServiceApi.fetchAuth` endpoint
9
+ * @param fetchAuth - /auth endpoint
12
10
  */
13
- function authenticateFactory(fetchAuth) {
11
+ function fetchAuthFactory(fetchAuth) {
14
12
  /**
15
13
  * Run authentication requests to Auth Server, and returns a promise that resolves with the decoded JTW token.
16
14
  * @param userKeys - set of user Keys to track membership updates. It is undefined for server-side API.
@@ -24,20 +22,21 @@ function authenticateFactory(fetchAuth) {
24
22
  if (typeof decodedToken.iat !== 'number' || typeof decodedToken.exp !== 'number')
25
23
  throw new Error('token properties "issuedAt" (iat) or "expiration" (exp) are missing or invalid');
26
24
  var channels = JSON.parse(decodedToken['x-ably-capability']);
27
- return (0, objectAssign_1.objectAssign)({
25
+ var credential = (0, objectAssign_1.objectAssign)({
28
26
  decodedToken: decodedToken,
29
27
  channels: channels
30
28
  }, json);
29
+ // The `/api/v3/auth` endpoint nests the streaming settings under `config.streaming`. Normalize
30
+ // them into the flat `pushEnabled`/`connDelay` properties used by the PushManager.
31
+ var streaming = credential.config && credential.config.streaming;
32
+ if (streaming) {
33
+ credential.pushEnabled = streaming.enabled;
34
+ credential.connDelay = streaming.delay;
35
+ }
36
+ return credential;
31
37
  }
32
38
  return json;
33
39
  });
34
40
  };
35
41
  }
36
- exports.authenticateFactory = authenticateFactory;
37
- /**
38
- * Returns the hash of a given user key
39
- */
40
- function hashUserKey(userKey) {
41
- return (0, base64_1.encodeToBase64)((0, murmur3_1.hash)(userKey, 0).toString());
42
- }
43
- exports.hashUserKey = hashUserKey;
42
+ exports.fetchAuthFactory = fetchAuthFactory;
@@ -74,6 +74,7 @@ function SSEHandlerFactory(log, pushEmitter, telemetryTracker) {
74
74
  switch (parsedData.type) {
75
75
  /* update events */
76
76
  case constants_1.SPLIT_UPDATE:
77
+ case constants_1.CONFIG_UPDATE:
77
78
  case constants_1.SEGMENT_UPDATE:
78
79
  case constants_1.MEMBERSHIPS_MS_UPDATE:
79
80
  case constants_1.MEMBERSHIPS_LS_UPDATE:
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ControlType = exports.OCCUPANCY = exports.CONTROL = exports.RB_SEGMENT_UPDATE = exports.SPLIT_UPDATE = exports.SPLIT_KILL = exports.SEGMENT_UPDATE = exports.MEMBERSHIPS_LS_UPDATE = exports.MEMBERSHIPS_MS_UPDATE = exports.PUSH_SUBSYSTEM_DOWN = exports.PUSH_SUBSYSTEM_UP = exports.PUSH_RETRYABLE_ERROR = exports.PUSH_NON_RETRYABLE_ERROR = exports.SECONDS_BEFORE_EXPIRATION = void 0;
3
+ exports.ControlType = exports.OCCUPANCY = exports.CONTROL = exports.RB_SEGMENT_UPDATE = exports.CONFIG_UPDATE = exports.SPLIT_UPDATE = exports.SPLIT_KILL = exports.SEGMENT_UPDATE = exports.MEMBERSHIPS_LS_UPDATE = exports.MEMBERSHIPS_MS_UPDATE = exports.PUSH_SUBSYSTEM_DOWN = exports.PUSH_SUBSYSTEM_UP = exports.PUSH_RETRYABLE_ERROR = exports.PUSH_NON_RETRYABLE_ERROR = exports.SECONDS_BEFORE_EXPIRATION = void 0;
4
4
  // time for refresh token
5
5
  exports.SECONDS_BEFORE_EXPIRATION = 600;
6
6
  // Internal SDK events, subscribed by SyncManager and PushManager
@@ -30,6 +30,7 @@ exports.MEMBERSHIPS_LS_UPDATE = 'MEMBERSHIPS_LS_UPDATE';
30
30
  exports.SEGMENT_UPDATE = 'SEGMENT_UPDATE';
31
31
  exports.SPLIT_KILL = 'SPLIT_KILL';
32
32
  exports.SPLIT_UPDATE = 'SPLIT_UPDATE';
33
+ exports.CONFIG_UPDATE = 'CONFIG_UPDATE';
33
34
  exports.RB_SEGMENT_UPDATE = 'RB_SEGMENT_UPDATE';
34
35
  // Control-type push notifications, handled by NotificationKeeper
35
36
  exports.CONTROL = 'CONTROL';
@@ -7,7 +7,6 @@ var SSEHandler_1 = require("./SSEHandler");
7
7
  var MySegmentsUpdateWorker_1 = require("./UpdateWorkers/MySegmentsUpdateWorker");
8
8
  var SegmentsUpdateWorker_1 = require("./UpdateWorkers/SegmentsUpdateWorker");
9
9
  var DefinitionsUpdateWorker_1 = require("./UpdateWorkers/DefinitionsUpdateWorker");
10
- var AuthClient_1 = require("./AuthClient");
11
10
  var lang_1 = require("../../utils/lang");
12
11
  var SSEClient_1 = require("./SSEClient");
13
12
  var key_1 = require("../../utils/key");
@@ -37,7 +36,6 @@ function pushManagerFactory(params, pollingManager) {
37
36
  log.warn(constants_2.STREAMING_FALLBACK, [e]);
38
37
  return;
39
38
  }
40
- var authenticate = (0, AuthClient_1.authenticateFactory)(serviceApi.fetchAuth);
41
39
  // init feedback loop
42
40
  var pushEmitter = new platform.EventEmitter();
43
41
  var sseHandler = (0, SSEHandler_1.SSEHandlerFactory)(log, pushEmitter, telemetryTracker);
@@ -47,8 +45,6 @@ function pushManagerFactory(params, pollingManager) {
47
45
  var segmentsUpdateWorker = userKey ? undefined : (0, SegmentsUpdateWorker_1.SegmentsUpdateWorker)(log, pollingManager.segmentsSyncTask, storage.segments);
48
46
  // For server-side we pass the segmentsSyncTask, used by DefinitionsUpdateWorker to fetch new segments
49
47
  var definitionsUpdateWorker = (0, DefinitionsUpdateWorker_1.DefinitionsUpdateWorker)(log, storage, pollingManager.definitionsSyncTask, readiness.definitions, telemetryTracker);
50
- // [Only for client-side] map of hashes to user keys, to dispatch membership update events to the corresponding MySegmentsUpdateWorker
51
- var userKeyHashes = {};
52
48
  // [Only for client-side] map of user keys to their corresponding hash64 and MySegmentsUpdateWorkers.
53
49
  // Hash64 is used to process membership update events and dispatch actions to the corresponding MySegmentsUpdateWorker.
54
50
  var clients = {};
@@ -93,7 +89,7 @@ function pushManagerFactory(params, pollingManager) {
93
89
  log.info(constants_2.STREAMING_CONNECTING);
94
90
  disconnected = false;
95
91
  var userKeys = userKey ? Object.keys(clients) : undefined;
96
- authenticate(userKeys).then(function (authData) {
92
+ serviceApi.fetchAuth(userKeys).then(function (authData) {
97
93
  if (disconnected)
98
94
  return;
99
95
  // 'pushEnabled: false' is handled as a PUSH_NON_RETRYABLE_ERROR instead of PUSH_SUBSYSTEM_DOWN, in order to
@@ -181,8 +177,11 @@ function pushManagerFactory(params, pollingManager) {
181
177
  connectPush();
182
178
  });
183
179
  /** Functions related to synchronization (Queues and Workers in the spec) */
180
+ // Some notification types are specific to the Feature flags or Configs SDKs. Their handlers are
181
+ // registered unconditionally, since the SDK only subscribes to the channels of its own entities.
184
182
  pushEmitter.on(constants_1.SPLIT_KILL, definitionsUpdateWorker.killDefinition);
185
183
  pushEmitter.on(constants_1.SPLIT_UPDATE, definitionsUpdateWorker.put);
184
+ pushEmitter.on(constants_1.CONFIG_UPDATE, definitionsUpdateWorker.put);
186
185
  pushEmitter.on(constants_1.RB_SEGMENT_UPDATE, definitionsUpdateWorker.put);
187
186
  function handleMySegmentsUpdate(parsedData) {
188
187
  switch (parsedData.u) {
@@ -285,9 +284,7 @@ function pushManagerFactory(params, pollingManager) {
285
284
  },
286
285
  // [Only for client-side]
287
286
  add: function (userKey, mySegmentsSyncTask) {
288
- var hash = (0, AuthClient_1.hashUserKey)(userKey);
289
- if (!userKeyHashes[hash]) {
290
- userKeyHashes[hash] = userKey;
287
+ if (!clients[userKey]) {
291
288
  clients[userKey] = {
292
289
  hash64: (0, murmur3_64_1.hash64)(userKey),
293
290
  worker: (0, MySegmentsUpdateWorker_1.MySegmentsUpdateWorker)(log, storage, mySegmentsSyncTask, telemetryTracker)
@@ -308,8 +305,6 @@ function pushManagerFactory(params, pollingManager) {
308
305
  },
309
306
  // [Only for client-side]
310
307
  remove: function (userKey) {
311
- var hash = (0, AuthClient_1.hashUserKey)(userKey);
312
- delete userKeyHashes[hash];
313
308
  delete clients[userKey];
314
309
  }
315
310
  });
@@ -23,7 +23,7 @@ function fromImpressionsCollector(sendLabels, data) {
23
23
  b: entry.bucketingKey,
24
24
  pt: entry.pt,
25
25
  properties: entry.properties,
26
- // @ts-expect-error - entityType is not yet public. @TODO: add to SplitIO.ImpressionDTO type
26
+ // @TODO: add entityType to public SplitIO.ImpressionDTO type
27
27
  et: entry.entityType, // Definition type
28
28
  };
29
29
  })