@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
@@ -8,8 +8,6 @@ var consent_1 = require("../consent");
8
8
  var constants_3 = require("../utils/constants");
9
9
  var constants_4 = require("../readiness/constants");
10
10
  var AbstractDefinitionsCacheSync_1 = require("../storages/AbstractDefinitionsCacheSync");
11
- var splitChangesFetcher_1 = require("./polling/fetchers/splitChangesFetcher");
12
- var segmentChangesFetcher_1 = require("./polling/fetchers/segmentChangesFetcher");
13
11
  /**
14
12
  * Online SyncManager factory.
15
13
  * Can be used for server-side API, and client-side API with or without multiple clients.
@@ -17,18 +15,15 @@ var segmentChangesFetcher_1 = require("./polling/fetchers/segmentChangesFetcher"
17
15
  * @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
18
16
  * `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
19
17
  * @param pushManagerFactory - optional to build a SyncManager with or without streaming support
20
- * @param definitionChangesFetcherFactory - optional to replace the default split changes fetcher
21
18
  */
22
- function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory, definitionFetcherFactory, segmentFetcherFactory) {
23
- if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcher_1.splitChangesFetcherFactory; }
24
- if (segmentFetcherFactory === void 0) { segmentFetcherFactory = function (params) { return (0, segmentChangesFetcher_1.segmentChangesFetcherFactory)(params.serviceApi.fetchSegmentChanges); }; }
19
+ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
25
20
  /**
26
21
  * SyncManager factory for modular SDK
27
22
  */
28
23
  return function (params) {
29
24
  var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker, storage = params.storage, readiness = params.readiness;
30
25
  /** Polling Manager */
31
- var pollingManager = pollingManagerFactory && pollingManagerFactory(params, definitionFetcherFactory(params), segmentFetcherFactory(params));
26
+ var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
32
27
  /** Push Manager */
33
28
  var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
34
29
  pushManagerFactory(params, pollingManager) :
@@ -1,4 +1,4 @@
1
- import { serviceApiFactory } from '../services/serviceApi';
1
+ import { splitApiFactory } from '../services/splitApi';
2
2
  import { syncManagerOnlineFactory } from '../sync/syncManagerOnline';
3
3
  import { pushManagerFactory } from '../sync/streaming/pushManager';
4
4
  import { pollingManagerSSFactory } from '../sync/polling/pollingManagerSS';
@@ -6,10 +6,10 @@ import { InMemoryStorageFactory } from '../storages/inMemory/InMemoryStorage';
6
6
  import { sdkManagerFactory } from '../sdkManager';
7
7
  import { sdkClientMethodFactory } from '../sdkClient/sdkClientMethod';
8
8
  import { impressionObserverSSFactory } from '../trackers/impressionObserver/impressionObserverSS';
9
- var syncManagerOnlineSSFactory = syncManagerOnlineFactory(pollingManagerSSFactory, pushManagerFactory);
9
+ var syncManagerOnlineSSFactory = syncManagerOnlineFactory(pollingManagerSSFactory(), pushManagerFactory);
10
10
  export var serverSideModules = {
11
11
  storageFactory: InMemoryStorageFactory,
12
- serviceApiFactory: serviceApiFactory,
12
+ serviceApiFactory: splitApiFactory,
13
13
  syncManagerFactory: syncManagerOnlineSSFactory,
14
14
  sdkManagerFactory: sdkManagerFactory,
15
15
  sdkClientMethodFactory: sdkClientMethodFactory,
@@ -1,4 +1,4 @@
1
- import { authenticateFactory } from '../sync/streaming/AuthClient';
1
+ import { fetchAuthFactory } from '../sync/streaming/AuthClient';
2
2
  import { Backoff } from '../utils/Backoff';
3
3
  import { LOG_PREFIX_SYNC_AUTH } from '../logger/constants';
4
4
  import { TOKEN } from '../utils/constants';
@@ -12,17 +12,16 @@ function isExpired(credential) {
12
12
  */
13
13
  export function authProviderFactory(settings, splitHttpClient, telemetryTracker) {
14
14
  var urls = settings.urls, log = settings.log;
15
- function fetchAuth() {
15
+ var fetchAuth = fetchAuthFactory(function () {
16
16
  var url = "".concat(urls.auth, "/api/v3/auth?capabilities=config,aiconfig");
17
17
  return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN), false, true);
18
- }
19
- var authenticate = authenticateFactory(fetchAuth);
18
+ });
20
19
  var backoff = new Backoff(fetchCredential);
21
20
  var cachedCredential;
22
21
  var inFlightPromise;
23
22
  var stopped = false;
24
23
  function fetchCredential() {
25
- return authenticate().then(function (credential) {
24
+ return fetchAuth().then(function (credential) {
26
25
  log.info(LOG_PREFIX_SYNC_AUTH + 'credential fetched successfully');
27
26
  cachedCredential = credential;
28
27
  inFlightPromise = undefined;
@@ -1,17 +1,12 @@
1
1
  import { __assign } from "tslib";
2
- import { splitHttpClientFactory } from './splitHttpClient';
3
- import { authProviderFactory } from './authProvider';
4
2
  /**
5
3
  * Factory of Secure HTTP client, which authenticates requests using a JWT token.
6
4
  * On 401 responses, invalidates the cached credential and retries once with a fresh token.
7
5
  *
8
- * @param settings - SDK settings
9
- * @param platform - object containing environment-specific dependencies
10
- * @param fetchAuth - function to fetch auth credentials from the /v2/auth endpoint
6
+ * @param splitHttpClient - `splitHttpClientFactory` to use for making requests
7
+ * @param authProvider - `authProviderFactory` to use for authentication
11
8
  */
12
- export function secureSplitHttpClientFactory(settings, platform, telemetryTracker) {
13
- var splitHttpClient = splitHttpClientFactory(settings, platform);
14
- var authProvider = authProviderFactory(settings, splitHttpClient, telemetryTracker);
9
+ export function secureSplitHttpClientFactory(splitHttpClient, authProvider) {
15
10
  function makeRequest(url, options, latencyTracker, logErrorsAsInfo, token) {
16
11
  return splitHttpClient(url, __assign(__assign({}, options), { headers: __assign(__assign({}, options === null || options === void 0 ? void 0 : options.headers), { Authorization: "Bearer ".concat(token) }) }), latencyTracker, logErrorsAsInfo, true);
17
12
  }
@@ -1,26 +1,37 @@
1
1
  import { splitHttpClientFactory } from './splitHttpClient';
2
2
  import { objectAssign } from '../utils/lang/objectAssign';
3
- import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MEMBERSHIPS } from '../utils/constants';
3
+ import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, SEGMENT, MEMBERSHIPS } from '../utils/constants';
4
4
  import { ERROR_TOO_MANY_SETS } from '../logger/constants';
5
+ import { authProviderFactory } from './authProvider';
6
+ import { secureSplitHttpClientFactory } from './secureSplitHttpClient';
5
7
  var noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
6
- function userKeyToQueryParam(userKey) {
7
- return 'users=' + encodeURIComponent(userKey); // no need to check availability of `encodeURIComponent`, since it is a global highly supported.
8
- }
9
8
  /**
10
9
  * Factory of ServiceApi objects, which group the collection of HTTP endpoints used by the SDKs
11
10
  *
12
11
  * @param settings - validated settings object
13
12
  * @param platform - object containing environment-specific dependencies
14
13
  * @param telemetryTracker - telemetry tracker
15
- * @param secureSplitHttpClientFactory - factory of SecureSplitHttpClient objects
16
14
  */
17
- export function serviceApiFactory(settings, platform, telemetryTracker, secureSplitHttpClientFactory) {
15
+ export function serviceApiFactory(settings, platform, telemetryTracker) {
18
16
  var urls = settings.urls;
19
17
  var filterQueryString = settings.sync.__splitFiltersValidation && settings.sync.__splitFiltersValidation.queryString;
20
18
  var SplitSDKImpressionsMode = settings.sync.impressionsMode;
21
19
  var splitHttpClient = splitHttpClientFactory(settings, platform);
22
- var secureSplitHttpClient = secureSplitHttpClientFactory(settings, platform, telemetryTracker);
20
+ // Shared authProvider so that the SSE authentication (via `fetchAuth`,
21
+ // used by `pushManager`) and every authenticated HTTP request to the Configs
22
+ // API reuse the same cached credential instead of each fetching their own.
23
+ var authProvider = authProviderFactory(settings, splitHttpClient, telemetryTracker);
24
+ var secureSplitHttpClient = secureSplitHttpClientFactory(splitHttpClient, authProvider);
25
+ var initialAuth = true;
23
26
  return {
27
+ fetchAuth: function () {
28
+ // Guard condition to avoid invalidating the cached credential on the first pushManager authentication
29
+ if (initialAuth)
30
+ initialAuth = false;
31
+ else
32
+ authProvider.invalidate();
33
+ return authProvider.credential();
34
+ },
24
35
  // @TODO throw errors if health check requests fail, to log them in the Synchronizer
25
36
  getSdkAPIHealthCheck: function () {
26
37
  var url = "".concat(urls.sdk, "/api/version");
@@ -30,15 +41,6 @@ export function serviceApiFactory(settings, platform, telemetryTracker, secureSp
30
41
  var url = "".concat(urls.events, "/api/version");
31
42
  return splitHttpClient(url).then(function () { return true; }).catch(function () { return false; });
32
43
  },
33
- fetchAuth: function (userMatchingKeys) {
34
- var url = "".concat(urls.auth, "/api/v2/auth?s=").concat(settings.sync.flagSpecVersion);
35
- if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
36
- var queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
37
- if (queryParams)
38
- url += '&' + queryParams;
39
- }
40
- return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN));
41
- },
42
44
  fetchSplitChanges: function (since, noCache, till, rbSince) {
43
45
  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 : '');
44
46
  return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SPLITS))
@@ -2,6 +2,7 @@ import { splitHttpClientFactory } from './splitHttpClient';
2
2
  import { objectAssign } from '../utils/lang/objectAssign';
3
3
  import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MEMBERSHIPS } from '../utils/constants';
4
4
  import { ERROR_TOO_MANY_SETS } from '../logger/constants';
5
+ import { fetchAuthFactory } from '../sync/streaming/AuthClient';
5
6
  var noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
6
7
  function userKeyToQueryParam(userKey) {
7
8
  return 'users=' + encodeURIComponent(userKey); // no need to check availability of `encodeURIComponent`, since it is a global highly supported.
@@ -20,6 +21,15 @@ export function splitApiFactory(settings, platform, telemetryTracker) {
20
21
  var SplitSDKImpressionsMode = settings.sync.impressionsMode;
21
22
  var splitHttpClient = splitHttpClientFactory(settings, platform);
22
23
  return {
24
+ fetchAuth: fetchAuthFactory(function (userMatchingKeys) {
25
+ var url = "".concat(urls.auth, "/v2/auth?s=").concat(settings.sync.flagSpecVersion);
26
+ if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
27
+ var queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
28
+ if (queryParams)
29
+ url += '&' + queryParams;
30
+ }
31
+ return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN));
32
+ }),
23
33
  // @TODO throw errors if health check requests fail, to log them in the Synchronizer
24
34
  getSdkAPIHealthCheck: function () {
25
35
  var url = "".concat(urls.sdk, "/version");
@@ -29,15 +39,6 @@ export function splitApiFactory(settings, platform, telemetryTracker) {
29
39
  var url = "".concat(urls.events, "/version");
30
40
  return splitHttpClient(url).then(function () { return true; }).catch(function () { return false; });
31
41
  },
32
- fetchAuth: function (userMatchingKeys) {
33
- var url = "".concat(urls.auth, "/v2/auth?s=").concat(settings.sync.flagSpecVersion);
34
- if (userMatchingKeys) { // `userMatchingKeys` is undefined in server-side
35
- var queryParams = userMatchingKeys.map(userKeyToQueryParam).join('&');
36
- if (queryParams)
37
- url += '&' + queryParams;
38
- }
39
- return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN));
40
- },
41
42
  fetchSplitChanges: function (since, noCache, till, rbSince) {
42
43
  var url = "".concat(urls.sdk, "/splitChanges?s=").concat(settings.sync.flagSpecVersion, "&since=").concat(since).concat(rbSince ? '&rbSince=' + rbSince : '').concat(filterQueryString || '').concat(till ? '&till=' + till : '');
43
44
  return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SPLITS))
@@ -5,92 +5,97 @@ import { getMatching } from '../../utils/key';
5
5
  import { SDK_DEFINITIONS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants';
6
6
  import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger/constants';
7
7
  import { usesSegmentsSync } from '../../storages/AbstractDefinitionsCacheSync';
8
+ import { splitChangesFetcherFactory } from './fetchers/splitChangesFetcher';
8
9
  /**
9
10
  * Expose start / stop mechanism for polling data from services.
10
11
  * For client-side API with multiple clients.
11
12
  */
12
- export function pollingManagerCSFactory(params, definitionChangesFetcher) {
13
- var serviceApi = params.serviceApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
14
- var log = settings.log;
15
- var definitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings);
16
- // Map of matching keys to their corresponding MySegmentsSyncTask.
17
- var mySegmentsSyncTasks = {};
18
- var matchingKey = getMatching(settings.core.key);
19
- var mySegmentsSyncTask = add(matchingKey, readiness, storage);
20
- function startMySegmentsSyncTasks() {
21
- forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
22
- mySegmentsSyncTask.start();
23
- });
24
- }
25
- function stopMySegmentsSyncTasks() {
26
- forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
27
- if (mySegmentsSyncTask.isRunning())
28
- mySegmentsSyncTask.stop();
29
- });
30
- }
31
- // smart pausing
32
- readiness.definitions.on(SDK_DEFINITIONS_ARRIVED, function () {
33
- if (!definitionsSyncTask.isRunning())
34
- return; // noop if not doing polling
35
- var usingSegments = usesSegmentsSync(storage);
36
- if (usingSegments !== mySegmentsSyncTask.isRunning()) {
37
- log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
38
- if (usingSegments) {
39
- startMySegmentsSyncTasks();
40
- }
41
- else {
42
- stopMySegmentsSyncTasks();
43
- }
44
- }
45
- });
46
- function add(matchingKey, readiness, storage) {
47
- var mySegmentsSyncTask = mySegmentsSyncTaskFactory(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
48
- // smart ready
49
- function smartReady(metadata) {
50
- if (!readiness.isReady() && !usesSegmentsSync(storage))
51
- readiness.segments.emit(SDK_SEGMENTS_ARRIVED, metadata);
13
+ export function pollingManagerCSFactory(definitionFetcherFactory) {
14
+ if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcherFactory; }
15
+ return function (params) {
16
+ var serviceApi = params.serviceApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
17
+ var log = settings.log;
18
+ var definitionChangesFetcher = definitionFetcherFactory(params);
19
+ var definitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings);
20
+ // Map of matching keys to their corresponding MySegmentsSyncTask.
21
+ var mySegmentsSyncTasks = {};
22
+ var matchingKey = getMatching(settings.core.key);
23
+ var mySegmentsSyncTask = add(matchingKey, readiness, storage);
24
+ function startMySegmentsSyncTasks() {
25
+ forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
26
+ mySegmentsSyncTask.start();
27
+ });
52
28
  }
53
- if (!usesSegmentsSync(storage))
54
- setTimeout(smartReady, 0);
55
- else
56
- readiness.definitions.once(SDK_DEFINITIONS_ARRIVED, smartReady);
57
- mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
58
- return mySegmentsSyncTask;
59
- }
60
- return {
61
- definitionsSyncTask: definitionsSyncTask,
62
- segmentsSyncTask: mySegmentsSyncTask,
63
- // Start periodic fetching (polling)
64
- start: function () {
65
- log.info(POLLING_START);
66
- definitionsSyncTask.start();
67
- if (usesSegmentsSync(storage))
68
- startMySegmentsSyncTasks();
69
- },
70
- // Stop periodic fetching (polling)
71
- stop: function () {
72
- log.info(POLLING_STOP);
73
- if (definitionsSyncTask.isRunning())
74
- definitionsSyncTask.stop();
75
- stopMySegmentsSyncTasks();
76
- },
77
- // Used by SyncManager to know if running in polling mode.
78
- isRunning: definitionsSyncTask.isRunning,
79
- // fetch definitions and segments
80
- syncAll: function () {
81
- var promises = [definitionsSyncTask.execute()];
29
+ function stopMySegmentsSyncTasks() {
82
30
  forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
83
- promises.push(mySegmentsSyncTask.execute());
31
+ if (mySegmentsSyncTask.isRunning())
32
+ mySegmentsSyncTask.stop();
84
33
  });
85
- return Promise.all(promises);
86
- },
87
- // Support for handling mySegments sync of multiple clients
88
- add: add,
89
- remove: function (matchingKey) {
90
- delete mySegmentsSyncTasks[matchingKey];
91
- },
92
- get: function (matchingKey) {
93
- return mySegmentsSyncTasks[matchingKey];
94
34
  }
35
+ // smart pausing
36
+ readiness.definitions.on(SDK_DEFINITIONS_ARRIVED, function () {
37
+ if (!definitionsSyncTask.isRunning())
38
+ return; // noop if not doing polling
39
+ var usingSegments = usesSegmentsSync(storage);
40
+ if (usingSegments !== mySegmentsSyncTask.isRunning()) {
41
+ log.info(POLLING_SMART_PAUSING, [usingSegments ? 'ON' : 'OFF']);
42
+ if (usingSegments) {
43
+ startMySegmentsSyncTasks();
44
+ }
45
+ else {
46
+ stopMySegmentsSyncTasks();
47
+ }
48
+ }
49
+ });
50
+ function add(matchingKey, readiness, storage) {
51
+ var mySegmentsSyncTask = mySegmentsSyncTaskFactory(serviceApi.fetchMemberships, storage, readiness, settings, matchingKey);
52
+ // smart ready
53
+ function smartReady(metadata) {
54
+ if (!readiness.isReady() && !usesSegmentsSync(storage))
55
+ readiness.segments.emit(SDK_SEGMENTS_ARRIVED, metadata);
56
+ }
57
+ if (!usesSegmentsSync(storage))
58
+ setTimeout(smartReady, 0);
59
+ else
60
+ readiness.definitions.once(SDK_DEFINITIONS_ARRIVED, smartReady);
61
+ mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
62
+ return mySegmentsSyncTask;
63
+ }
64
+ return {
65
+ definitionsSyncTask: definitionsSyncTask,
66
+ segmentsSyncTask: mySegmentsSyncTask,
67
+ // Start periodic fetching (polling)
68
+ start: function () {
69
+ log.info(POLLING_START);
70
+ definitionsSyncTask.start();
71
+ if (usesSegmentsSync(storage))
72
+ startMySegmentsSyncTasks();
73
+ },
74
+ // Stop periodic fetching (polling)
75
+ stop: function () {
76
+ log.info(POLLING_STOP);
77
+ if (definitionsSyncTask.isRunning())
78
+ definitionsSyncTask.stop();
79
+ stopMySegmentsSyncTasks();
80
+ },
81
+ // Used by SyncManager to know if running in polling mode.
82
+ isRunning: definitionsSyncTask.isRunning,
83
+ // fetch definitions and segments
84
+ syncAll: function () {
85
+ var promises = [definitionsSyncTask.execute()];
86
+ forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
87
+ promises.push(mySegmentsSyncTask.execute());
88
+ });
89
+ return Promise.all(promises);
90
+ },
91
+ // Support for handling mySegments sync of multiple clients
92
+ add: add,
93
+ remove: function (matchingKey) {
94
+ delete mySegmentsSyncTasks[matchingKey];
95
+ },
96
+ get: function (matchingKey) {
97
+ return mySegmentsSyncTasks[matchingKey];
98
+ }
99
+ };
95
100
  };
96
101
  }
@@ -1,45 +1,53 @@
1
1
  import { definitionsSyncTaskFactory } from './syncTasks/definitionsSyncTask';
2
2
  import { segmentsSyncTaskFactory } from './syncTasks/segmentsSyncTask';
3
3
  import { POLLING_START, POLLING_STOP, LOG_PREFIX_SYNC_POLLING } from '../../logger/constants';
4
+ import { segmentChangesFetcherFactory } from './fetchers/segmentChangesFetcher';
5
+ import { splitChangesFetcherFactory } from './fetchers/splitChangesFetcher';
4
6
  /**
5
7
  * Expose start / stop mechanism for pulling data from services.
6
8
  */
7
- export function pollingManagerSSFactory(params, definitionChangesFetcher, segmentChangesFetcher) {
8
- var storage = params.storage, readiness = params.readiness, settings = params.settings;
9
- var log = settings.log;
10
- var segmentsSyncTask = segmentsSyncTaskFactory(segmentChangesFetcher, storage, readiness, settings);
11
- var definitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings, segmentsSyncTask);
12
- return {
13
- definitionsSyncTask: definitionsSyncTask,
14
- segmentsSyncTask: segmentsSyncTask,
15
- // Start periodic fetching (polling)
16
- start: function () {
17
- log.info(POLLING_START);
18
- log.debug(LOG_PREFIX_SYNC_POLLING + "".concat(definitionChangesFetcher.type, " 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 = definitionsSyncTask.start();
21
- if (startingUp) {
22
- startingUp.then(function () {
23
- if (definitionsSyncTask.isRunning())
24
- segmentsSyncTask.start();
9
+ export function pollingManagerSSFactory(definitionFetcherFactory, segmentFetcherFactory) {
10
+ if (definitionFetcherFactory === void 0) { definitionFetcherFactory = splitChangesFetcherFactory; }
11
+ if (segmentFetcherFactory === void 0) { segmentFetcherFactory = function (params) { return segmentChangesFetcherFactory(params.serviceApi.fetchSegmentChanges); }; }
12
+ return function (params) {
13
+ var storage = params.storage, readiness = params.readiness, settings = params.settings;
14
+ var log = settings.log;
15
+ var definitionChangesFetcher = definitionFetcherFactory(params);
16
+ var segmentChangesFetcher = segmentFetcherFactory(params);
17
+ var segmentsSyncTask = segmentsSyncTaskFactory(segmentChangesFetcher, storage, readiness, settings);
18
+ var definitionsSyncTask = definitionsSyncTaskFactory(definitionChangesFetcher, storage, readiness, settings, segmentsSyncTask);
19
+ return {
20
+ definitionsSyncTask: definitionsSyncTask,
21
+ segmentsSyncTask: segmentsSyncTask,
22
+ // Start periodic fetching (polling)
23
+ start: function () {
24
+ log.info(POLLING_START);
25
+ log.debug(LOG_PREFIX_SYNC_POLLING + "".concat(definitionChangesFetcher.type, " will be refreshed each ").concat(settings.scheduler.featuresRefreshRate, " millis"));
26
+ log.debug(LOG_PREFIX_SYNC_POLLING + "segments will be refreshed each ".concat(settings.scheduler.segmentsRefreshRate, " millis"));
27
+ var startingUp = definitionsSyncTask.start();
28
+ if (startingUp) {
29
+ startingUp.then(function () {
30
+ if (definitionsSyncTask.isRunning())
31
+ segmentsSyncTask.start();
32
+ });
33
+ }
34
+ },
35
+ // Stop periodic fetching (polling)
36
+ stop: function () {
37
+ log.info(POLLING_STOP);
38
+ if (definitionsSyncTask.isRunning())
39
+ definitionsSyncTask.stop();
40
+ if (segmentsSyncTask.isRunning())
41
+ segmentsSyncTask.stop();
42
+ },
43
+ // Used by SyncManager to know if running in polling mode.
44
+ isRunning: definitionsSyncTask.isRunning,
45
+ syncAll: function () {
46
+ // fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
47
+ return definitionsSyncTask.execute().then(function () {
48
+ return segmentsSyncTask.execute();
25
49
  });
26
50
  }
27
- },
28
- // Stop periodic fetching (polling)
29
- stop: function () {
30
- log.info(POLLING_STOP);
31
- if (definitionsSyncTask.isRunning())
32
- definitionsSyncTask.stop();
33
- if (segmentsSyncTask.isRunning())
34
- segmentsSyncTask.stop();
35
- },
36
- // Used by SyncManager to know if running in polling mode.
37
- isRunning: definitionsSyncTask.isRunning,
38
- syncAll: function () {
39
- // fetch definitions and segments. There is no need to catch this promise (`DefinitionChangesUpdater` is always resolved with a boolean value)
40
- return definitionsSyncTask.execute().then(function () {
41
- return segmentsSyncTask.execute();
42
- });
43
- }
51
+ };
44
52
  };
45
53
  }
@@ -4,7 +4,7 @@ import { SYNC_FETCH, SYNC_UPDATE, SYNC_FETCH_FAILS, SYNC_FETCH_RETRY } from '../
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
- import { SPLIT_UPDATE } from '../../streaming/constants';
7
+ import { RB_SEGMENT_UPDATE } from '../../streaming/constants';
8
8
  /**
9
9
  * Collect segments from a raw FF or RBS definition.
10
10
  * Exported for testing purposes.
@@ -120,14 +120,14 @@ export function definitionChangesUpdaterFactory(log, definitionChangesFetcher, s
120
120
  var since = sinces[0], rbSince = sinces[1];
121
121
  log.debug(SYNC_FETCH, [definitionChangesFetcher.type, since, rbSince]);
122
122
  return Promise.resolve(instantUpdate ?
123
- instantUpdate.type === SPLIT_UPDATE ?
123
+ instantUpdate.type === RB_SEGMENT_UPDATE ?
124
+ { rbs: convertInstantUpdateToDefinitionChanges(instantUpdate) } :
124
125
  // IFFU edge case: a change to definition that adds an IN_RULE_BASED_SEGMENT matcher that is not present yet
125
126
  Promise.resolve(rbSegments.contains(parseSegments(instantUpdate.payload, IN_RULE_BASED_SEGMENT))).then(function (contains) {
126
127
  return contains ?
127
128
  { d: convertInstantUpdateToDefinitionChanges(instantUpdate) } :
128
129
  definitionChangesFetcher(since, noCache, till, rbSince, _promiseDecorator);
129
130
  }) :
130
- { rbs: convertInstantUpdateToDefinitionChanges(instantUpdate) } :
131
131
  definitionChangesFetcher(since, noCache, till, rbSince, _promiseDecorator))
132
132
  .then(function (definitionChanges) {
133
133
  var usedSegments = new Set();
@@ -28,7 +28,7 @@ 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(LOG_PREFIX_SYNC, "Processing ").concat(segmentName, " with till = ").concat(x.till, ". Added: ").concat(x.added.length, ". Removed: ").concat(x.removed.length));
31
+ log.debug("".concat(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));
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; });
@@ -1,13 +1,11 @@
1
1
  import { objectAssign } from '../../../utils/lang/objectAssign';
2
- import { encodeToBase64 } from '../../../utils/base64';
3
2
  import { decodeJWTtoken } from '../../../utils/jwt';
4
- import { hash } from '../../../utils/murmur3/murmur3';
5
3
  /**
6
4
  * Factory of authentication function.
7
5
  *
8
- * @param fetchAuth - `ServiceApi.fetchAuth` endpoint
6
+ * @param fetchAuth - /auth endpoint
9
7
  */
10
- export function authenticateFactory(fetchAuth) {
8
+ export function fetchAuthFactory(fetchAuth) {
11
9
  /**
12
10
  * Run authentication requests to Auth Server, and returns a promise that resolves with the decoded JTW token.
13
11
  * @param userKeys - set of user Keys to track membership updates. It is undefined for server-side API.
@@ -21,18 +19,20 @@ export function authenticateFactory(fetchAuth) {
21
19
  if (typeof decodedToken.iat !== 'number' || typeof decodedToken.exp !== 'number')
22
20
  throw new Error('token properties "issuedAt" (iat) or "expiration" (exp) are missing or invalid');
23
21
  var channels = JSON.parse(decodedToken['x-ably-capability']);
24
- return objectAssign({
22
+ var credential = objectAssign({
25
23
  decodedToken: decodedToken,
26
24
  channels: channels
27
25
  }, json);
26
+ // The `/api/v3/auth` endpoint nests the streaming settings under `config.streaming`. Normalize
27
+ // them into the flat `pushEnabled`/`connDelay` properties used by the PushManager.
28
+ var streaming = credential.config && credential.config.streaming;
29
+ if (streaming) {
30
+ credential.pushEnabled = streaming.enabled;
31
+ credential.connDelay = streaming.delay;
32
+ }
33
+ return credential;
28
34
  }
29
35
  return json;
30
36
  });
31
37
  };
32
38
  }
33
- /**
34
- * Returns the hash of a given user key
35
- */
36
- export function hashUserKey(userKey) {
37
- return encodeToBase64(hash(userKey, 0).toString());
38
- }
@@ -1,6 +1,6 @@
1
1
  import { errorParser, messageParser } from './NotificationParser';
2
2
  import { notificationKeeperFactory } from './NotificationKeeper';
3
- import { PUSH_RETRYABLE_ERROR, PUSH_NON_RETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, RB_SEGMENT_UPDATE } from '../constants';
3
+ import { PUSH_RETRYABLE_ERROR, PUSH_NON_RETRYABLE_ERROR, OCCUPANCY, CONTROL, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, CONFIG_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
  /**
@@ -71,6 +71,7 @@ export function SSEHandlerFactory(log, pushEmitter, telemetryTracker) {
71
71
  switch (parsedData.type) {
72
72
  /* update events */
73
73
  case SPLIT_UPDATE:
74
+ case CONFIG_UPDATE:
74
75
  case SEGMENT_UPDATE:
75
76
  case MEMBERSHIPS_MS_UPDATE:
76
77
  case MEMBERSHIPS_LS_UPDATE:
@@ -27,6 +27,7 @@ export var MEMBERSHIPS_LS_UPDATE = 'MEMBERSHIPS_LS_UPDATE';
27
27
  export var SEGMENT_UPDATE = 'SEGMENT_UPDATE';
28
28
  export var SPLIT_KILL = 'SPLIT_KILL';
29
29
  export var SPLIT_UPDATE = 'SPLIT_UPDATE';
30
+ export var CONFIG_UPDATE = 'CONFIG_UPDATE';
30
31
  export var RB_SEGMENT_UPDATE = 'RB_SEGMENT_UPDATE';
31
32
  // Control-type push notifications, handled by NotificationKeeper
32
33
  export var CONTROL = 'CONTROL';