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

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 (141) hide show
  1. package/CHANGES.txt +3 -0
  2. package/cjs/evaluator/matchers/index.js +3 -1
  3. package/cjs/evaluator/matchers/large_segment.js +16 -0
  4. package/cjs/evaluator/matchers/matcherTypes.js +1 -0
  5. package/cjs/evaluator/matchersTransform/index.js +1 -1
  6. package/cjs/logger/constants.js +4 -4
  7. package/cjs/logger/messages/info.js +0 -1
  8. package/cjs/readiness/readinessManager.js +11 -6
  9. package/cjs/readiness/sdkReadinessManager.js +5 -6
  10. package/cjs/sdkClient/sdkClientMethodCS.js +3 -4
  11. package/cjs/sdkClient/sdkClientMethodCSWithTT.js +4 -5
  12. package/cjs/sdkFactory/index.js +1 -1
  13. package/cjs/services/splitApi.js +4 -0
  14. package/cjs/storages/AbstractSplitsCacheAsync.js +2 -2
  15. package/cjs/storages/AbstractSplitsCacheSync.js +5 -5
  16. package/cjs/storages/KeyBuilder.js +3 -0
  17. package/cjs/storages/KeyBuilderCS.js +17 -5
  18. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +16 -4
  19. package/cjs/storages/inLocalStorage/index.js +6 -2
  20. package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -0
  21. package/cjs/storages/inMemory/SplitsCacheInMemory.js +20 -11
  22. package/cjs/storages/inMemory/TelemetryCacheInMemory.js +7 -10
  23. package/cjs/sync/polling/pollingManagerCS.js +54 -30
  24. package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
  25. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +13 -8
  26. package/cjs/sync/polling/updaters/splitChangesUpdater.js +2 -1
  27. package/cjs/sync/streaming/SSEHandler/index.js +1 -0
  28. package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +6 -5
  29. package/cjs/sync/streaming/constants.js +2 -1
  30. package/cjs/sync/streaming/pushManager.js +96 -64
  31. package/cjs/sync/submitters/telemetrySubmitter.js +2 -0
  32. package/cjs/sync/syncManagerOnline.js +24 -14
  33. package/cjs/utils/constants/index.js +5 -1
  34. package/cjs/utils/settingsValidation/index.js +9 -4
  35. package/esm/evaluator/matchers/index.js +3 -1
  36. package/esm/evaluator/matchers/large_segment.js +12 -0
  37. package/esm/evaluator/matchers/matcherTypes.js +1 -0
  38. package/esm/evaluator/matchersTransform/index.js +1 -1
  39. package/esm/logger/constants.js +1 -1
  40. package/esm/logger/messages/info.js +0 -1
  41. package/esm/readiness/readinessManager.js +11 -6
  42. package/esm/readiness/sdkReadinessManager.js +5 -6
  43. package/esm/sdkClient/sdkClientMethodCS.js +4 -5
  44. package/esm/sdkClient/sdkClientMethodCSWithTT.js +5 -6
  45. package/esm/sdkFactory/index.js +1 -1
  46. package/esm/services/splitApi.js +5 -1
  47. package/esm/storages/AbstractSplitsCacheAsync.js +2 -2
  48. package/esm/storages/AbstractSplitsCacheSync.js +3 -3
  49. package/esm/storages/KeyBuilder.js +3 -0
  50. package/esm/storages/KeyBuilderCS.js +15 -4
  51. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +17 -5
  52. package/esm/storages/inLocalStorage/index.js +7 -3
  53. package/esm/storages/inMemory/InMemoryStorageCS.js +5 -0
  54. package/esm/storages/inMemory/SplitsCacheInMemory.js +21 -12
  55. package/esm/storages/inMemory/TelemetryCacheInMemory.js +7 -10
  56. package/esm/sync/polling/pollingManagerCS.js +55 -31
  57. package/esm/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
  58. package/esm/sync/polling/updaters/mySegmentsUpdater.js +11 -6
  59. package/esm/sync/polling/updaters/splitChangesUpdater.js +2 -1
  60. package/esm/sync/streaming/SSEHandler/index.js +2 -1
  61. package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +6 -5
  62. package/esm/sync/streaming/constants.js +1 -0
  63. package/esm/sync/streaming/pushManager.js +96 -65
  64. package/esm/sync/submitters/telemetrySubmitter.js +2 -0
  65. package/esm/sync/syncManagerOnline.js +25 -15
  66. package/esm/utils/constants/index.js +4 -0
  67. package/esm/utils/settingsValidation/index.js +10 -5
  68. package/package.json +1 -1
  69. package/src/dtos/types.ts +7 -1
  70. package/src/evaluator/matchers/index.ts +2 -0
  71. package/src/evaluator/matchers/large_segment.ts +18 -0
  72. package/src/evaluator/matchers/matcherTypes.ts +1 -0
  73. package/src/evaluator/matchersTransform/index.ts +1 -1
  74. package/src/logger/constants.ts +1 -1
  75. package/src/logger/messages/info.ts +0 -1
  76. package/src/readiness/readinessManager.ts +11 -5
  77. package/src/readiness/sdkReadinessManager.ts +7 -7
  78. package/src/readiness/types.ts +3 -2
  79. package/src/sdkClient/sdkClientMethodCS.ts +4 -6
  80. package/src/sdkClient/sdkClientMethodCSWithTT.ts +5 -7
  81. package/src/sdkFactory/index.ts +1 -1
  82. package/src/services/splitApi.ts +6 -1
  83. package/src/services/types.ts +1 -0
  84. package/src/storages/AbstractSplitsCacheAsync.ts +2 -2
  85. package/src/storages/AbstractSplitsCacheSync.ts +4 -4
  86. package/src/storages/KeyBuilder.ts +3 -0
  87. package/src/storages/KeyBuilderCS.ts +25 -5
  88. package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +3 -3
  89. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +20 -5
  90. package/src/storages/inLocalStorage/index.ts +8 -4
  91. package/src/storages/inMemory/InMemoryStorageCS.ts +5 -0
  92. package/src/storages/inMemory/SplitsCacheInMemory.ts +15 -10
  93. package/src/storages/inMemory/TelemetryCacheInMemory.ts +7 -11
  94. package/src/storages/types.ts +6 -4
  95. package/src/sync/polling/pollingManagerCS.ts +62 -27
  96. package/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +8 -9
  97. package/src/sync/polling/types.ts +4 -3
  98. package/src/sync/polling/updaters/mySegmentsUpdater.ts +13 -10
  99. package/src/sync/polling/updaters/splitChangesUpdater.ts +4 -3
  100. package/src/sync/streaming/SSEHandler/index.ts +2 -1
  101. package/src/sync/streaming/SSEHandler/types.ts +14 -2
  102. package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +7 -5
  103. package/src/sync/streaming/constants.ts +1 -0
  104. package/src/sync/streaming/pushManager.ts +101 -63
  105. package/src/sync/streaming/types.ts +5 -3
  106. package/src/sync/submitters/telemetrySubmitter.ts +2 -0
  107. package/src/sync/submitters/types.ts +10 -4
  108. package/src/sync/syncManagerOnline.ts +19 -11
  109. package/src/types.ts +26 -1
  110. package/src/utils/constants/index.ts +5 -0
  111. package/src/utils/settingsValidation/index.ts +11 -6
  112. package/src/utils/settingsValidation/types.ts +1 -1
  113. package/types/dtos/types.d.ts +5 -1
  114. package/types/evaluator/matchers/large_segment.d.ts +5 -0
  115. package/types/logger/constants.d.ts +1 -1
  116. package/types/readiness/readinessManager.d.ts +2 -2
  117. package/types/readiness/sdkReadinessManager.d.ts +2 -3
  118. package/types/readiness/types.d.ts +3 -2
  119. package/types/services/types.d.ts +1 -0
  120. package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
  121. package/types/storages/AbstractSplitsCacheSync.d.ts +3 -3
  122. package/types/storages/KeyBuilder.d.ts +1 -0
  123. package/types/storages/KeyBuilderCS.d.ts +7 -2
  124. package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +2 -2
  125. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +1 -1
  126. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +3 -2
  127. package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +4 -6
  128. package/types/storages/types.d.ts +4 -3
  129. package/types/sync/polling/syncTasks/mySegmentsSyncTask.d.ts +2 -3
  130. package/types/sync/polling/types.d.ts +10 -3
  131. package/types/sync/polling/updaters/mySegmentsUpdater.d.ts +4 -4
  132. package/types/sync/streaming/SSEHandler/types.d.ts +13 -2
  133. package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +2 -1
  134. package/types/sync/streaming/constants.d.ts +1 -0
  135. package/types/sync/streaming/pushManager.d.ts +2 -0
  136. package/types/sync/streaming/types.d.ts +5 -4
  137. package/types/sync/submitters/types.d.ts +9 -3
  138. package/types/types.d.ts +25 -0
  139. package/types/utils/constants/index.d.ts +3 -0
  140. package/types/utils/settingsValidation/index.d.ts +2 -0
  141. package/types/utils/settingsValidation/types.d.ts +1 -1
@@ -1,7 +1,8 @@
1
1
  import { __extends } from "tslib";
2
- import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
2
+ import { AbstractSplitsCacheSync, usesMatcher } from '../AbstractSplitsCacheSync';
3
3
  import { isFiniteNumber } from '../../utils/lang';
4
4
  import { _Set } from '../../utils/lang/sets';
5
+ import { IN_LARGE_SEGMENT, IN_SEGMENT } from '../../utils/constants';
5
6
  /**
6
7
  * Default ISplitsCacheSync implementation that stores split definitions in memory.
7
8
  * Supported by all JS runtimes.
@@ -13,7 +14,8 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
13
14
  _this.splitsCache = {};
14
15
  _this.ttCache = {};
15
16
  _this.changeNumber = -1;
16
- _this.splitsWithSegmentsCount = 0;
17
+ _this.segmentsCount = 0;
18
+ _this.largeSegmentsCount = 0;
17
19
  _this.flagSetsCache = {};
18
20
  _this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
19
21
  return _this;
@@ -22,7 +24,8 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
22
24
  this.splitsCache = {};
23
25
  this.ttCache = {};
24
26
  this.changeNumber = -1;
25
- this.splitsWithSegmentsCount = 0;
27
+ this.segmentsCount = 0;
28
+ this.largeSegmentsCount = 0;
26
29
  };
27
30
  SplitsCacheInMemory.prototype.addSplit = function (name, split) {
28
31
  var previousSplit = this.getSplit(name);
@@ -32,9 +35,11 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
32
35
  if (!this.ttCache[previousTtName])
33
36
  delete this.ttCache[previousTtName];
34
37
  this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
35
- if (usesSegments(previousSplit)) { // Substract from segments count for the previous version of this Split.
36
- this.splitsWithSegmentsCount--;
37
- }
38
+ // Substract from segments count for the previous version of this Split.
39
+ if (usesMatcher(previousSplit, IN_SEGMENT))
40
+ this.segmentsCount--;
41
+ if (usesMatcher(previousSplit, IN_LARGE_SEGMENT))
42
+ this.largeSegmentsCount--;
38
43
  }
39
44
  if (split) {
40
45
  // Store the Split.
@@ -44,8 +49,10 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
44
49
  this.ttCache[ttName] = (this.ttCache[ttName] || 0) + 1;
45
50
  this.addToFlagSets(split);
46
51
  // Add to segments count for the new version of the Split
47
- if (usesSegments(split))
48
- this.splitsWithSegmentsCount++;
52
+ if (usesMatcher(split, IN_SEGMENT))
53
+ this.segmentsCount++;
54
+ if (usesMatcher(split, IN_LARGE_SEGMENT))
55
+ this.largeSegmentsCount++;
49
56
  return true;
50
57
  }
51
58
  else {
@@ -63,8 +70,10 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
63
70
  delete this.ttCache[ttName];
64
71
  this.removeFromFlagSets(split.name, split.sets);
65
72
  // Update the segments count.
66
- if (usesSegments(split))
67
- this.splitsWithSegmentsCount--;
73
+ if (usesMatcher(split, IN_SEGMENT))
74
+ this.segmentsCount--;
75
+ if (usesMatcher(split, IN_LARGE_SEGMENT))
76
+ this.largeSegmentsCount--;
68
77
  return true;
69
78
  }
70
79
  else {
@@ -87,8 +96,8 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
87
96
  SplitsCacheInMemory.prototype.trafficTypeExists = function (trafficType) {
88
97
  return isFiniteNumber(this.ttCache[trafficType]) && this.ttCache[trafficType] > 0;
89
98
  };
90
- SplitsCacheInMemory.prototype.usesSegments = function () {
91
- return this.getChangeNumber() === -1 || this.splitsWithSegmentsCount > 0;
99
+ SplitsCacheInMemory.prototype.usesMatcher = function (matcherType) {
100
+ return this.getChangeNumber() === -1 || (matcherType === IN_SEGMENT ? this.segmentsCount > 0 : this.largeSegmentsCount > 0);
92
101
  };
93
102
  SplitsCacheInMemory.prototype.getNamesByFlagSets = function (flagSets) {
94
103
  var _this = this;
@@ -18,9 +18,10 @@ export function shouldRecordTelemetry(_a) {
18
18
  return settings.mode !== LOCALHOST_MODE && (settings.core.key === undefined || Math.random() <= ACCEPTANCE_RANGE);
19
19
  }
20
20
  var TelemetryCacheInMemory = /** @class */ (function () {
21
- function TelemetryCacheInMemory(splits, segments) {
21
+ function TelemetryCacheInMemory(splits, segments, largeSegments) {
22
22
  this.splits = splits;
23
23
  this.segments = segments;
24
+ this.largeSegments = largeSegments;
24
25
  // isEmpty flag
25
26
  this.e = true;
26
27
  this.notReadyUsage = 0;
@@ -36,10 +37,7 @@ var TelemetryCacheInMemory = /** @class */ (function () {
36
37
  this.tags = [];
37
38
  this.exceptions = {};
38
39
  this.latencies = {};
39
- this.updatesFromSSE = {
40
- sp: 0,
41
- ms: 0
42
- };
40
+ this.updatesFromSSE = {};
43
41
  }
44
42
  TelemetryCacheInMemory.prototype.isEmpty = function () { return this.e; };
45
43
  TelemetryCacheInMemory.prototype.clear = function () { };
@@ -59,6 +57,8 @@ var TelemetryCacheInMemory = /** @class */ (function () {
59
57
  spC: this.splits && this.splits.getSplitNames().length,
60
58
  seC: this.segments && this.segments.getRegisteredSegments().length,
61
59
  skC: this.segments && this.segments.getKeysCount(),
60
+ lseC: this.largeSegments && this.largeSegments.getRegisteredSegments().length,
61
+ lskC: this.largeSegments && this.largeSegments.getKeysCount(),
62
62
  sL: this.getSessionLength(),
63
63
  eQ: this.getEventStats(QUEUED),
64
64
  eD: this.getEventStats(DROPPED),
@@ -190,14 +190,11 @@ var TelemetryCacheInMemory = /** @class */ (function () {
190
190
  };
191
191
  TelemetryCacheInMemory.prototype.popUpdatesFromSSE = function () {
192
192
  var result = this.updatesFromSSE;
193
- this.updatesFromSSE = {
194
- sp: 0,
195
- ms: 0,
196
- };
193
+ this.updatesFromSSE = {};
197
194
  return result;
198
195
  };
199
196
  TelemetryCacheInMemory.prototype.recordUpdatesFromSSE = function (type) {
200
- this.updatesFromSSE[type]++;
197
+ this.updatesFromSSE[type] = (this.updatesFromSSE[type] || 0) + 1;
201
198
  this.e = false;
202
199
  };
203
200
  return TelemetryCacheInMemory;
@@ -3,7 +3,8 @@ import { mySegmentsSyncTaskFactory } from './syncTasks/mySegmentsSyncTask';
3
3
  import { splitsSyncTaskFactory } from './syncTasks/splitsSyncTask';
4
4
  import { getMatching } from '../../utils/key';
5
5
  import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../readiness/constants';
6
- import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger/constants';
6
+ import { POLLING_START, POLLING_STOP } from '../../logger/constants';
7
+ import { IN_LARGE_SEGMENT, IN_SEGMENT } from '../../utils/constants';
7
8
  /**
8
9
  * Expose start / stop mechanism for polling data from services.
9
10
  * For client-side API with multiple clients.
@@ -12,59 +13,80 @@ export function pollingManagerCSFactory(params) {
12
13
  var splitApi = params.splitApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
13
14
  var log = settings.log;
14
15
  var splitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings, true);
15
- // Map of matching keys to their corresponding MySegmentsSyncTask.
16
+ // Map of matching keys to their corresponding MySegmentsSyncTask for segments and large segments.
16
17
  var mySegmentsSyncTasks = {};
17
18
  var matchingKey = getMatching(settings.core.key);
18
- var mySegmentsSyncTask = add(matchingKey, readiness, storage);
19
+ var _a = add(matchingKey, readiness, storage), msSyncTask = _a.msSyncTask, mlsSyncTask = _a.mlsSyncTask;
19
20
  function startMySegmentsSyncTasks() {
20
- forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
21
- mySegmentsSyncTask.start();
21
+ var splitsHaveSegments = storage.splits.usesMatcher(IN_SEGMENT);
22
+ var splitsHaveLargeSegments = storage.splits.usesMatcher(IN_LARGE_SEGMENT);
23
+ forOwn(mySegmentsSyncTasks, function (_a) {
24
+ var msSyncTask = _a.msSyncTask, mlsSyncTask = _a.mlsSyncTask;
25
+ if (splitsHaveSegments)
26
+ msSyncTask.start();
27
+ else
28
+ msSyncTask.stop();
29
+ if (mlsSyncTask) {
30
+ if (splitsHaveLargeSegments)
31
+ mlsSyncTask.start();
32
+ else
33
+ mlsSyncTask.stop();
34
+ }
22
35
  });
23
36
  }
24
37
  function stopMySegmentsSyncTasks() {
25
- forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
26
- if (mySegmentsSyncTask.isRunning())
27
- mySegmentsSyncTask.stop();
38
+ forOwn(mySegmentsSyncTasks, function (_a) {
39
+ var msSyncTask = _a.msSyncTask, mlsSyncTask = _a.mlsSyncTask;
40
+ msSyncTask.stop();
41
+ mlsSyncTask && mlsSyncTask.stop();
28
42
  });
29
43
  }
30
44
  // smart pausing
31
45
  readiness.splits.on(SDK_SPLITS_ARRIVED, function () {
32
- if (!splitsSyncTask.isRunning())
33
- return; // noop if not doing polling
34
- var splitsHaveSegments = storage.splits.usesSegments();
35
- if (splitsHaveSegments !== mySegmentsSyncTask.isRunning()) {
36
- log.info(POLLING_SMART_PAUSING, [splitsHaveSegments ? 'ON' : 'OFF']);
37
- if (splitsHaveSegments) {
38
- startMySegmentsSyncTasks();
39
- }
40
- else {
41
- stopMySegmentsSyncTasks();
42
- }
43
- }
46
+ // smart pausing of mySegments polling
47
+ if (splitsSyncTask.isRunning())
48
+ startMySegmentsSyncTasks();
44
49
  });
45
50
  function add(matchingKey, readiness, storage) {
46
- var mySegmentsSyncTask = mySegmentsSyncTaskFactory(splitApi.fetchMySegments, storage, readiness, settings, matchingKey);
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);
55
+ var mlsSyncTask;
56
+ 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);
61
+ }
47
62
  // smart ready
48
63
  function smartReady() {
49
- if (!readiness.isReady() && !storage.splits.usesSegments())
50
- readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
64
+ if (!readiness.isReady()) {
65
+ if (!storage.splits.usesMatcher(IN_SEGMENT))
66
+ readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
67
+ if (readiness.largeSegments && !storage.splits.usesMatcher(IN_LARGE_SEGMENT))
68
+ readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED);
69
+ }
51
70
  }
52
- if (!storage.splits.usesSegments())
71
+ if (!storage.splits.usesMatcher(IN_SEGMENT) && !storage.splits.usesMatcher(IN_LARGE_SEGMENT))
53
72
  setTimeout(smartReady, 0);
54
73
  else
55
74
  readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);
56
- mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
57
- return mySegmentsSyncTask;
75
+ mySegmentsSyncTasks[matchingKey] = { msSyncTask: msSyncTask, mlsSyncTask: mlsSyncTask };
76
+ return {
77
+ msSyncTask: msSyncTask,
78
+ mlsSyncTask: mlsSyncTask
79
+ };
58
80
  }
59
81
  return {
60
82
  splitsSyncTask: splitsSyncTask,
61
- segmentsSyncTask: mySegmentsSyncTask,
83
+ segmentsSyncTask: msSyncTask,
84
+ largeSegmentsSyncTask: mlsSyncTask,
62
85
  // Start periodic fetching (polling)
63
86
  start: function () {
64
87
  log.info(POLLING_START);
65
88
  splitsSyncTask.start();
66
- if (storage.splits.usesSegments())
67
- startMySegmentsSyncTasks();
89
+ startMySegmentsSyncTasks();
68
90
  },
69
91
  // Stop periodic fetching (polling)
70
92
  stop: function () {
@@ -78,8 +100,10 @@ export function pollingManagerCSFactory(params) {
78
100
  // fetch splits and segments
79
101
  syncAll: function () {
80
102
  var promises = [splitsSyncTask.execute()];
81
- forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
82
- promises.push(mySegmentsSyncTask.execute());
103
+ forOwn(mySegmentsSyncTasks, function (_a) {
104
+ var msSyncTask = _a.msSyncTask, mlsSyncTask = _a.mlsSyncTask;
105
+ promises.push(msSyncTask.execute());
106
+ mlsSyncTask && promises.push(mlsSyncTask.execute());
83
107
  });
84
108
  return Promise.all(promises);
85
109
  },
@@ -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, storage, readiness, settings, matchingKey) {
8
- return syncTaskFactory(settings.log, mySegmentsUpdaterFactory(settings.log, mySegmentsFetcherFactory(fetchMySegments), storage.splits, storage.segments, readiness.segments, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, matchingKey), settings.scheduler.segmentsRefreshRate, 'mySegmentsUpdater');
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');
9
9
  }
@@ -1,5 +1,4 @@
1
1
  import { timeout } from '../../../utils/promise/timeout';
2
- import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
3
2
  import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
4
3
  /**
5
4
  * factory of MySegments updater, a task that:
@@ -7,7 +6,7 @@ import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
7
6
  * - updates `mySegmentsCache`
8
7
  * - uses `segmentsEventEmitter` to emit events related to segments data updates
9
8
  */
10
- export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, splitsCache, mySegmentsCache, segmentsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, matchingKey) {
9
+ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, mySegmentsCache, notifyUpdate, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, matchingKey) {
11
10
  var readyOnAlreadyExistentState = true;
12
11
  var startingUp = true;
13
12
  /** timeout and telemetry decorator for `splitChangesFetcher` promise */
@@ -38,9 +37,9 @@ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, splitsCache, my
38
37
  }
39
38
  }
40
39
  // Notify update if required
41
- if (splitsCache.usesSegments() && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
40
+ if (shouldNotifyUpdate || readyOnAlreadyExistentState) {
42
41
  readyOnAlreadyExistentState = false;
43
- segmentsEventEmitter.emit(SDK_SEGMENTS_ARRIVED);
42
+ notifyUpdate();
44
43
  }
45
44
  }
46
45
  function _mySegmentsUpdater(retry, segmentsData, noCache) {
@@ -76,7 +75,13 @@ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, splitsCache, my
76
75
  * (3) or `undefined`, for which the updater will fetch mySegments in order to sync the storage.
77
76
  * @param {boolean | undefined} noCache true to revalidate data to fetch
78
77
  */
79
- return function mySegmentsUpdater(segmentsData, noCache) {
80
- return _mySegmentsUpdater(0, segmentsData, noCache);
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);
81
86
  };
82
87
  }
@@ -3,6 +3,7 @@ import { timeout } from '../../../utils/promise/timeout';
3
3
  import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants';
4
4
  import { SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants';
5
5
  import { startsWith } from '../../../utils/lang';
6
+ import { IN_SEGMENT } from '../../../utils/constants';
6
7
  // Checks that all registered segments have been fetched (changeNumber !== -1 for every segment).
7
8
  // Returns a promise that could be rejected.
8
9
  // @TODO review together with Segments and MySegments storage APIs
@@ -23,7 +24,7 @@ export function parseSegments(_a) {
23
24
  for (var i = 0; i < conditions.length; i++) {
24
25
  var matchers = conditions[i].matcherGroup.matchers;
25
26
  matchers.forEach(function (matcher) {
26
- if (matcher.matcherType === 'IN_SEGMENT')
27
+ if (matcher.matcherType === IN_SEGMENT)
27
28
  segments.add(matcher.userDefinedSegmentMatcherData.segmentName);
28
29
  });
29
30
  }
@@ -1,6 +1,6 @@
1
1
  import { errorParser, messageParser } from './NotificationParser';
2
2
  import { notificationKeeperFactory } from './NotificationKeeper';
3
- import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE } from '../constants';
3
+ import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, MY_LARGE_SEGMENTS_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
  /**
@@ -73,6 +73,7 @@ export function SSEHandlerFactory(log, pushEmitter, telemetryTracker) {
73
73
  case SPLIT_UPDATE:
74
74
  case SEGMENT_UPDATE:
75
75
  case MY_SEGMENTS_UPDATE_V2:
76
+ case MY_LARGE_SEGMENTS_UPDATE:
76
77
  case SPLIT_KILL:
77
78
  pushEmitter.emit(parsedData.type, parsedData);
78
79
  break;
@@ -1,14 +1,14 @@
1
1
  import { Backoff } from '../../../utils/Backoff';
2
- import { MY_SEGMENT } from '../../../utils/constants';
3
2
  /**
4
3
  * MySegmentsUpdateWorker factory
5
4
  */
6
- export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker) {
5
+ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, updateType) {
7
6
  var maxChangeNumber = 0; // keeps the maximum changeNumber among queued events
8
7
  var currentChangeNumber = -1;
9
8
  var handleNewEvent = false;
10
9
  var isHandlingEvent;
11
10
  var _segmentsData; // keeps the segmentsData (if included in notification payload) from the queued event with maximum changeNumber
11
+ var _delay;
12
12
  var backoff = new Backoff(__handleMySegmentsUpdateCall);
13
13
  function __handleMySegmentsUpdateCall() {
14
14
  isHandlingEvent = true;
@@ -16,12 +16,12 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker) {
16
16
  handleNewEvent = false;
17
17
  var currentMaxChangeNumber_1 = maxChangeNumber;
18
18
  // fetch mySegments revalidating data if cached
19
- mySegmentsSyncTask.execute(_segmentsData, true).then(function (result) {
19
+ mySegmentsSyncTask.execute(_segmentsData, true, _delay).then(function (result) {
20
20
  if (!isHandlingEvent)
21
21
  return; // halt if `stop` has been called
22
22
  if (result !== false) { // Unlike `Splits|SegmentsUpdateWorker`, we cannot use `mySegmentsCache.getChangeNumber` since `/mySegments` endpoint doesn't provide this value.
23
23
  if (_segmentsData)
24
- telemetryTracker.trackUpdatesFromSSE(MY_SEGMENT);
24
+ telemetryTracker.trackUpdatesFromSSE(updateType);
25
25
  currentChangeNumber = Math.max(currentChangeNumber, currentMaxChangeNumber_1); // use `currentMaxChangeNumber`, in case that `maxChangeNumber` was updated during fetch.
26
26
  }
27
27
  if (handleNewEvent) {
@@ -43,12 +43,13 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker) {
43
43
  * @param {number} changeNumber change number of the MY_SEGMENTS_UPDATE notification
44
44
  * @param {SegmentsData | undefined} segmentsData might be undefined
45
45
  */
46
- put: function (changeNumber, segmentsData) {
46
+ put: function (changeNumber, segmentsData, delay) {
47
47
  if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber)
48
48
  return;
49
49
  maxChangeNumber = changeNumber;
50
50
  handleNewEvent = true;
51
51
  _segmentsData = segmentsData;
52
+ _delay = delay;
52
53
  if (backoff.timeoutID || !isHandlingEvent)
53
54
  __handleMySegmentsUpdateCall();
54
55
  backoff.reset();
@@ -27,6 +27,7 @@ export var MY_SEGMENTS_UPDATE_V2 = 'MY_SEGMENTS_UPDATE_V2';
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 MY_LARGE_SEGMENTS_UPDATE = 'MY_LARGE_SEGMENTS_UPDATE';
30
31
  // Control-type push notifications, handled by NotificationKeeper
31
32
  export var CONTROL = 'CONTROL';
32
33
  export var OCCUPANCY = 'OCCUPANCY';
@@ -8,13 +8,20 @@ import { authenticateFactory, hashUserKey } from './AuthClient';
8
8
  import { forOwn } from '../../utils/lang';
9
9
  import { SSEClient } from './SSEClient';
10
10
  import { getMatching } from '../../utils/key';
11
- import { MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
11
+ import { MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType, MY_LARGE_SEGMENTS_UPDATE } from './constants';
12
12
  import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, STREAMING_PARSING_SPLIT_UPDATE } from '../../logger/constants';
13
13
  import { UpdateStrategy } from './SSEHandler/types';
14
14
  import { isInBitmap, parseBitmap, parseFFUpdatePayload, parseKeyList } from './parseUtils';
15
15
  import { _Set } from '../../utils/lang/sets';
16
+ import { hash } from '../../utils/murmur3/murmur3';
16
17
  import { hash64 } from '../../utils/murmur3/murmur3_64';
17
- import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
18
+ import { TOKEN_REFRESH, AUTH_REJECTION, MY_LARGE_SEGMENT, MY_SEGMENT } from '../../utils/constants';
19
+ export function getDelay(parsedData, matchingKey) {
20
+ var interval = parsedData.i || 60000;
21
+ // const hashType = parsedData.h || 0;
22
+ var seed = parsedData.s || 0;
23
+ return hash(matchingKey, seed) % interval;
24
+ }
18
25
  /**
19
26
  * PushManager factory:
20
27
  * - for server-side if key is not provided in settings.
@@ -140,8 +147,9 @@ export function pushManagerFactory(params, pollingManager) {
140
147
  splitsUpdateWorker.stop();
141
148
  if (userKey)
142
149
  forOwn(clients, function (_a) {
143
- var worker = _a.worker;
144
- return worker.stop();
150
+ var worker = _a.worker, workerLarge = _a.workerLarge;
151
+ worker.stop();
152
+ workerLarge && workerLarge.stop();
145
153
  });
146
154
  else
147
155
  segmentsUpdateWorker.stop();
@@ -195,77 +203,96 @@ export function pushManagerFactory(params, pollingManager) {
195
203
  }
196
204
  splitsUpdateWorker.put(parsedData);
197
205
  });
198
- if (userKey) {
199
- pushEmitter.on(MY_SEGMENTS_UPDATE, function handleMySegmentsUpdate(parsedData, channel) {
200
- var userKeyHash = channel.split('_')[2];
201
- var userKey = userKeyHashes[userKeyHash];
202
- if (userKey && clients[userKey]) { // check existence since it can be undefined if client has been destroyed
203
- clients[userKey].worker.put(parsedData.changeNumber, parsedData.includesPayload ? parsedData.segmentList ? parsedData.segmentList : [] : undefined);
204
- }
205
- });
206
- pushEmitter.on(MY_SEGMENTS_UPDATE_V2, function handleMySegmentsUpdate(parsedData) {
207
- switch (parsedData.u) {
208
- case UpdateStrategy.BoundedFetchRequest: {
209
- var bitmap_1;
210
- try {
211
- bitmap_1 = parseBitmap(parsedData.d, parsedData.c);
212
- }
213
- catch (e) {
214
- log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['BoundedFetchRequest', e]);
215
- break;
216
- }
217
- forOwn(clients, function (_a) {
218
- var hash64 = _a.hash64, worker = _a.worker;
219
- if (isInBitmap(bitmap_1, hash64.hex)) {
220
- worker.put(parsedData.changeNumber); // fetch mySegments
221
- }
222
- });
223
- return;
206
+ function handleMySegmentsUpdate(parsedData) {
207
+ var isLS = parsedData.type === MY_LARGE_SEGMENTS_UPDATE;
208
+ switch (parsedData.u) {
209
+ case UpdateStrategy.BoundedFetchRequest: {
210
+ var bitmap_1;
211
+ try {
212
+ bitmap_1 = parseBitmap(parsedData.d, parsedData.c);
224
213
  }
225
- case UpdateStrategy.KeyList: {
226
- var keyList = void 0, added_1, removed_1;
227
- try {
228
- keyList = parseKeyList(parsedData.d, parsedData.c);
229
- added_1 = new _Set(keyList.a);
230
- removed_1 = new _Set(keyList.r);
231
- }
232
- catch (e) {
233
- log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['KeyList', e]);
234
- break;
214
+ catch (e) {
215
+ log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['BoundedFetchRequest', e]);
216
+ break;
217
+ }
218
+ forOwn(clients, function (_a, matchingKey) {
219
+ var hash64 = _a.hash64, worker = _a.worker, workerLarge = _a.workerLarge;
220
+ if (isInBitmap(bitmap_1, hash64.hex)) {
221
+ isLS ?
222
+ workerLarge && workerLarge.put(parsedData.changeNumber, undefined, getDelay(parsedData, matchingKey)) :
223
+ worker.put(parsedData.changeNumber);
235
224
  }
236
- forOwn(clients, function (_a) {
237
- var hash64 = _a.hash64, worker = _a.worker;
238
- var add = added_1.has(hash64.dec) ? true : removed_1.has(hash64.dec) ? false : undefined;
239
- if (add !== undefined) {
225
+ });
226
+ return;
227
+ }
228
+ case UpdateStrategy.KeyList: {
229
+ var keyList = void 0, added_1, removed_1;
230
+ try {
231
+ keyList = parseKeyList(parsedData.d, parsedData.c);
232
+ added_1 = new _Set(keyList.a);
233
+ removed_1 = new _Set(keyList.r);
234
+ }
235
+ catch (e) {
236
+ log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['KeyList', e]);
237
+ break;
238
+ }
239
+ forOwn(clients, function (_a) {
240
+ var hash64 = _a.hash64, worker = _a.worker, workerLarge = _a.workerLarge;
241
+ var add = added_1.has(hash64.dec) ? true : removed_1.has(hash64.dec) ? false : undefined;
242
+ if (add !== undefined) {
243
+ isLS ?
244
+ workerLarge && workerLarge.put(parsedData.changeNumber, {
245
+ name: parsedData.largeSegments[0],
246
+ add: add
247
+ }) :
240
248
  worker.put(parsedData.changeNumber, {
241
249
  name: parsedData.segmentName,
242
250
  add: add
243
251
  });
244
- }
245
- });
246
- return;
247
- }
248
- case UpdateStrategy.SegmentRemoval:
249
- if (!parsedData.segmentName) {
250
- log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['SegmentRemoval', 'No segment name was provided']);
251
- break;
252
252
  }
253
- forOwn(clients, function (_a) {
254
- var worker = _a.worker;
255
- return worker.put(parsedData.changeNumber, {
253
+ });
254
+ return;
255
+ }
256
+ case UpdateStrategy.SegmentRemoval:
257
+ if ((isLS && parsedData.largeSegments.length === 0) || (!isLS && !parsedData.segmentName)) {
258
+ log.warn(STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, ['SegmentRemoval', 'No segment name was provided']);
259
+ break;
260
+ }
261
+ forOwn(clients, function (_a) {
262
+ var worker = _a.worker, workerLarge = _a.workerLarge;
263
+ isLS ?
264
+ workerLarge && parsedData.largeSegments.forEach(function (largeSegment) {
265
+ workerLarge.put(parsedData.changeNumber, {
266
+ name: largeSegment,
267
+ add: false
268
+ });
269
+ }) :
270
+ worker.put(parsedData.changeNumber, {
256
271
  name: parsedData.segmentName,
257
272
  add: false
258
273
  });
259
- });
260
- return;
261
- }
262
- // `UpdateStrategy.UnboundedFetchRequest` and fallbacks of other cases
263
- forOwn(clients, function (_a) {
264
- var worker = _a.worker;
274
+ });
275
+ return;
276
+ }
277
+ // `UpdateStrategy.UnboundedFetchRequest` and fallbacks of other cases
278
+ forOwn(clients, function (_a, matchingKey) {
279
+ var worker = _a.worker, workerLarge = _a.workerLarge;
280
+ isLS ?
281
+ workerLarge && workerLarge.put(parsedData.changeNumber, undefined, getDelay(parsedData, matchingKey)) :
265
282
  worker.put(parsedData.changeNumber);
266
- });
267
283
  });
268
284
  }
285
+ if (userKey) {
286
+ pushEmitter.on(MY_SEGMENTS_UPDATE, function handleMySegmentsUpdate(parsedData, channel) {
287
+ var userKeyHash = channel.split('_')[2];
288
+ var userKey = userKeyHashes[userKeyHash];
289
+ if (userKey && clients[userKey]) { // check existence since it can be undefined if client has been destroyed
290
+ clients[userKey].worker.put(parsedData.changeNumber, parsedData.includesPayload ? parsedData.segmentList ? parsedData.segmentList : [] : undefined);
291
+ }
292
+ });
293
+ pushEmitter.on(MY_SEGMENTS_UPDATE_V2, handleMySegmentsUpdate);
294
+ pushEmitter.on(MY_LARGE_SEGMENTS_UPDATE, handleMySegmentsUpdate);
295
+ }
269
296
  else {
270
297
  pushEmitter.on(SEGMENT_UPDATE, segmentsUpdateWorker.put);
271
298
  }
@@ -287,7 +314,7 @@ export function pushManagerFactory(params, pollingManager) {
287
314
  return;
288
315
  disconnected = false;
289
316
  if (userKey)
290
- this.add(userKey, pollingManager.segmentsSyncTask); // client-side
317
+ this.add(userKey, pollingManager.segmentsSyncTask, pollingManager.largeSegmentsSyncTask); // client-side
291
318
  else
292
319
  setTimeout(connectPush); // server-side runs in next cycle as in client-side, for consistency with client-side
293
320
  },
@@ -296,11 +323,15 @@ export function pushManagerFactory(params, pollingManager) {
296
323
  return disconnected === false;
297
324
  },
298
325
  // [Only for client-side]
299
- add: function (userKey, mySegmentsSyncTask) {
326
+ add: function (userKey, mySegmentsSyncTask, myLargeSegmentsSyncTask) {
300
327
  var hash = hashUserKey(userKey);
301
328
  if (!userKeyHashes[hash]) {
302
329
  userKeyHashes[hash] = userKey;
303
- clients[userKey] = { hash64: hash64(userKey), worker: MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker) };
330
+ clients[userKey] = {
331
+ hash64: hash64(userKey),
332
+ worker: MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, MY_SEGMENT),
333
+ workerLarge: myLargeSegmentsSyncTask ? MySegmentsUpdateWorker(myLargeSegmentsSyncTask, telemetryTracker, MY_LARGE_SEGMENT) : undefined
334
+ };
304
335
  connectForNewClient = true; // we must reconnect on start, to listen the channel for the new user key
305
336
  // Reconnects in case of a new client.
306
337
  // Run in next event-loop cycle to save authentication calls
@@ -61,10 +61,12 @@ export function telemetryCacheConfigAdapter(telemetry, settings) {
61
61
  var _a = getTelemetryFlagSetsStats(settings.sync.__splitFiltersValidation), flagSetsTotal = _a.flagSetsTotal, flagSetsIgnored = _a.flagSetsIgnored;
62
62
  return objectAssign(getTelemetryConfigStats(settings.mode, settings.storage.type), {
63
63
  sE: settings.streamingEnabled,
64
+ lE: isClientSide ? settings.sync.largeSegmentsEnabled : undefined,
64
65
  rR: {
65
66
  sp: scheduler.featuresRefreshRate / 1000,
66
67
  se: isClientSide ? undefined : scheduler.segmentsRefreshRate / 1000,
67
68
  ms: isClientSide ? scheduler.segmentsRefreshRate / 1000 : undefined,
69
+ mls: isClientSide && settings.sync.largeSegmentsEnabled ? scheduler.largeSegmentsRefreshRate / 1000 : undefined,
68
70
  im: scheduler.impressionsRefreshRate / 1000,
69
71
  ev: scheduler.eventsPushRate / 1000,
70
72
  te: scheduler.telemetryRefreshRate / 1000,