@splitsoftware/splitio-commons 1.16.1-rc.0 → 1.16.1-rc.1

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 (33) hide show
  1. package/cjs/readiness/readinessManager.js +4 -5
  2. package/cjs/storages/pluggable/inMemoryWrapper.js +1 -1
  3. package/cjs/sync/polling/fetchers/mySegmentsFetcher.js +5 -1
  4. package/cjs/sync/polling/pollingManagerCS.js +11 -17
  5. package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
  6. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +2 -8
  7. package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +10 -1
  8. package/cjs/sync/streaming/pushManager.js +0 -1
  9. package/esm/readiness/readinessManager.js +4 -5
  10. package/esm/storages/pluggable/inMemoryWrapper.js +1 -1
  11. package/esm/sync/polling/fetchers/mySegmentsFetcher.js +5 -1
  12. package/esm/sync/polling/pollingManagerCS.js +11 -17
  13. package/esm/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
  14. package/esm/sync/polling/updaters/mySegmentsUpdater.js +2 -8
  15. package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +10 -1
  16. package/esm/sync/streaming/pushManager.js +0 -1
  17. package/package.json +1 -1
  18. package/src/dtos/types.ts +10 -6
  19. package/src/readiness/readinessManager.ts +3 -5
  20. package/src/storages/pluggable/inMemoryWrapper.ts +1 -1
  21. package/src/storages/types.ts +1 -1
  22. package/src/sync/polling/fetchers/mySegmentsFetcher.ts +6 -2
  23. package/src/sync/polling/pollingManagerCS.ts +12 -15
  24. package/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +3 -2
  25. package/src/sync/polling/types.ts +1 -1
  26. package/src/sync/polling/updaters/mySegmentsUpdater.ts +2 -8
  27. package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +11 -1
  28. package/src/sync/streaming/pushManager.ts +1 -2
  29. package/types/dtos/types.d.ts +9 -5
  30. package/types/storages/pluggable/inMemoryWrapper.d.ts +1 -1
  31. package/types/sync/polling/syncTasks/mySegmentsSyncTask.d.ts +1 -1
  32. package/types/sync/polling/types.d.ts +1 -1
  33. package/types/sync/streaming/pushManager.d.ts +1 -1
@@ -16,10 +16,9 @@ function splitsEventEmitterFactory(EventEmitter) {
16
16
  splitsEventEmitter.once(constants_1.SDK_SPLITS_CACHE_LOADED, function () { splitsEventEmitter.splitsCacheLoaded = true; });
17
17
  return splitsEventEmitter;
18
18
  }
19
- function segmentsEventEmitterFactory(EventEmitter) {
20
- var segmentsEventEmitter = (0, objectAssign_1.objectAssign)(new EventEmitter(), {
21
- segmentsArrived: false
22
- });
19
+ function segmentsEventEmitterFactory(EventEmitter, segmentsArrived) {
20
+ if (segmentsArrived === void 0) { segmentsArrived = false; }
21
+ var segmentsEventEmitter = (0, objectAssign_1.objectAssign)(new EventEmitter(), { segmentsArrived: segmentsArrived });
23
22
  segmentsEventEmitter.once(constants_1.SDK_SEGMENTS_ARRIVED, function () { segmentsEventEmitter.segmentsArrived = true; });
24
23
  return segmentsEventEmitter;
25
24
  }
@@ -30,7 +29,7 @@ function readinessManagerFactory(EventEmitter, settings, splits) {
30
29
  if (splits === void 0) { splits = splitsEventEmitterFactory(EventEmitter); }
31
30
  var _a = settings.startup, readyTimeout = _a.readyTimeout, waitForLargeSegments = _a.waitForLargeSegments, largeSegmentsEnabled = settings.sync.largeSegmentsEnabled;
32
31
  var segments = segmentsEventEmitterFactory(EventEmitter);
33
- var largeSegments = largeSegmentsEnabled && waitForLargeSegments ? segmentsEventEmitterFactory(EventEmitter) : undefined;
32
+ var largeSegments = largeSegmentsEnabled ? segmentsEventEmitterFactory(EventEmitter, !waitForLargeSegments) : undefined;
34
33
  var gate = new EventEmitter();
35
34
  // emit SDK_READY_FROM_CACHE
36
35
  var isReadyFromCache = false;
@@ -8,7 +8,7 @@ var sets_1 = require("../../utils/lang/sets");
8
8
  * The `_cache` property is the object were items are stored.
9
9
  * Intended for testing purposes.
10
10
  *
11
- * @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves inmediatelly.
11
+ * @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves immediately.
12
12
  */
13
13
  function inMemoryWrapperFactory(connDelay) {
14
14
  var _cache = {};
@@ -15,7 +15,11 @@ function mySegmentsFetcherFactory(fetchMySegments) {
15
15
  // Extract segment names
16
16
  return mySegmentsPromise
17
17
  .then(function (resp) { return resp.json(); })
18
- .then(function (json) { return json.mySegments.map(function (segment) { return segment.name; }); });
18
+ .then(function (json) {
19
+ return json.mySegments ?
20
+ json.mySegments.map(function (segment) { return segment.name; }) :
21
+ json.myLargeSegments;
22
+ });
19
23
  };
20
24
  }
21
25
  exports.mySegmentsFetcherFactory = mySegmentsFetcherFactory;
@@ -28,12 +28,12 @@ function pollingManagerCSFactory(params) {
28
28
  if (splitsHaveSegments)
29
29
  msSyncTask.start();
30
30
  else
31
- msSyncTask.stop();
31
+ msSyncTask.stop(); // smart pausing
32
32
  if (mlsSyncTask) {
33
33
  if (splitsHaveLargeSegments)
34
34
  mlsSyncTask.start();
35
35
  else
36
- mlsSyncTask.stop();
36
+ mlsSyncTask.stop(); // smart pausing
37
37
  }
38
38
  });
39
39
  }
@@ -44,37 +44,31 @@ function pollingManagerCSFactory(params) {
44
44
  mlsSyncTask && mlsSyncTask.stop();
45
45
  });
46
46
  }
47
- // smart pausing
48
47
  readiness.splits.on(constants_1.SDK_SPLITS_ARRIVED, function () {
49
- // smart pausing of mySegments polling
50
48
  if (splitsSyncTask.isRunning())
51
49
  startMySegmentsSyncTasks();
52
50
  });
53
51
  function add(matchingKey, readiness, storage) {
54
- var msSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(splitApi.fetchMySegments, storage.segments, function () {
55
- if (storage.splits.usesMatcher(constants_3.IN_SEGMENT))
56
- readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED);
57
- }, settings, matchingKey, settings.scheduler.segmentsRefreshRate);
52
+ var msSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(splitApi.fetchMySegments, storage.segments, function () { if (storage.splits.usesMatcher(constants_3.IN_SEGMENT))
53
+ readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED); }, settings, matchingKey, settings.scheduler.segmentsRefreshRate, 'mySegmentsUpdater');
58
54
  var mlsSyncTask;
59
55
  if (settings.sync.largeSegmentsEnabled) {
60
- mlsSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(splitApi.fetchMyLargeSegments, storage.largeSegments, function () {
61
- if (readiness.largeSegments && storage.splits.usesMatcher(constants_3.IN_LARGE_SEGMENT))
62
- readiness.largeSegments.emit(constants_1.SDK_SEGMENTS_ARRIVED);
63
- }, settings, matchingKey, settings.scheduler.largeSegmentsRefreshRate);
56
+ mlsSyncTask = (0, mySegmentsSyncTask_1.mySegmentsSyncTaskFactory)(splitApi.fetchMyLargeSegments, storage.largeSegments, function () { if (readiness.largeSegments && storage.splits.usesMatcher(constants_3.IN_LARGE_SEGMENT))
57
+ readiness.largeSegments.emit(constants_1.SDK_SEGMENTS_ARRIVED); }, settings, matchingKey, settings.scheduler.largeSegmentsRefreshRate, 'myLargeSegmentsUpdater');
64
58
  }
65
59
  // smart ready
66
60
  function smartReady() {
67
61
  if (!readiness.isReady()) {
68
- if (!storage.splits.usesMatcher(constants_3.IN_SEGMENT))
69
- readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED);
70
62
  if (readiness.largeSegments && !storage.splits.usesMatcher(constants_3.IN_LARGE_SEGMENT))
71
63
  readiness.largeSegments.emit(constants_1.SDK_SEGMENTS_ARRIVED);
64
+ if (!storage.splits.usesMatcher(constants_3.IN_SEGMENT))
65
+ readiness.segments.emit(constants_1.SDK_SEGMENTS_ARRIVED);
72
66
  }
73
67
  }
74
- if (!storage.splits.usesMatcher(constants_3.IN_SEGMENT) && !storage.splits.usesMatcher(constants_3.IN_LARGE_SEGMENT))
75
- setTimeout(smartReady, 0);
76
- else
68
+ if (storage.splits.usesMatcher(constants_3.IN_SEGMENT) && storage.splits.usesMatcher(constants_3.IN_LARGE_SEGMENT))
77
69
  readiness.splits.once(constants_1.SDK_SPLITS_ARRIVED, smartReady);
70
+ else
71
+ setTimeout(smartReady, 0);
78
72
  mySegmentsSyncTasks[matchingKey] = { msSyncTask: msSyncTask, mlsSyncTask: mlsSyncTask };
79
73
  return {
80
74
  msSyncTask: msSyncTask,
@@ -7,7 +7,7 @@ var mySegmentsUpdater_1 = require("../updaters/mySegmentsUpdater");
7
7
  /**
8
8
  * Creates a sync task that periodically executes a `mySegmentsUpdater` task
9
9
  */
10
- function mySegmentsSyncTaskFactory(fetchMySegments, mySegmentsCache, notifyUpdate, settings, matchingKey, segmentsRefreshRate) {
11
- return (0, syncTask_1.syncTaskFactory)(settings.log, (0, mySegmentsUpdater_1.mySegmentsUpdaterFactory)(settings.log, (0, mySegmentsFetcher_1.mySegmentsFetcherFactory)(fetchMySegments), mySegmentsCache, notifyUpdate, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, matchingKey), segmentsRefreshRate, 'mySegmentsUpdater');
10
+ function mySegmentsSyncTaskFactory(fetchMySegments, mySegmentsCache, notifyUpdate, settings, matchingKey, segmentsRefreshRate, NAME) {
11
+ return (0, syncTask_1.syncTaskFactory)(settings.log, (0, mySegmentsUpdater_1.mySegmentsUpdaterFactory)(settings.log, (0, mySegmentsFetcher_1.mySegmentsFetcherFactory)(fetchMySegments), mySegmentsCache, notifyUpdate, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, matchingKey), segmentsRefreshRate, NAME);
12
12
  }
13
13
  exports.mySegmentsSyncTaskFactory = mySegmentsSyncTaskFactory;
@@ -78,14 +78,8 @@ function mySegmentsUpdaterFactory(log, mySegmentsFetcher, mySegmentsCache, notif
78
78
  * (3) or `undefined`, for which the updater will fetch mySegments in order to sync the storage.
79
79
  * @param {boolean | undefined} noCache true to revalidate data to fetch
80
80
  */
81
- return function mySegmentsUpdater(segmentsData, noCache, delay) {
82
- return delay ?
83
- new Promise(function (res) {
84
- setTimeout(function () {
85
- _mySegmentsUpdater(0, segmentsData, noCache).then(res);
86
- }, delay);
87
- }) :
88
- _mySegmentsUpdater(0, segmentsData, noCache);
81
+ return function mySegmentsUpdater(segmentsData, noCache) {
82
+ return _mySegmentsUpdater(0, segmentsData, noCache);
89
83
  };
90
84
  }
91
85
  exports.mySegmentsUpdaterFactory = mySegmentsUpdaterFactory;
@@ -12,6 +12,7 @@ function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, updateType
12
12
  var isHandlingEvent;
13
13
  var _segmentsData; // keeps the segmentsData (if included in notification payload) from the queued event with maximum changeNumber
14
14
  var _delay;
15
+ var _delayTimeoutID;
15
16
  var backoff = new Backoff_1.Backoff(__handleMySegmentsUpdateCall);
16
17
  function __handleMySegmentsUpdateCall() {
17
18
  isHandlingEvent = true;
@@ -19,7 +20,14 @@ function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, updateType
19
20
  handleNewEvent = false;
20
21
  var currentMaxChangeNumber_1 = maxChangeNumber;
21
22
  // fetch mySegments revalidating data if cached
22
- mySegmentsSyncTask.execute(_segmentsData, true, _delay).then(function (result) {
23
+ var syncTask = _delay ?
24
+ new Promise(function (res) {
25
+ _delayTimeoutID = setTimeout(function () {
26
+ mySegmentsSyncTask.execute(_segmentsData, true).then(res);
27
+ }, _delay);
28
+ }) :
29
+ mySegmentsSyncTask.execute(_segmentsData, true);
30
+ syncTask.then(function (result) {
23
31
  if (!isHandlingEvent)
24
32
  return; // halt if `stop` has been called
25
33
  if (result !== false) { // Unlike `Splits|SegmentsUpdateWorker`, we cannot use `mySegmentsCache.getChangeNumber` since `/mySegments` endpoint doesn't provide this value.
@@ -58,6 +66,7 @@ function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, updateType
58
66
  backoff.reset();
59
67
  },
60
68
  stop: function () {
69
+ clearTimeout(_delayTimeoutID);
61
70
  isHandlingEvent = false;
62
71
  backoff.reset();
63
72
  }
@@ -21,7 +21,6 @@ var murmur3_64_1 = require("../../utils/murmur3/murmur3_64");
21
21
  var constants_3 = require("../../utils/constants");
22
22
  function getDelay(parsedData, matchingKey) {
23
23
  var interval = parsedData.i || 60000;
24
- // const hashType = parsedData.h || 0;
25
24
  var seed = parsedData.s || 0;
26
25
  return (0, murmur3_1.hash)(matchingKey, seed) % interval;
27
26
  }
@@ -13,10 +13,9 @@ function splitsEventEmitterFactory(EventEmitter) {
13
13
  splitsEventEmitter.once(SDK_SPLITS_CACHE_LOADED, function () { splitsEventEmitter.splitsCacheLoaded = true; });
14
14
  return splitsEventEmitter;
15
15
  }
16
- function segmentsEventEmitterFactory(EventEmitter) {
17
- var segmentsEventEmitter = objectAssign(new EventEmitter(), {
18
- segmentsArrived: false
19
- });
16
+ function segmentsEventEmitterFactory(EventEmitter, segmentsArrived) {
17
+ if (segmentsArrived === void 0) { segmentsArrived = false; }
18
+ var segmentsEventEmitter = objectAssign(new EventEmitter(), { segmentsArrived: segmentsArrived });
20
19
  segmentsEventEmitter.once(SDK_SEGMENTS_ARRIVED, function () { segmentsEventEmitter.segmentsArrived = true; });
21
20
  return segmentsEventEmitter;
22
21
  }
@@ -27,7 +26,7 @@ export function readinessManagerFactory(EventEmitter, settings, splits) {
27
26
  if (splits === void 0) { splits = splitsEventEmitterFactory(EventEmitter); }
28
27
  var _a = settings.startup, readyTimeout = _a.readyTimeout, waitForLargeSegments = _a.waitForLargeSegments, largeSegmentsEnabled = settings.sync.largeSegmentsEnabled;
29
28
  var segments = segmentsEventEmitterFactory(EventEmitter);
30
- var largeSegments = largeSegmentsEnabled && waitForLargeSegments ? segmentsEventEmitterFactory(EventEmitter) : undefined;
29
+ var largeSegments = largeSegmentsEnabled ? segmentsEventEmitterFactory(EventEmitter, !waitForLargeSegments) : undefined;
31
30
  var gate = new EventEmitter();
32
31
  // emit SDK_READY_FROM_CACHE
33
32
  var isReadyFromCache = false;
@@ -5,7 +5,7 @@ import { setToArray, _Set } from '../../utils/lang/sets';
5
5
  * The `_cache` property is the object were items are stored.
6
6
  * Intended for testing purposes.
7
7
  *
8
- * @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves inmediatelly.
8
+ * @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves immediately.
9
9
  */
10
10
  export function inMemoryWrapperFactory(connDelay) {
11
11
  var _cache = {};
@@ -12,6 +12,10 @@ export function mySegmentsFetcherFactory(fetchMySegments) {
12
12
  // Extract segment names
13
13
  return mySegmentsPromise
14
14
  .then(function (resp) { return resp.json(); })
15
- .then(function (json) { return json.mySegments.map(function (segment) { return segment.name; }); });
15
+ .then(function (json) {
16
+ return json.mySegments ?
17
+ json.mySegments.map(function (segment) { return segment.name; }) :
18
+ json.myLargeSegments;
19
+ });
16
20
  };
17
21
  }
@@ -25,12 +25,12 @@ export function pollingManagerCSFactory(params) {
25
25
  if (splitsHaveSegments)
26
26
  msSyncTask.start();
27
27
  else
28
- msSyncTask.stop();
28
+ msSyncTask.stop(); // smart pausing
29
29
  if (mlsSyncTask) {
30
30
  if (splitsHaveLargeSegments)
31
31
  mlsSyncTask.start();
32
32
  else
33
- mlsSyncTask.stop();
33
+ mlsSyncTask.stop(); // smart pausing
34
34
  }
35
35
  });
36
36
  }
@@ -41,37 +41,31 @@ export function pollingManagerCSFactory(params) {
41
41
  mlsSyncTask && mlsSyncTask.stop();
42
42
  });
43
43
  }
44
- // smart pausing
45
44
  readiness.splits.on(SDK_SPLITS_ARRIVED, function () {
46
- // smart pausing of mySegments polling
47
45
  if (splitsSyncTask.isRunning())
48
46
  startMySegmentsSyncTasks();
49
47
  });
50
48
  function add(matchingKey, readiness, storage) {
51
- var msSyncTask = mySegmentsSyncTaskFactory(splitApi.fetchMySegments, storage.segments, function () {
52
- if (storage.splits.usesMatcher(IN_SEGMENT))
53
- readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
54
- }, settings, matchingKey, settings.scheduler.segmentsRefreshRate);
49
+ var msSyncTask = mySegmentsSyncTaskFactory(splitApi.fetchMySegments, storage.segments, function () { if (storage.splits.usesMatcher(IN_SEGMENT))
50
+ readiness.segments.emit(SDK_SEGMENTS_ARRIVED); }, settings, matchingKey, settings.scheduler.segmentsRefreshRate, 'mySegmentsUpdater');
55
51
  var mlsSyncTask;
56
52
  if (settings.sync.largeSegmentsEnabled) {
57
- mlsSyncTask = mySegmentsSyncTaskFactory(splitApi.fetchMyLargeSegments, storage.largeSegments, function () {
58
- if (readiness.largeSegments && storage.splits.usesMatcher(IN_LARGE_SEGMENT))
59
- readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED);
60
- }, settings, matchingKey, settings.scheduler.largeSegmentsRefreshRate);
53
+ mlsSyncTask = mySegmentsSyncTaskFactory(splitApi.fetchMyLargeSegments, storage.largeSegments, function () { if (readiness.largeSegments && storage.splits.usesMatcher(IN_LARGE_SEGMENT))
54
+ readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED); }, settings, matchingKey, settings.scheduler.largeSegmentsRefreshRate, 'myLargeSegmentsUpdater');
61
55
  }
62
56
  // smart ready
63
57
  function smartReady() {
64
58
  if (!readiness.isReady()) {
65
- if (!storage.splits.usesMatcher(IN_SEGMENT))
66
- readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
67
59
  if (readiness.largeSegments && !storage.splits.usesMatcher(IN_LARGE_SEGMENT))
68
60
  readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED);
61
+ if (!storage.splits.usesMatcher(IN_SEGMENT))
62
+ readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
69
63
  }
70
64
  }
71
- if (!storage.splits.usesMatcher(IN_SEGMENT) && !storage.splits.usesMatcher(IN_LARGE_SEGMENT))
72
- setTimeout(smartReady, 0);
73
- else
65
+ if (storage.splits.usesMatcher(IN_SEGMENT) && storage.splits.usesMatcher(IN_LARGE_SEGMENT))
74
66
  readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);
67
+ else
68
+ setTimeout(smartReady, 0);
75
69
  mySegmentsSyncTasks[matchingKey] = { msSyncTask: msSyncTask, mlsSyncTask: mlsSyncTask };
76
70
  return {
77
71
  msSyncTask: msSyncTask,
@@ -4,6 +4,6 @@ import { mySegmentsUpdaterFactory } from '../updaters/mySegmentsUpdater';
4
4
  /**
5
5
  * Creates a sync task that periodically executes a `mySegmentsUpdater` task
6
6
  */
7
- export function mySegmentsSyncTaskFactory(fetchMySegments, mySegmentsCache, notifyUpdate, settings, matchingKey, segmentsRefreshRate) {
8
- return syncTaskFactory(settings.log, mySegmentsUpdaterFactory(settings.log, mySegmentsFetcherFactory(fetchMySegments), mySegmentsCache, notifyUpdate, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, matchingKey), segmentsRefreshRate, 'mySegmentsUpdater');
7
+ export function mySegmentsSyncTaskFactory(fetchMySegments, mySegmentsCache, notifyUpdate, settings, matchingKey, segmentsRefreshRate, NAME) {
8
+ return syncTaskFactory(settings.log, mySegmentsUpdaterFactory(settings.log, mySegmentsFetcherFactory(fetchMySegments), mySegmentsCache, notifyUpdate, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, matchingKey), segmentsRefreshRate, NAME);
9
9
  }
@@ -75,13 +75,7 @@ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, mySegmentsCache
75
75
  * (3) or `undefined`, for which the updater will fetch mySegments in order to sync the storage.
76
76
  * @param {boolean | undefined} noCache true to revalidate data to fetch
77
77
  */
78
- return function mySegmentsUpdater(segmentsData, noCache, delay) {
79
- return delay ?
80
- new Promise(function (res) {
81
- setTimeout(function () {
82
- _mySegmentsUpdater(0, segmentsData, noCache).then(res);
83
- }, delay);
84
- }) :
85
- _mySegmentsUpdater(0, segmentsData, noCache);
78
+ return function mySegmentsUpdater(segmentsData, noCache) {
79
+ return _mySegmentsUpdater(0, segmentsData, noCache);
86
80
  };
87
81
  }
@@ -9,6 +9,7 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
9
9
  var isHandlingEvent;
10
10
  var _segmentsData; // keeps the segmentsData (if included in notification payload) from the queued event with maximum changeNumber
11
11
  var _delay;
12
+ var _delayTimeoutID;
12
13
  var backoff = new Backoff(__handleMySegmentsUpdateCall);
13
14
  function __handleMySegmentsUpdateCall() {
14
15
  isHandlingEvent = true;
@@ -16,7 +17,14 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
16
17
  handleNewEvent = false;
17
18
  var currentMaxChangeNumber_1 = maxChangeNumber;
18
19
  // fetch mySegments revalidating data if cached
19
- mySegmentsSyncTask.execute(_segmentsData, true, _delay).then(function (result) {
20
+ var syncTask = _delay ?
21
+ new Promise(function (res) {
22
+ _delayTimeoutID = setTimeout(function () {
23
+ mySegmentsSyncTask.execute(_segmentsData, true).then(res);
24
+ }, _delay);
25
+ }) :
26
+ mySegmentsSyncTask.execute(_segmentsData, true);
27
+ syncTask.then(function (result) {
20
28
  if (!isHandlingEvent)
21
29
  return; // halt if `stop` has been called
22
30
  if (result !== false) { // Unlike `Splits|SegmentsUpdateWorker`, we cannot use `mySegmentsCache.getChangeNumber` since `/mySegments` endpoint doesn't provide this value.
@@ -55,6 +63,7 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
55
63
  backoff.reset();
56
64
  },
57
65
  stop: function () {
66
+ clearTimeout(_delayTimeoutID);
58
67
  isHandlingEvent = false;
59
68
  backoff.reset();
60
69
  }
@@ -18,7 +18,6 @@ import { hash64 } from '../../utils/murmur3/murmur3_64';
18
18
  import { TOKEN_REFRESH, AUTH_REJECTION, MY_LARGE_SEGMENT, MY_SEGMENT } from '../../utils/constants';
19
19
  export function getDelay(parsedData, matchingKey) {
20
20
  var interval = parsedData.i || 60000;
21
- // const hashType = parsedData.h || 0;
22
21
  var seed = parsedData.s || 0;
23
22
  return hash(matchingKey, seed) % interval;
24
23
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.16.1-rc.0",
3
+ "version": "1.16.1-rc.1",
4
4
  "description": "Split JavaScript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
package/src/dtos/types.ts CHANGED
@@ -224,14 +224,18 @@ export interface ISegmentChangesResponse {
224
224
  till: number
225
225
  }
226
226
 
227
- export interface IMySegmentsResponseItem {
228
- id: string,
229
- name: string
230
- }
231
-
232
227
  /** Interface of the parsed JSON response of `/mySegments/{userKey}` */
233
228
  export interface IMySegmentsResponse {
234
- mySegments: IMySegmentsResponseItem[]
229
+ mySegments: {
230
+ id: string,
231
+ name: string
232
+ }[]
233
+ }
234
+
235
+ /** Interface of the parsed JSON response of `/myLargeSegments/{userKey}` */
236
+ export interface IMyLargeSegmentsResponse {
237
+ myLargeSegments: string[],
238
+ changeNumber: number
235
239
  }
236
240
 
237
241
  /** Metadata internal type for storages */
@@ -18,10 +18,8 @@ function splitsEventEmitterFactory(EventEmitter: new () => IEventEmitter): ISpli
18
18
  return splitsEventEmitter;
19
19
  }
20
20
 
21
- function segmentsEventEmitterFactory(EventEmitter: new () => IEventEmitter): ISegmentsEventEmitter {
22
- const segmentsEventEmitter = objectAssign(new EventEmitter(), {
23
- segmentsArrived: false
24
- });
21
+ function segmentsEventEmitterFactory(EventEmitter: new () => IEventEmitter, segmentsArrived = false): ISegmentsEventEmitter {
22
+ const segmentsEventEmitter = objectAssign(new EventEmitter(), { segmentsArrived });
25
23
 
26
24
  segmentsEventEmitter.once(SDK_SEGMENTS_ARRIVED, () => { segmentsEventEmitter.segmentsArrived = true; });
27
25
 
@@ -39,7 +37,7 @@ export function readinessManagerFactory(
39
37
  const { startup: { readyTimeout, waitForLargeSegments }, sync: { largeSegmentsEnabled } } = settings;
40
38
 
41
39
  const segments: ISegmentsEventEmitter = segmentsEventEmitterFactory(EventEmitter);
42
- const largeSegments = largeSegmentsEnabled && waitForLargeSegments ? segmentsEventEmitterFactory(EventEmitter) : undefined;
40
+ const largeSegments = largeSegmentsEnabled ? segmentsEventEmitterFactory(EventEmitter, !waitForLargeSegments) : undefined;
43
41
  const gate: IReadinessEventEmitter = new EventEmitter();
44
42
 
45
43
  // emit SDK_READY_FROM_CACHE
@@ -7,7 +7,7 @@ import { ISet, setToArray, _Set } from '../../utils/lang/sets';
7
7
  * The `_cache` property is the object were items are stored.
8
8
  * Intended for testing purposes.
9
9
  *
10
- * @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves inmediatelly.
10
+ * @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves immediately.
11
11
  */
12
12
  export function inMemoryWrapperFactory(connDelay?: number): IPluggableStorageWrapper & { _cache: Record<string, string | string[] | ISet<string>>, _setConnDelay(connDelay: number): void } {
13
13
 
@@ -204,7 +204,7 @@ export interface ISplitsCacheBase {
204
204
  getSplitNames(): MaybeThenable<string[]>,
205
205
  // should never reject or throw an exception. Instead return true by default, asssuming the TT might exist.
206
206
  trafficTypeExists(trafficType: string): MaybeThenable<boolean>,
207
- // only for Client-Side
207
+ // only for Client-Side. Returns true if the storage is not synchronized yet (getChangeNumber() === 1) or contains a FF using the given matcher
208
208
  usesMatcher(matcherType: string): MaybeThenable<boolean>,
209
209
  clear(): MaybeThenable<boolean | void>,
210
210
  // should never reject or throw an exception. Instead return false by default, to avoid emitting SDK_READY_FROM_CACHE.
@@ -1,5 +1,5 @@
1
1
  import { IFetchMySegments, IResponse } from '../../../services/types';
2
- import { IMySegmentsResponseItem } from '../../../dtos/types';
2
+ import { IMySegmentsResponse, IMyLargeSegmentsResponse } from '../../../dtos/types';
3
3
  import { IMySegmentsFetcher } from './types';
4
4
 
5
5
  /**
@@ -21,7 +21,11 @@ export function mySegmentsFetcherFactory(fetchMySegments: IFetchMySegments): IMy
21
21
  // Extract segment names
22
22
  return mySegmentsPromise
23
23
  .then(resp => resp.json())
24
- .then(json => json.mySegments.map((segment: IMySegmentsResponseItem) => segment.name));
24
+ .then((json: IMySegmentsResponse | IMyLargeSegmentsResponse) => {
25
+ return (json as IMySegmentsResponse).mySegments ?
26
+ (json as IMySegmentsResponse).mySegments.map((segment) => segment.name) :
27
+ (json as IMyLargeSegmentsResponse).myLargeSegments;
28
+ });
25
29
  };
26
30
 
27
31
  }
@@ -35,11 +35,11 @@ export function pollingManagerCSFactory(
35
35
 
36
36
  forOwn(mySegmentsSyncTasks, ({ msSyncTask, mlsSyncTask }) => {
37
37
  if (splitsHaveSegments) msSyncTask.start();
38
- else msSyncTask.stop();
38
+ else msSyncTask.stop(); // smart pausing
39
39
 
40
40
  if (mlsSyncTask) {
41
41
  if (splitsHaveLargeSegments) mlsSyncTask.start();
42
- else mlsSyncTask.stop();
42
+ else mlsSyncTask.stop(); // smart pausing
43
43
  }
44
44
  });
45
45
  }
@@ -51,9 +51,7 @@ export function pollingManagerCSFactory(
51
51
  });
52
52
  }
53
53
 
54
- // smart pausing
55
54
  readiness.splits.on(SDK_SPLITS_ARRIVED, () => {
56
- // smart pausing of mySegments polling
57
55
  if (splitsSyncTask.isRunning()) startMySegmentsSyncTasks();
58
56
  });
59
57
 
@@ -61,12 +59,11 @@ export function pollingManagerCSFactory(
61
59
  const msSyncTask = mySegmentsSyncTaskFactory(
62
60
  splitApi.fetchMySegments,
63
61
  storage.segments,
64
- () => {
65
- if (storage.splits.usesMatcher(IN_SEGMENT)) readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
66
- },
62
+ () => { if (storage.splits.usesMatcher(IN_SEGMENT)) readiness.segments.emit(SDK_SEGMENTS_ARRIVED); },
67
63
  settings,
68
64
  matchingKey,
69
- settings.scheduler.segmentsRefreshRate
65
+ settings.scheduler.segmentsRefreshRate,
66
+ 'mySegmentsUpdater'
70
67
  );
71
68
 
72
69
  let mlsSyncTask;
@@ -74,24 +71,24 @@ export function pollingManagerCSFactory(
74
71
  mlsSyncTask = mySegmentsSyncTaskFactory(
75
72
  splitApi.fetchMyLargeSegments,
76
73
  storage.largeSegments!,
77
- () => {
78
- if (readiness.largeSegments && storage.splits.usesMatcher(IN_LARGE_SEGMENT)) readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED);
79
- },
74
+ () => { if (readiness.largeSegments && storage.splits.usesMatcher(IN_LARGE_SEGMENT)) readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED); },
80
75
  settings,
81
76
  matchingKey,
82
- settings.scheduler.largeSegmentsRefreshRate
77
+ settings.scheduler.largeSegmentsRefreshRate,
78
+ 'myLargeSegmentsUpdater'
83
79
  );
84
80
  }
85
81
 
86
82
  // smart ready
87
83
  function smartReady() {
88
84
  if (!readiness.isReady()) {
89
- if (!storage.splits.usesMatcher(IN_SEGMENT)) readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
90
85
  if (readiness.largeSegments && !storage.splits.usesMatcher(IN_LARGE_SEGMENT)) readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED);
86
+ if (!storage.splits.usesMatcher(IN_SEGMENT)) readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
91
87
  }
92
88
  }
93
- if (!storage.splits.usesMatcher(IN_SEGMENT) && !storage.splits.usesMatcher(IN_LARGE_SEGMENT)) setTimeout(smartReady, 0);
94
- else readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);
89
+
90
+ if (storage.splits.usesMatcher(IN_SEGMENT) && storage.splits.usesMatcher(IN_LARGE_SEGMENT)) readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);
91
+ else setTimeout(smartReady, 0);
95
92
 
96
93
  mySegmentsSyncTasks[matchingKey] = { msSyncTask: msSyncTask, mlsSyncTask: mlsSyncTask };
97
94
 
@@ -15,7 +15,8 @@ export function mySegmentsSyncTaskFactory(
15
15
  notifyUpdate: () => void,
16
16
  settings: ISettings,
17
17
  matchingKey: string,
18
- segmentsRefreshRate: number
18
+ segmentsRefreshRate: number,
19
+ NAME: string
19
20
  ): IMySegmentsSyncTask {
20
21
  return syncTaskFactory(
21
22
  settings.log,
@@ -29,6 +30,6 @@ export function mySegmentsSyncTaskFactory(
29
30
  matchingKey
30
31
  ),
31
32
  segmentsRefreshRate,
32
- 'mySegmentsUpdater',
33
+ NAME,
33
34
  );
34
35
  }
@@ -14,7 +14,7 @@ export type MySegmentsData = string[] | {
14
14
  add: boolean
15
15
  }
16
16
 
17
- export interface IMySegmentsSyncTask extends ISyncTask<[segmentsData?: MySegmentsData, noCache?: boolean, delay?: number], boolean> { }
17
+ export interface IMySegmentsSyncTask extends ISyncTask<[segmentsData?: MySegmentsData, noCache?: boolean], boolean> { }
18
18
 
19
19
  export interface IPollingManager extends ITask {
20
20
  syncAll(): Promise<any>
@@ -94,14 +94,8 @@ export function mySegmentsUpdaterFactory(
94
94
  * (3) or `undefined`, for which the updater will fetch mySegments in order to sync the storage.
95
95
  * @param {boolean | undefined} noCache true to revalidate data to fetch
96
96
  */
97
- return function mySegmentsUpdater(segmentsData?: MySegmentsData, noCache?: boolean, delay?: number) {
98
- return delay ?
99
- new Promise(res => {
100
- setTimeout(() => {
101
- _mySegmentsUpdater(0, segmentsData, noCache).then(res);
102
- }, delay);
103
- }) :
104
- _mySegmentsUpdater(0, segmentsData, noCache);
97
+ return function mySegmentsUpdater(segmentsData?: MySegmentsData, noCache?: boolean) {
98
+ return _mySegmentsUpdater(0, segmentsData, noCache);
105
99
  };
106
100
 
107
101
  }
@@ -15,6 +15,7 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask,
15
15
  let isHandlingEvent: boolean;
16
16
  let _segmentsData: MySegmentsData | undefined; // keeps the segmentsData (if included in notification payload) from the queued event with maximum changeNumber
17
17
  let _delay: undefined | number;
18
+ let _delayTimeoutID: undefined | number;
18
19
  const backoff = new Backoff(__handleMySegmentsUpdateCall);
19
20
 
20
21
  function __handleMySegmentsUpdateCall() {
@@ -24,7 +25,15 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask,
24
25
  const currentMaxChangeNumber = maxChangeNumber;
25
26
 
26
27
  // fetch mySegments revalidating data if cached
27
- mySegmentsSyncTask.execute(_segmentsData, true, _delay).then((result) => {
28
+ const syncTask = _delay ?
29
+ new Promise(res => {
30
+ _delayTimeoutID = setTimeout(() => {
31
+ mySegmentsSyncTask.execute(_segmentsData, true).then(res);
32
+ }, _delay);
33
+ }) :
34
+ mySegmentsSyncTask.execute(_segmentsData, true);
35
+
36
+ syncTask.then((result) => {
28
37
  if (!isHandlingEvent) return; // halt if `stop` has been called
29
38
  if (result !== false) {// Unlike `Splits|SegmentsUpdateWorker`, we cannot use `mySegmentsCache.getChangeNumber` since `/mySegments` endpoint doesn't provide this value.
30
39
  if (_segmentsData) telemetryTracker.trackUpdatesFromSSE(updateType);
@@ -61,6 +70,7 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask,
61
70
  },
62
71
 
63
72
  stop() {
73
+ clearTimeout(_delayTimeoutID);
64
74
  isHandlingEvent = false;
65
75
  backoff.reset();
66
76
  }
@@ -23,9 +23,8 @@ import { TOKEN_REFRESH, AUTH_REJECTION, MY_LARGE_SEGMENT, MY_SEGMENT } from '../
23
23
  import { ISdkFactoryContextSync } from '../../sdkFactory/types';
24
24
  import { IUpdateWorker } from './UpdateWorkers/types';
25
25
 
26
- export function getDelay(parsedData: IMyLargeSegmentsUpdateData, matchingKey: string) {
26
+ export function getDelay(parsedData: Pick<IMyLargeSegmentsUpdateData, 'i' | 'h' | 's'>, matchingKey: string) {
27
27
  const interval = parsedData.i || 60000;
28
- // const hashType = parsedData.h || 0;
29
28
  const seed = parsedData.s || 0;
30
29
 
31
30
  return hash(matchingKey, seed) % interval;
@@ -177,13 +177,17 @@ export interface ISegmentChangesResponse {
177
177
  since: number;
178
178
  till: number;
179
179
  }
180
- export interface IMySegmentsResponseItem {
181
- id: string;
182
- name: string;
183
- }
184
180
  /** Interface of the parsed JSON response of `/mySegments/{userKey}` */
185
181
  export interface IMySegmentsResponse {
186
- mySegments: IMySegmentsResponseItem[];
182
+ mySegments: {
183
+ id: string;
184
+ name: string;
185
+ }[];
186
+ }
187
+ /** Interface of the parsed JSON response of `/myLargeSegments/{userKey}` */
188
+ export interface IMyLargeSegmentsResponse {
189
+ myLargeSegments: string[];
190
+ changeNumber: number;
187
191
  }
188
192
  /** Metadata internal type for storages */
189
193
  export interface IMetadata {
@@ -5,7 +5,7 @@ import { ISet } from '../../utils/lang/sets';
5
5
  * The `_cache` property is the object were items are stored.
6
6
  * Intended for testing purposes.
7
7
  *
8
- * @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves inmediatelly.
8
+ * @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves immediately.
9
9
  */
10
10
  export declare function inMemoryWrapperFactory(connDelay?: number): IPluggableStorageWrapper & {
11
11
  _cache: Record<string, string | string[] | ISet<string>>;
@@ -5,4 +5,4 @@ import { ISettings } from '../../../types';
5
5
  /**
6
6
  * Creates a sync task that periodically executes a `mySegmentsUpdater` task
7
7
  */
8
- export declare function mySegmentsSyncTaskFactory(fetchMySegments: IFetchMySegments, mySegmentsCache: ISegmentsCacheSync, notifyUpdate: () => void, settings: ISettings, matchingKey: string, segmentsRefreshRate: number): IMySegmentsSyncTask;
8
+ export declare function mySegmentsSyncTaskFactory(fetchMySegments: IFetchMySegments, mySegmentsCache: ISegmentsCacheSync, notifyUpdate: () => void, settings: ISettings, matchingKey: string, segmentsRefreshRate: number, NAME: string): IMySegmentsSyncTask;
@@ -13,7 +13,7 @@ export declare type MySegmentsData = string[] | {
13
13
  name: string;
14
14
  add: boolean;
15
15
  };
16
- export interface IMySegmentsSyncTask extends ISyncTask<[segmentsData?: MySegmentsData, noCache?: boolean, delay?: number], boolean> {
16
+ export interface IMySegmentsSyncTask extends ISyncTask<[segmentsData?: MySegmentsData, noCache?: boolean], boolean> {
17
17
  }
18
18
  export interface IPollingManager extends ITask {
19
19
  syncAll(): Promise<any>;
@@ -2,7 +2,7 @@ import { IPushManager } from './types';
2
2
  import { IPollingManager } from '../polling/types';
3
3
  import { IMyLargeSegmentsUpdateData } from './SSEHandler/types';
4
4
  import { ISdkFactoryContextSync } from '../../sdkFactory/types';
5
- export declare function getDelay(parsedData: IMyLargeSegmentsUpdateData, matchingKey: string): number;
5
+ export declare function getDelay(parsedData: Pick<IMyLargeSegmentsUpdateData, 'i' | 'h' | 's'>, matchingKey: string): number;
6
6
  /**
7
7
  * PushManager factory:
8
8
  * - for server-side if key is not provided in settings.