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

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 (138) hide show
  1. package/CHANGES.txt +4 -0
  2. package/cjs/logger/constants.js +5 -4
  3. package/cjs/logger/messages/info.js +2 -1
  4. package/cjs/logger/messages/warn.js +1 -1
  5. package/cjs/readiness/readinessManager.js +7 -12
  6. package/cjs/services/splitApi.js +4 -8
  7. package/cjs/storages/AbstractSegmentsCacheSync.js +1 -6
  8. package/cjs/storages/AbstractSplitsCacheAsync.js +2 -2
  9. package/cjs/storages/AbstractSplitsCacheSync.js +7 -5
  10. package/cjs/storages/KeyBuilder.js +0 -3
  11. package/cjs/storages/KeyBuilderCS.js +6 -0
  12. package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +23 -2
  13. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +4 -16
  14. package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +5 -1
  15. package/cjs/storages/inMemory/SplitsCacheInMemory.js +6 -15
  16. package/cjs/sync/polling/fetchers/mySegmentsFetcher.js +4 -11
  17. package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
  18. package/cjs/sync/polling/pollingManagerCS.js +33 -51
  19. package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
  20. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +23 -19
  21. package/cjs/sync/streaming/SSEHandler/index.js +7 -8
  22. package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +8 -4
  23. package/cjs/sync/streaming/constants.js +2 -3
  24. package/cjs/sync/streaming/parseUtils.js +14 -9
  25. package/cjs/sync/streaming/pushManager.js +29 -52
  26. package/cjs/sync/submitters/telemetrySubmitter.js +0 -2
  27. package/cjs/sync/syncManagerOnline.js +14 -24
  28. package/cjs/utils/constants/index.js +1 -1
  29. package/cjs/utils/settingsValidation/index.js +1 -5
  30. package/esm/logger/constants.js +2 -1
  31. package/esm/logger/messages/info.js +2 -1
  32. package/esm/logger/messages/warn.js +1 -1
  33. package/esm/readiness/readinessManager.js +7 -12
  34. package/esm/services/splitApi.js +5 -9
  35. package/esm/storages/AbstractSegmentsCacheSync.js +1 -6
  36. package/esm/storages/AbstractSplitsCacheAsync.js +2 -2
  37. package/esm/storages/AbstractSplitsCacheSync.js +5 -3
  38. package/esm/storages/KeyBuilder.js +0 -3
  39. package/esm/storages/KeyBuilderCS.js +6 -0
  40. package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +23 -2
  41. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +5 -17
  42. package/esm/storages/inMemory/MySegmentsCacheInMemory.js +5 -1
  43. package/esm/storages/inMemory/SplitsCacheInMemory.js +7 -16
  44. package/esm/sync/polling/fetchers/mySegmentsFetcher.js +4 -11
  45. package/esm/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
  46. package/esm/sync/polling/pollingManagerCS.js +34 -52
  47. package/esm/sync/polling/syncTasks/mySegmentsSyncTask.js +2 -2
  48. package/esm/sync/polling/updaters/mySegmentsUpdater.js +21 -17
  49. package/esm/sync/streaming/SSEHandler/index.js +8 -9
  50. package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +8 -4
  51. package/esm/sync/streaming/constants.js +1 -2
  52. package/esm/sync/streaming/parseUtils.js +12 -8
  53. package/esm/sync/streaming/pushManager.js +31 -53
  54. package/esm/sync/submitters/telemetrySubmitter.js +0 -2
  55. package/esm/sync/syncManagerOnline.js +15 -25
  56. package/esm/utils/constants/index.js +1 -1
  57. package/esm/utils/settingsValidation/index.js +1 -5
  58. package/package.json +1 -1
  59. package/src/dtos/types.ts +14 -12
  60. package/src/logger/constants.ts +2 -1
  61. package/src/logger/messages/info.ts +2 -1
  62. package/src/logger/messages/warn.ts +1 -1
  63. package/src/readiness/readinessManager.ts +7 -9
  64. package/src/readiness/types.ts +0 -1
  65. package/src/services/splitApi.ts +6 -11
  66. package/src/services/splitHttpClient.ts +1 -1
  67. package/src/services/types.ts +2 -3
  68. package/src/storages/AbstractSegmentsCacheSync.ts +2 -6
  69. package/src/storages/AbstractSplitsCacheAsync.ts +2 -2
  70. package/src/storages/AbstractSplitsCacheSync.ts +6 -4
  71. package/src/storages/KeyBuilder.ts +0 -3
  72. package/src/storages/KeyBuilderCS.ts +9 -0
  73. package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +26 -2
  74. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +5 -20
  75. package/src/storages/inMemory/MySegmentsCacheInMemory.ts +7 -1
  76. package/src/storages/inMemory/SplitsCacheInMemory.ts +7 -13
  77. package/src/storages/types.ts +6 -5
  78. package/src/sync/polling/fetchers/mySegmentsFetcher.ts +7 -14
  79. package/src/sync/polling/fetchers/segmentChangesFetcher.ts +1 -1
  80. package/src/sync/polling/fetchers/types.ts +2 -2
  81. package/src/sync/polling/pollingManagerCS.ts +29 -61
  82. package/src/sync/polling/syncTasks/mySegmentsSyncTask.ts +12 -13
  83. package/src/sync/polling/types.ts +8 -7
  84. package/src/sync/polling/updaters/mySegmentsUpdater.ts +20 -16
  85. package/src/sync/streaming/SSEClient/index.ts +4 -6
  86. package/src/sync/streaming/SSEHandler/index.ts +11 -13
  87. package/src/sync/streaming/SSEHandler/types.ts +13 -25
  88. package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +11 -7
  89. package/src/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.ts +1 -1
  90. package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +1 -1
  91. package/src/sync/streaming/UpdateWorkers/types.ts +2 -2
  92. package/src/sync/streaming/constants.ts +1 -2
  93. package/src/sync/streaming/parseUtils.ts +19 -11
  94. package/src/sync/streaming/pushManager.ts +37 -64
  95. package/src/sync/streaming/types.ts +9 -11
  96. package/src/sync/submitters/telemetrySubmitter.ts +0 -2
  97. package/src/sync/submitters/types.ts +1 -3
  98. package/src/sync/syncManagerOnline.ts +11 -19
  99. package/src/types.ts +1 -26
  100. package/src/utils/constants/index.ts +1 -1
  101. package/src/utils/settingsValidation/index.ts +1 -5
  102. package/types/dtos/types.d.ts +14 -11
  103. package/types/logger/constants.d.ts +2 -1
  104. package/types/readiness/types.d.ts +0 -1
  105. package/types/services/decorateHeaders.d.ts +2 -0
  106. package/types/services/splitApi.d.ts +1 -1
  107. package/types/services/splitHttpClient.d.ts +1 -1
  108. package/types/services/types.d.ts +2 -3
  109. package/types/storages/AbstractSegmentsCacheSync.d.ts +2 -6
  110. package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
  111. package/types/storages/AbstractSplitsCacheSync.d.ts +3 -3
  112. package/types/storages/KeyBuilder.d.ts +0 -1
  113. package/types/storages/KeyBuilderCS.d.ts +2 -0
  114. package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +3 -2
  115. package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +1 -1
  116. package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +3 -1
  117. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +1 -2
  118. package/types/storages/types.d.ts +4 -4
  119. package/types/sync/polling/fetchers/mySegmentsFetcher.d.ts +2 -2
  120. package/types/sync/polling/fetchers/types.d.ts +2 -2
  121. package/types/sync/polling/syncTasks/mySegmentsSyncTask.d.ts +4 -3
  122. package/types/sync/polling/types.d.ts +6 -12
  123. package/types/sync/polling/updaters/mySegmentsUpdater.d.ts +3 -2
  124. package/types/sync/streaming/SSEHandler/types.d.ts +13 -22
  125. package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +2 -2
  126. package/types/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.d.ts +2 -1
  127. package/types/sync/streaming/UpdateWorkers/SplitsUpdateWorker.d.ts +3 -2
  128. package/types/sync/streaming/UpdateWorkers/types.d.ts +2 -2
  129. package/types/sync/streaming/constants.d.ts +1 -2
  130. package/types/sync/streaming/parseUtils.d.ts +4 -5
  131. package/types/sync/streaming/pushManager.d.ts +0 -2
  132. package/types/sync/streaming/pushManagerCS_Spec1_3.d.ts +9 -0
  133. package/types/sync/streaming/pushManager_Spec1_3.d.ts +9 -0
  134. package/types/sync/streaming/types.d.ts +8 -9
  135. package/types/sync/submitters/types.d.ts +1 -3
  136. package/types/types.d.ts +0 -25
  137. package/types/utils/constants/index.d.ts +1 -1
  138. package/types/utils/settingsValidation/index.d.ts +0 -2
@@ -1,6 +1,6 @@
1
1
  import { splitHttpClientFactory } from './splitHttpClient';
2
2
  import { objectAssign } from '../utils/lang/objectAssign';
3
- import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MY_SEGMENT, MY_LARGE_SEGMENT } from '../utils/constants';
3
+ import { SPLITS, IMPRESSIONS, IMPRESSIONS_COUNT, EVENTS, TELEMETRY, TOKEN, SEGMENT, MY_SEGMENT } from '../utils/constants';
4
4
  import { ERROR_TOO_MANY_SETS } from '../logger/constants';
5
5
  var noCacheHeaderOptions = { headers: { 'Cache-Control': 'no-cache' } };
6
6
  function userKeyToQueryParam(userKey) {
@@ -51,20 +51,16 @@ export function splitApiFactory(settings, platform, telemetryTracker) {
51
51
  var url = urls.sdk + "/segmentChanges/" + segmentName + "?since=" + since + (till ? '&till=' + till : '');
52
52
  return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(SEGMENT));
53
53
  },
54
- fetchMySegments: function (userMatchingKey, noCache) {
54
+ fetchMemberships: function (userMatchingKey, noCache) {
55
55
  /**
56
56
  * URI encoding of user keys in order to:
57
- * - avoid 400 responses (due to URI malformed). E.g.: '/api/mySegments/%'
58
- * - avoid 404 responses. E.g.: '/api/mySegments/foo/bar'
57
+ * - avoid 400 responses (due to URI malformed). E.g.: '/api/memberships/%'
58
+ * - avoid 404 responses. E.g.: '/api/memberships/foo/bar'
59
59
  * - match user keys with special characters. E.g.: 'foo%bar', 'foo/bar'
60
60
  */
61
- var url = urls.sdk + "/mySegments/" + encodeURIComponent(userMatchingKey);
61
+ var url = urls.sdk + "/memberships/" + encodeURIComponent(userMatchingKey);
62
62
  return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(MY_SEGMENT));
63
63
  },
64
- fetchMyLargeSegments: function (userMatchingKey, noCache) {
65
- var url = urls.sdk + "/myLargeSegments/" + encodeURIComponent(userMatchingKey);
66
- return splitHttpClient(url, noCache ? noCacheHeaderOptions : undefined, telemetryTracker.trackHttp(MY_LARGE_SEGMENT));
67
- },
68
64
  /**
69
65
  * Post events.
70
66
  *
@@ -15,16 +15,11 @@ var AbstractSegmentsCacheSync = /** @class */ (function () {
15
15
  * For client-side synchronizer: the method is not used.
16
16
  */
17
17
  AbstractSegmentsCacheSync.prototype.setChangeNumber = function (name, changeNumber) { return true; };
18
- /**
19
- * For server-side synchronizer: get the change number of `name` segment.
20
- * For client-side synchronizer: the method is not used.
21
- */
22
- AbstractSegmentsCacheSync.prototype.getChangeNumber = function (name) { return -1; };
23
18
  /**
24
19
  * For server-side synchronizer: the method is not used.
25
20
  * For client-side synchronizer: reset the cache with the given list of segments.
26
21
  */
27
- AbstractSegmentsCacheSync.prototype.resetSegments = function (names) { return true; };
22
+ AbstractSegmentsCacheSync.prototype.resetSegments = function (names, changeNumber) { return true; };
28
23
  return AbstractSegmentsCacheSync;
29
24
  }());
30
25
  export { AbstractSegmentsCacheSync };
@@ -6,9 +6,9 @@ import { objectAssign } from '../utils/lang/objectAssign';
6
6
  var AbstractSplitsCacheAsync = /** @class */ (function () {
7
7
  function AbstractSplitsCacheAsync() {
8
8
  }
9
- // @TODO revisit segment-related methods ('usesMatcher', 'getRegisteredSegments', 'registerSegments')
9
+ // @TODO revisit segment-related methods ('usesSegments', 'getRegisteredSegments', 'registerSegments')
10
10
  // noop, just keeping the interface. This is used by standalone client-side API only, and so only implemented by InMemory and InLocalStorage.
11
- AbstractSplitsCacheAsync.prototype.usesMatcher = function () {
11
+ AbstractSplitsCacheAsync.prototype.usesSegments = function () {
12
12
  return Promise.resolve(true);
13
13
  };
14
14
  /**
@@ -1,4 +1,5 @@
1
1
  import { objectAssign } from '../utils/lang/objectAssign';
2
+ import { IN_SEGMENT, IN_LARGE_SEGMENT } from '../utils/constants';
2
3
  /**
3
4
  * This class provides a skeletal implementation of the ISplitsCacheSync interface
4
5
  * to minimize the effort required to implement this interface.
@@ -59,14 +60,15 @@ var AbstractSplitsCacheSync = /** @class */ (function () {
59
60
  export { AbstractSplitsCacheSync };
60
61
  /**
61
62
  * Given a parsed split, it returns a boolean flagging if its conditions use segments matchers (rules & whitelists).
62
- * This util is intended to simplify the implementation of `splitsCache::usesMatcher` method
63
+ * This util is intended to simplify the implementation of `splitsCache::usesSegments` method
63
64
  */
64
- export function usesMatcher(split, matcherType) {
65
+ export function usesSegments(split) {
65
66
  var conditions = split.conditions || [];
66
67
  for (var i = 0; i < conditions.length; i++) {
67
68
  var matchers = conditions[i].matcherGroup.matchers;
68
69
  for (var j = 0; j < matchers.length; j++) {
69
- if (matchers[j].matcherType === matcherType)
70
+ var matcher = matchers[j].matcherType;
71
+ if (matcher === IN_SEGMENT || matcher === IN_LARGE_SEGMENT)
70
72
  return true;
71
73
  }
72
74
  }
@@ -36,9 +36,6 @@ var KeyBuilder = /** @class */ (function () {
36
36
  KeyBuilder.prototype.buildSplitsWithSegmentCountKey = function () {
37
37
  return this.prefix + ".splits.usingSegments";
38
38
  };
39
- KeyBuilder.prototype.buildSplitsWithLargeSegmentCountKey = function () {
40
- return this.prefix + ".splits.usingLargeSegments";
41
- };
42
39
  KeyBuilder.prototype.buildSegmentNameKey = function (segmentName) {
43
40
  return this.prefix + ".segment." + segmentName;
44
41
  };
@@ -32,6 +32,9 @@ var KeyBuilderCS = /** @class */ (function (_super) {
32
32
  KeyBuilderCS.prototype.isSplitsCacheKey = function (key) {
33
33
  return this.regexSplitsCacheKey.test(key);
34
34
  };
35
+ KeyBuilderCS.prototype.buildTillKey = function () {
36
+ return this.prefix + "." + this.matchingKey + ".segments.till";
37
+ };
35
38
  return KeyBuilderCS;
36
39
  }(KeyBuilder));
37
40
  export { KeyBuilderCS };
@@ -47,6 +50,9 @@ export function myLargeSegmentsKeyBuilder(prefix, matchingKey) {
47
50
  },
48
51
  extractOldSegmentKey: function () {
49
52
  return undefined;
53
+ },
54
+ buildTillKey: function () {
55
+ return prefix + "." + matchingKey + ".largeSegments.till";
50
56
  }
51
57
  };
52
58
  }
@@ -1,4 +1,5 @@
1
1
  import { __extends } from "tslib";
2
+ import { isNaNNumber } from '../../utils/lang';
2
3
  import { AbstractSegmentsCacheSync } from '../AbstractSegmentsCacheSync';
3
4
  import { LOG_PREFIX, DEFINED } from './constants';
4
5
  var MySegmentsCacheInLocal = /** @class */ (function (_super) {
@@ -48,11 +49,22 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
48
49
  /**
49
50
  * Reset (update) the cached list of segments with the given list, removing and adding segments if necessary.
50
51
  *
51
- * @param {string[]} segmentNames list of segment names
52
+ * @param {string[]} names list of segment names
52
53
  * @returns boolean indicating if the cache was updated (i.e., given list was different from the cached one)
53
54
  */
54
- MySegmentsCacheInLocal.prototype.resetSegments = function (names) {
55
+ MySegmentsCacheInLocal.prototype.resetSegments = function (names, changeNumber) {
55
56
  var _this = this;
57
+ try {
58
+ if (changeNumber) {
59
+ localStorage.setItem(this.keys.buildTillKey(), changeNumber + '');
60
+ }
61
+ else {
62
+ localStorage.removeItem(this.keys.buildTillKey());
63
+ }
64
+ }
65
+ catch (e) {
66
+ this.log.error(e);
67
+ }
56
68
  var isDiff = false;
57
69
  var index;
58
70
  // Scan current values from localStorage
@@ -116,6 +128,15 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
116
128
  MySegmentsCacheInLocal.prototype.getKeysCount = function () {
117
129
  return 1;
118
130
  };
131
+ MySegmentsCacheInLocal.prototype.getChangeNumber = function () {
132
+ var n = -1;
133
+ var value = localStorage.getItem(this.keys.buildTillKey());
134
+ if (value !== null) {
135
+ value = parseInt(value, 10);
136
+ return isNaNNumber(value) ? n : value;
137
+ }
138
+ return n;
139
+ };
119
140
  return MySegmentsCacheInLocal;
120
141
  }(AbstractSegmentsCacheSync));
121
142
  export { MySegmentsCacheInLocal };
@@ -1,10 +1,9 @@
1
1
  import { __extends } from "tslib";
2
- import { AbstractSplitsCacheSync, usesMatcher } from '../AbstractSplitsCacheSync';
2
+ import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSync';
3
3
  import { isFiniteNumber, toNumber, isNaNNumber } from '../../utils/lang';
4
4
  import { LOG_PREFIX } from './constants';
5
5
  import { _Set, setToArray } from '../../utils/lang/sets';
6
6
  import { getStorageHash } from '../KeyBuilder';
7
- import { IN_LARGE_SEGMENT, IN_SEGMENT } from '../../utils/constants';
8
7
  /**
9
8
  * ISplitsCacheSync implementation that stores split definitions in browser LocalStorage.
10
9
  */
@@ -38,14 +37,10 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
38
37
  if (split) {
39
38
  var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
40
39
  this._decrementCount(ttKey);
41
- if (usesMatcher(split, IN_SEGMENT)) {
40
+ if (usesSegments(split)) {
42
41
  var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
43
42
  this._decrementCount(segmentsCountKey);
44
43
  }
45
- if (usesMatcher(split, IN_LARGE_SEGMENT)) {
46
- var segmentsCountKey = this.keys.buildSplitsWithLargeSegmentCountKey();
47
- this._decrementCount(segmentsCountKey);
48
- }
49
44
  }
50
45
  }
51
46
  catch (e) {
@@ -58,16 +53,11 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
58
53
  var ttKey = this.keys.buildTrafficTypeKey(split.trafficTypeName);
59
54
  // @ts-expect-error
60
55
  localStorage.setItem(ttKey, toNumber(localStorage.getItem(ttKey)) + 1);
61
- if (usesMatcher(split, IN_SEGMENT)) {
56
+ if (usesSegments(split)) {
62
57
  var segmentsCountKey = this.keys.buildSplitsWithSegmentCountKey();
63
58
  // @ts-expect-error
64
59
  localStorage.setItem(segmentsCountKey, toNumber(localStorage.getItem(segmentsCountKey)) + 1);
65
60
  }
66
- if (usesMatcher(split, IN_LARGE_SEGMENT)) {
67
- var segmentsCountKey = this.keys.buildSplitsWithLargeSegmentCountKey();
68
- // @ts-expect-error
69
- localStorage.setItem(segmentsCountKey, toNumber(localStorage.getItem(segmentsCountKey)) + 1);
70
- }
71
61
  }
72
62
  }
73
63
  catch (e) {
@@ -180,13 +170,11 @@ var SplitsCacheInLocal = /** @class */ (function (_super) {
180
170
  var ttCount = toNumber(localStorage.getItem(this.keys.buildTrafficTypeKey(trafficType)));
181
171
  return isFiniteNumber(ttCount) && ttCount > 0;
182
172
  };
183
- SplitsCacheInLocal.prototype.usesMatcher = function (matcherType) {
173
+ SplitsCacheInLocal.prototype.usesSegments = function () {
184
174
  // If cache hasn't been synchronized with the cloud, assume we need them.
185
175
  if (!this.hasSync)
186
176
  return true;
187
- var storedCount = localStorage.getItem(matcherType === IN_SEGMENT ?
188
- this.keys.buildSplitsWithSegmentCountKey() :
189
- this.keys.buildSplitsWithLargeSegmentCountKey());
177
+ var storedCount = localStorage.getItem(this.keys.buildSplitsWithSegmentCountKey());
190
178
  var splitsWithSegmentsCount = storedCount === null ? 0 : toNumber(storedCount);
191
179
  if (isFiniteNumber(splitsWithSegmentsCount)) {
192
180
  return splitsWithSegmentsCount > 0;
@@ -32,8 +32,9 @@ var MySegmentsCacheInMemory = /** @class */ (function (_super) {
32
32
  * @param {string[]} names list of segment names
33
33
  * @returns boolean indicating if the cache was updated (i.e., given list was different from the cached one)
34
34
  */
35
- MySegmentsCacheInMemory.prototype.resetSegments = function (names) {
35
+ MySegmentsCacheInMemory.prototype.resetSegments = function (names, changeNumber) {
36
36
  var _this = this;
37
+ this.cn = changeNumber;
37
38
  var isDiff = false;
38
39
  var index;
39
40
  var storedSegmentKeys = Object.keys(this.segmentCache);
@@ -63,6 +64,9 @@ var MySegmentsCacheInMemory = /** @class */ (function (_super) {
63
64
  }
64
65
  return isDiff;
65
66
  };
67
+ MySegmentsCacheInMemory.prototype.getChangeNumber = function () {
68
+ return this.cn || -1;
69
+ };
66
70
  MySegmentsCacheInMemory.prototype.getRegisteredSegments = function () {
67
71
  return Object.keys(this.segmentCache);
68
72
  };
@@ -1,8 +1,7 @@
1
1
  import { __extends } from "tslib";
2
- import { AbstractSplitsCacheSync, usesMatcher } from '../AbstractSplitsCacheSync';
2
+ import { AbstractSplitsCacheSync, usesSegments } 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';
6
5
  /**
7
6
  * Default ISplitsCacheSync implementation that stores split definitions in memory.
8
7
  * Supported by all JS runtimes.
@@ -15,7 +14,6 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
15
14
  _this.ttCache = {};
16
15
  _this.changeNumber = -1;
17
16
  _this.segmentsCount = 0;
18
- _this.largeSegmentsCount = 0;
19
17
  _this.flagSetsCache = {};
20
18
  _this.flagSetsFilter = splitFiltersValidation ? splitFiltersValidation.groupedFilters.bySet : [];
21
19
  return _this;
@@ -25,7 +23,6 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
25
23
  this.ttCache = {};
26
24
  this.changeNumber = -1;
27
25
  this.segmentsCount = 0;
28
- this.largeSegmentsCount = 0;
29
26
  };
30
27
  SplitsCacheInMemory.prototype.addSplit = function (name, split) {
31
28
  var previousSplit = this.getSplit(name);
@@ -35,11 +32,9 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
35
32
  if (!this.ttCache[previousTtName])
36
33
  delete this.ttCache[previousTtName];
37
34
  this.removeFromFlagSets(previousSplit.name, previousSplit.sets);
38
- // Substract from segments count for the previous version of this Split.
39
- if (usesMatcher(previousSplit, IN_SEGMENT))
35
+ // Subtract from segments count for the previous version of this Split
36
+ if (usesSegments(previousSplit))
40
37
  this.segmentsCount--;
41
- if (usesMatcher(previousSplit, IN_LARGE_SEGMENT))
42
- this.largeSegmentsCount--;
43
38
  }
44
39
  if (split) {
45
40
  // Store the Split.
@@ -49,10 +44,8 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
49
44
  this.ttCache[ttName] = (this.ttCache[ttName] || 0) + 1;
50
45
  this.addToFlagSets(split);
51
46
  // Add to segments count for the new version of the Split
52
- if (usesMatcher(split, IN_SEGMENT))
47
+ if (usesSegments(split))
53
48
  this.segmentsCount++;
54
- if (usesMatcher(split, IN_LARGE_SEGMENT))
55
- this.largeSegmentsCount++;
56
49
  return true;
57
50
  }
58
51
  else {
@@ -70,10 +63,8 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
70
63
  delete this.ttCache[ttName];
71
64
  this.removeFromFlagSets(split.name, split.sets);
72
65
  // Update the segments count.
73
- if (usesMatcher(split, IN_SEGMENT))
66
+ if (usesSegments(split))
74
67
  this.segmentsCount--;
75
- if (usesMatcher(split, IN_LARGE_SEGMENT))
76
- this.largeSegmentsCount--;
77
68
  return true;
78
69
  }
79
70
  else {
@@ -96,8 +87,8 @@ var SplitsCacheInMemory = /** @class */ (function (_super) {
96
87
  SplitsCacheInMemory.prototype.trafficTypeExists = function (trafficType) {
97
88
  return isFiniteNumber(this.ttCache[trafficType]) && this.ttCache[trafficType] > 0;
98
89
  };
99
- SplitsCacheInMemory.prototype.usesMatcher = function (matcherType) {
100
- return this.getChangeNumber() === -1 || (matcherType === IN_SEGMENT ? this.segmentsCount > 0 : this.largeSegmentsCount > 0);
90
+ SplitsCacheInMemory.prototype.usesSegments = function () {
91
+ return this.getChangeNumber() === -1 || this.segmentsCount > 0;
101
92
  };
102
93
  SplitsCacheInMemory.prototype.getNamesByFlagSets = function (flagSets) {
103
94
  var _this = this;
@@ -2,20 +2,13 @@
2
2
  * Factory of MySegments fetcher.
3
3
  * MySegments fetcher is a wrapper around `mySegments` API service that parses the response and handle errors.
4
4
  */
5
- export function mySegmentsFetcherFactory(fetchMySegments) {
5
+ export function mySegmentsFetcherFactory(fetchMemberships) {
6
6
  return function mySegmentsFetcher(userMatchingKey, noCache,
7
- // Optional decorator for `fetchMySegments` promise, such as timeout or time tracker
7
+ // Optional decorator for `fetchMemberships` promise, such as timeout or time tracker
8
8
  decorator) {
9
- var mySegmentsPromise = fetchMySegments(userMatchingKey, noCache);
9
+ var mySegmentsPromise = fetchMemberships(userMatchingKey, noCache);
10
10
  if (decorator)
11
11
  mySegmentsPromise = decorator(mySegmentsPromise);
12
- // Extract segment names
13
- return mySegmentsPromise
14
- .then(function (resp) { return resp.json(); })
15
- .then(function (json) {
16
- return json.mySegments ?
17
- json.mySegments.map(function (segment) { return segment.name; }) :
18
- json.myLargeSegments;
19
- });
12
+ return mySegmentsPromise.then(function (resp) { return resp.json(); });
20
13
  };
21
14
  }
@@ -20,7 +20,7 @@ function greedyFetch(fetchSegmentChanges, since, segmentName, noCache, targetTil
20
20
  */
21
21
  export function segmentChangesFetcherFactory(fetchSegmentChanges) {
22
22
  return function segmentChangesFetcher(since, segmentName, noCache, till,
23
- // Optional decorator for `fetchMySegments` promise, such as timeout or time tracker
23
+ // Optional decorator for `fetchSegmentChanges` promise, such as timeout or time tracker
24
24
  decorator) {
25
25
  var segmentsPromise = greedyFetch(fetchSegmentChanges, since, segmentName, noCache, till);
26
26
  if (decorator)
@@ -3,8 +3,7 @@ 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_START, POLLING_STOP } from '../../logger/constants';
7
- import { IN_LARGE_SEGMENT, IN_SEGMENT } from '../../utils/constants';
6
+ import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger/constants';
8
7
  /**
9
8
  * Expose start / stop mechanism for polling data from services.
10
9
  * For client-side API with multiple clients.
@@ -13,74 +12,59 @@ export function pollingManagerCSFactory(params) {
13
12
  var splitApi = params.splitApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
14
13
  var log = settings.log;
15
14
  var splitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings, true);
16
- // Map of matching keys to their corresponding MySegmentsSyncTask for segments and large segments.
15
+ // Map of matching keys to their corresponding MySegmentsSyncTask.
17
16
  var mySegmentsSyncTasks = {};
18
17
  var matchingKey = getMatching(settings.core.key);
19
- var _a = add(matchingKey, readiness, storage), msSyncTask = _a.msSyncTask, mlsSyncTask = _a.mlsSyncTask;
18
+ var mySegmentsSyncTask = add(matchingKey, readiness, storage);
20
19
  function startMySegmentsSyncTasks() {
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(); // smart pausing
29
- if (mlsSyncTask) {
30
- if (splitsHaveLargeSegments)
31
- mlsSyncTask.start();
32
- else
33
- mlsSyncTask.stop(); // smart pausing
34
- }
20
+ forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
21
+ mySegmentsSyncTask.start();
35
22
  });
36
23
  }
37
24
  function stopMySegmentsSyncTasks() {
38
- forOwn(mySegmentsSyncTasks, function (_a) {
39
- var msSyncTask = _a.msSyncTask, mlsSyncTask = _a.mlsSyncTask;
40
- msSyncTask.stop();
41
- mlsSyncTask && mlsSyncTask.stop();
25
+ forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
26
+ if (mySegmentsSyncTask.isRunning())
27
+ mySegmentsSyncTask.stop();
42
28
  });
43
29
  }
30
+ // smart pausing
44
31
  readiness.splits.on(SDK_SPLITS_ARRIVED, function () {
45
- if (splitsSyncTask.isRunning())
46
- startMySegmentsSyncTasks();
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
+ }
47
44
  });
48
45
  function add(matchingKey, readiness, storage) {
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');
51
- var mlsSyncTask;
52
- if (settings.sync.largeSegmentsEnabled) {
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');
55
- }
46
+ var mySegmentsSyncTask = mySegmentsSyncTaskFactory(splitApi.fetchMemberships, storage, readiness, settings, matchingKey);
56
47
  // smart ready
57
48
  function smartReady() {
58
- if (!readiness.isReady()) {
59
- if (readiness.largeSegments && !storage.splits.usesMatcher(IN_LARGE_SEGMENT))
60
- readiness.largeSegments.emit(SDK_SEGMENTS_ARRIVED);
61
- if (!storage.splits.usesMatcher(IN_SEGMENT))
62
- readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
63
- }
49
+ if (!readiness.isReady() && !storage.splits.usesSegments())
50
+ readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
64
51
  }
65
- if (storage.splits.usesMatcher(IN_SEGMENT) && storage.splits.usesMatcher(IN_LARGE_SEGMENT))
66
- readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);
67
- else
52
+ if (!storage.splits.usesSegments())
68
53
  setTimeout(smartReady, 0);
69
- mySegmentsSyncTasks[matchingKey] = { msSyncTask: msSyncTask, mlsSyncTask: mlsSyncTask };
70
- return {
71
- msSyncTask: msSyncTask,
72
- mlsSyncTask: mlsSyncTask
73
- };
54
+ else
55
+ readiness.splits.once(SDK_SPLITS_ARRIVED, smartReady);
56
+ mySegmentsSyncTasks[matchingKey] = mySegmentsSyncTask;
57
+ return mySegmentsSyncTask;
74
58
  }
75
59
  return {
76
60
  splitsSyncTask: splitsSyncTask,
77
- segmentsSyncTask: msSyncTask,
78
- largeSegmentsSyncTask: mlsSyncTask,
61
+ segmentsSyncTask: mySegmentsSyncTask,
79
62
  // Start periodic fetching (polling)
80
63
  start: function () {
81
64
  log.info(POLLING_START);
82
65
  splitsSyncTask.start();
83
- startMySegmentsSyncTasks();
66
+ if (storage.splits.usesSegments())
67
+ startMySegmentsSyncTasks();
84
68
  },
85
69
  // Stop periodic fetching (polling)
86
70
  stop: function () {
@@ -94,10 +78,8 @@ export function pollingManagerCSFactory(params) {
94
78
  // fetch splits and segments
95
79
  syncAll: function () {
96
80
  var promises = [splitsSyncTask.execute()];
97
- forOwn(mySegmentsSyncTasks, function (_a) {
98
- var msSyncTask = _a.msSyncTask, mlsSyncTask = _a.mlsSyncTask;
99
- promises.push(msSyncTask.execute());
100
- mlsSyncTask && promises.push(mlsSyncTask.execute());
81
+ forOwn(mySegmentsSyncTasks, function (mySegmentsSyncTask) {
82
+ promises.push(mySegmentsSyncTask.execute());
101
83
  });
102
84
  return Promise.all(promises);
103
85
  },
@@ -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, NAME) {
8
- return syncTaskFactory(settings.log, mySegmentsUpdaterFactory(settings.log, mySegmentsFetcherFactory(fetchMySegments), mySegmentsCache, notifyUpdate, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, matchingKey), segmentsRefreshRate, NAME);
7
+ export function mySegmentsSyncTaskFactory(fetchMemberships, storage, readiness, settings, matchingKey) {
8
+ return syncTaskFactory(settings.log, mySegmentsUpdaterFactory(settings.log, mySegmentsFetcherFactory(fetchMemberships), storage, readiness.segments, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, matchingKey), settings.scheduler.segmentsRefreshRate, 'mySegmentsUpdater');
9
9
  }
@@ -1,4 +1,5 @@
1
1
  import { timeout } from '../../../utils/promise/timeout';
2
+ import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
2
3
  import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
3
4
  /**
4
5
  * factory of MySegments updater, a task that:
@@ -6,7 +7,8 @@ import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
6
7
  * - updates `mySegmentsCache`
7
8
  * - uses `segmentsEventEmitter` to emit events related to segments data updates
8
9
  */
9
- export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, mySegmentsCache, notifyUpdate, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, matchingKey) {
10
+ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, storage, segmentsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, matchingKey) {
11
+ var splits = storage.splits, segments = storage.segments, largeSegments = storage.largeSegments;
10
12
  var readyOnAlreadyExistentState = true;
11
13
  var startingUp = true;
12
14
  /** timeout and telemetry decorator for `splitChangesFetcher` promise */
@@ -17,29 +19,31 @@ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, mySegmentsCache
17
19
  }
18
20
  // @TODO if allowing pluggable storages, handle async execution
19
21
  function updateSegments(segmentsData) {
22
+ var _a, _b, _c, _d;
20
23
  var shouldNotifyUpdate;
21
24
  if (Array.isArray(segmentsData)) {
22
- // Update the list of segment names available
23
- shouldNotifyUpdate = mySegmentsCache.resetSegments(segmentsData);
25
+ // Add/Delete the segment names
26
+ segmentsData.forEach(function (_a) {
27
+ var isLS = _a.isLS, name = _a.name, add = _a.add;
28
+ var cache = isLS ? largeSegments : segments;
29
+ if (cache.isInSegment(name) !== add) {
30
+ shouldNotifyUpdate = true;
31
+ if (add)
32
+ cache.addToSegment(name);
33
+ else
34
+ cache.removeFromSegment(name);
35
+ }
36
+ });
24
37
  }
25
38
  else {
26
- // Add/Delete the segment
27
- var name_1 = segmentsData.name, add = segmentsData.add;
28
- if (mySegmentsCache.isInSegment(name_1) !== add) {
29
- shouldNotifyUpdate = true;
30
- if (add)
31
- mySegmentsCache.addToSegment(name_1);
32
- else
33
- mySegmentsCache.removeFromSegment(name_1);
34
- }
35
- else {
36
- shouldNotifyUpdate = false;
37
- }
39
+ // Reset the list of segment names
40
+ shouldNotifyUpdate = segments.resetSegments((((_a = segmentsData.ms) === null || _a === void 0 ? void 0 : _a.k) || []).map(function (segment) { return segment.n; }), (_b = segmentsData.ms) === null || _b === void 0 ? void 0 : _b.cn);
41
+ shouldNotifyUpdate = largeSegments.resetSegments((((_c = segmentsData.ls) === null || _c === void 0 ? void 0 : _c.k) || []).map(function (segment) { return segment.n; }), (_d = segmentsData.ls) === null || _d === void 0 ? void 0 : _d.cn) || shouldNotifyUpdate;
38
42
  }
39
43
  // Notify update if required
40
- if (shouldNotifyUpdate || readyOnAlreadyExistentState) {
44
+ if (splits.usesSegments() && (shouldNotifyUpdate || readyOnAlreadyExistentState)) {
41
45
  readyOnAlreadyExistentState = false;
42
- notifyUpdate();
46
+ segmentsEventEmitter.emit(SDK_SEGMENTS_ARRIVED);
43
47
  }
44
48
  }
45
49
  function _mySegmentsUpdater(retry, segmentsData, noCache) {
@@ -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, MY_LARGE_SEGMENTS_UPDATE } from '../constants';
3
+ import { PUSH_RETRYABLE_ERROR, PUSH_NONRETRYABLE_ERROR, OCCUPANCY, CONTROL, MY_SEGMENTS_UPDATE_V3, 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
  /**
@@ -65,20 +65,19 @@ export function SSEHandlerFactory(log, pushEmitter, telemetryTracker) {
65
65
  }
66
66
  var parsedData = messageWithParsedData.parsedData, data = messageWithParsedData.data, channel = messageWithParsedData.channel, timestamp = messageWithParsedData.timestamp;
67
67
  log.debug(STREAMING_NEW_MESSAGE, [data]);
68
- // we only handle update events if streaming is up.
69
- if (!notificationKeeper.isStreamingUp() && [OCCUPANCY, CONTROL].indexOf(parsedData.type) === -1)
68
+ // we only handle update events if streaming is up
69
+ // @ts-expect-error
70
+ var type = parsedData.type || parsedData.t;
71
+ if (!notificationKeeper.isStreamingUp() && [OCCUPANCY, CONTROL].indexOf(type) === -1)
70
72
  return;
71
- switch (parsedData.type) {
73
+ switch (type) {
72
74
  /* update events */
73
75
  case SPLIT_UPDATE:
74
76
  case SEGMENT_UPDATE:
75
- case MY_SEGMENTS_UPDATE_V2:
77
+ case MY_SEGMENTS_UPDATE_V3:
76
78
  case MY_LARGE_SEGMENTS_UPDATE:
77
79
  case SPLIT_KILL:
78
- pushEmitter.emit(parsedData.type, parsedData);
79
- break;
80
- case MY_SEGMENTS_UPDATE:
81
- pushEmitter.emit(parsedData.type, parsedData, channel);
80
+ pushEmitter.emit(type, parsedData);
82
81
  break;
83
82
  /* occupancy & control events, handled by NotificationManagerKeeper */
84
83
  case OCCUPANCY:
@@ -20,6 +20,7 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
20
20
  var syncTask = _delay ?
21
21
  new Promise(function (res) {
22
22
  _delayTimeoutID = setTimeout(function () {
23
+ _delay = undefined;
23
24
  mySegmentsSyncTask.execute(_segmentsData, true).then(res);
24
25
  }, _delay);
25
26
  }) :
@@ -46,13 +47,15 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
46
47
  }
47
48
  return {
48
49
  /**
49
- * Invoked by NotificationProcessor on MY_SEGMENTS_UPDATE event
50
+ * Invoked by NotificationProcessor on MY_(LARGE)_SEGMENTS_UPDATE notifications
50
51
  *
51
- * @param {number} changeNumber change number of the MY_SEGMENTS_UPDATE notification
52
- * @param {SegmentsData | undefined} segmentsData might be undefined
52
+ * @param changeNumber change number of the notification
53
+ * @param segmentsData data for KeyList or SegmentRemoval instant updates
54
+ * @param delay optional time to wait for BoundedFetchRequest or BoundedFetchRequest updates
53
55
  */
54
56
  put: function (changeNumber, segmentsData, delay) {
55
- if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber)
57
+ // Ignore event if it is outdated or if there is a pending fetch request (_delay is set)
58
+ if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber || _delay)
56
59
  return;
57
60
  maxChangeNumber = changeNumber;
58
61
  handleNewEvent = true;
@@ -64,6 +67,7 @@ export function MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker, upd
64
67
  },
65
68
  stop: function () {
66
69
  clearTimeout(_delayTimeoutID);
70
+ _delay = undefined;
67
71
  isHandlingEvent = false;
68
72
  backoff.reset();
69
73
  }