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