@atlaskit/editor-synced-block-provider 8.1.9 → 8.1.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.
- package/CHANGELOG.md +11 -0
- package/dist/cjs/store-manager/syncBlockSubscriptionManager.js +46 -11
- package/dist/es2019/store-manager/syncBlockSubscriptionManager.js +41 -11
- package/dist/esm/store-manager/syncBlockSubscriptionManager.js +46 -11
- package/dist/types/store-manager/syncBlockSubscriptionManager.d.ts +4 -5
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @atlaskit/editor-synced-block-provider
|
|
2
2
|
|
|
3
|
+
## 8.1.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`b4cfc35a62476`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/b4cfc35a62476) -
|
|
8
|
+
Improve the reliability of synced-block real-time updates. Transient WebSocket drops now recover
|
|
9
|
+
silently via a more resilient reconnection strategy (more retry attempts, capped exponential
|
|
10
|
+
backoff with jitter) instead of being reported as failures. A failure is only surfaced once
|
|
11
|
+
reconnection is genuinely exhausted. Behind a feature gate.
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
|
|
3
14
|
## 8.1.9
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -37,6 +37,7 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
37
37
|
// causing the cache to be deleted prematurely. We delay deletion to allow
|
|
38
38
|
// the new component to subscribe and cancel the pending deletion.
|
|
39
39
|
(0, _defineProperty2.default)(this, "pendingCacheDeletions", new Map());
|
|
40
|
+
// backoff cap (gate ON)
|
|
40
41
|
(0, _defineProperty2.default)(this, "retryAttempts", new Map());
|
|
41
42
|
(0, _defineProperty2.default)(this, "pendingRetries", new Map());
|
|
42
43
|
this.deps = deps;
|
|
@@ -47,6 +48,30 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
47
48
|
* that need to read the current subscription state.
|
|
48
49
|
*/
|
|
49
50
|
return (0, _createClass2.default)(SyncBlockSubscriptionManager, [{
|
|
51
|
+
key: "getMaxRetryAttempts",
|
|
52
|
+
value:
|
|
53
|
+
// EDITOR-7861: higher ceiling lets transient WS-gateway drops self-heal
|
|
54
|
+
// before a terminal failure is surfaced.
|
|
55
|
+
function getMaxRetryAttempts() {
|
|
56
|
+
return (0, _platformFeatureFlags.fg)('platform_editor_blocks_patch_3') ? SyncBlockSubscriptionManager.MAX_RETRY_ATTEMPTS_HARDENED : SyncBlockSubscriptionManager.MAX_RETRY_ATTEMPTS;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Backoff delay for the given attempt.
|
|
60
|
+
// Gate OFF: pure exponential (1s, 2s, 4s, 8s, 16s).
|
|
61
|
+
// Gate ON (EDITOR-7861): exponential capped at MAX_RETRY_DELAY_MS with equal
|
|
62
|
+
// jitter (capped/2 + random*capped/2) — de-synchronises simultaneous
|
|
63
|
+
// reconnects while guaranteeing a non-zero delay (full jitter could hit 0).
|
|
64
|
+
}, {
|
|
65
|
+
key: "getReconnectionDelay",
|
|
66
|
+
value: function getReconnectionDelay(attempts) {
|
|
67
|
+
var exponential = SyncBlockSubscriptionManager.INITIAL_RETRY_DELAY_MS * Math.pow(SyncBlockSubscriptionManager.RETRY_BACKOFF_MULTIPLIER, attempts);
|
|
68
|
+
if (!(0, _platformFeatureFlags.fg)('platform_editor_blocks_patch_3')) {
|
|
69
|
+
return exponential;
|
|
70
|
+
}
|
|
71
|
+
var half = Math.min(exponential, SyncBlockSubscriptionManager.MAX_RETRY_DELAY_MS) / 2;
|
|
72
|
+
return Math.round(half + Math.random() * half);
|
|
73
|
+
}
|
|
74
|
+
}, {
|
|
50
75
|
key: "getSubscriptions",
|
|
51
76
|
value: function getSubscriptions() {
|
|
52
77
|
return this.subscriptions;
|
|
@@ -273,11 +298,17 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
273
298
|
var unsubscribe = dataProvider.subscribeToBlockUpdates(resourceId, function (syncBlockInstance) {
|
|
274
299
|
_this5.handleGraphQLUpdate(syncBlockInstance);
|
|
275
300
|
}, function (error) {
|
|
276
|
-
var _this5$deps$getFireAn;
|
|
277
301
|
(0, _monitoring.logException)(error, {
|
|
278
302
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/graphql-subscription'
|
|
279
303
|
});
|
|
280
|
-
|
|
304
|
+
// EDITOR-7861: a single socket drop is usually transient and
|
|
305
|
+
// recovers on reconnect, so under the gate we don't fire a
|
|
306
|
+
// user-facing error here — it's only surfaced on exhaustion (see
|
|
307
|
+
// scheduleReconnection). Gate OFF keeps the legacy fire-on-drop.
|
|
308
|
+
if (!(0, _platformFeatureFlags.fg)('platform_editor_blocks_patch_3')) {
|
|
309
|
+
var _this5$deps$getFireAn;
|
|
310
|
+
(_this5$deps$getFireAn = _this5.deps.getFireAnalyticsEvent()) === null || _this5$deps$getFireAn === void 0 || _this5$deps$getFireAn((0, _errorHandling.fetchErrorPayload)(error.message, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId)));
|
|
311
|
+
}
|
|
281
312
|
_this5.handleSubscriptionTerminated(resourceId);
|
|
282
313
|
}, function () {
|
|
283
314
|
_this5.handleSubscriptionTerminated(resourceId);
|
|
@@ -308,19 +339,19 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
308
339
|
}
|
|
309
340
|
}
|
|
310
341
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
* Delay = INITIAL_RETRY_DELAY_MS * (RETRY_BACKOFF_MULTIPLIER ^ attempts)
|
|
314
|
-
* e.g. 1s, 2s, 4s, 8s, 16s
|
|
315
|
-
*/
|
|
342
|
+
// Schedules a reconnection with backoff (see getMaxRetryAttempts /
|
|
343
|
+
// getReconnectionDelay for the gated behaviour).
|
|
316
344
|
}, {
|
|
317
345
|
key: "scheduleReconnection",
|
|
318
346
|
value: function scheduleReconnection(resourceId) {
|
|
319
347
|
var _this$retryAttempts$g,
|
|
320
348
|
_this6 = this;
|
|
321
349
|
var attempts = (_this$retryAttempts$g = this.retryAttempts.get(resourceId)) !== null && _this$retryAttempts$g !== void 0 ? _this$retryAttempts$g : 0;
|
|
322
|
-
|
|
350
|
+
var maxAttempts = this.getMaxRetryAttempts();
|
|
351
|
+
if (attempts >= maxAttempts) {
|
|
323
352
|
var _this$deps$getFireAna;
|
|
353
|
+
// Exhausted all attempts — the only place a WS drop surfaces as a
|
|
354
|
+
// fetch error under the gate (EDITOR-7861).
|
|
324
355
|
var errorMessage = "Subscription reconnection failed after ".concat(attempts, " attempts");
|
|
325
356
|
(0, _monitoring.logException)(new Error(errorMessage), {
|
|
326
357
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/max-retries-exhausted'
|
|
@@ -328,7 +359,7 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
328
359
|
(_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 || _this$deps$getFireAna((0, _errorHandling.fetchErrorPayload)(errorMessage, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId)));
|
|
329
360
|
return;
|
|
330
361
|
}
|
|
331
|
-
var delay =
|
|
362
|
+
var delay = this.getReconnectionDelay(attempts);
|
|
332
363
|
var timer = setTimeout(function () {
|
|
333
364
|
_this6.pendingRetries.delete(resourceId);
|
|
334
365
|
|
|
@@ -486,7 +517,11 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
486
517
|
}
|
|
487
518
|
}]);
|
|
488
519
|
}();
|
|
489
|
-
// Reconnection with exponential backoff
|
|
520
|
+
// Reconnection with exponential backoff.
|
|
490
521
|
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "INITIAL_RETRY_DELAY_MS", 1000);
|
|
491
522
|
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "RETRY_BACKOFF_MULTIPLIER", 2);
|
|
492
|
-
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS", 5);
|
|
523
|
+
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS", 5);
|
|
524
|
+
// legacy (gate OFF)
|
|
525
|
+
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS_HARDENED", 8);
|
|
526
|
+
// gate ON (EDITOR-7861)
|
|
527
|
+
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "MAX_RETRY_DELAY_MS", 30000);
|
|
@@ -12,6 +12,25 @@ import { getSourceProductFromResourceIdSafe } from '../utils/utils';
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
export class SyncBlockSubscriptionManager {
|
|
15
|
+
// EDITOR-7861: higher ceiling lets transient WS-gateway drops self-heal
|
|
16
|
+
// before a terminal failure is surfaced.
|
|
17
|
+
getMaxRetryAttempts() {
|
|
18
|
+
return fg('platform_editor_blocks_patch_3') ? SyncBlockSubscriptionManager.MAX_RETRY_ATTEMPTS_HARDENED : SyncBlockSubscriptionManager.MAX_RETRY_ATTEMPTS;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Backoff delay for the given attempt.
|
|
22
|
+
// Gate OFF: pure exponential (1s, 2s, 4s, 8s, 16s).
|
|
23
|
+
// Gate ON (EDITOR-7861): exponential capped at MAX_RETRY_DELAY_MS with equal
|
|
24
|
+
// jitter (capped/2 + random*capped/2) — de-synchronises simultaneous
|
|
25
|
+
// reconnects while guaranteeing a non-zero delay (full jitter could hit 0).
|
|
26
|
+
getReconnectionDelay(attempts) {
|
|
27
|
+
const exponential = SyncBlockSubscriptionManager.INITIAL_RETRY_DELAY_MS * Math.pow(SyncBlockSubscriptionManager.RETRY_BACKOFF_MULTIPLIER, attempts);
|
|
28
|
+
if (!fg('platform_editor_blocks_patch_3')) {
|
|
29
|
+
return exponential;
|
|
30
|
+
}
|
|
31
|
+
const half = Math.min(exponential, SyncBlockSubscriptionManager.MAX_RETRY_DELAY_MS) / 2;
|
|
32
|
+
return Math.round(half + Math.random() * half);
|
|
33
|
+
}
|
|
15
34
|
constructor(deps) {
|
|
16
35
|
_defineProperty(this, "subscriptions", new Map());
|
|
17
36
|
_defineProperty(this, "titleSubscriptions", new Map());
|
|
@@ -23,6 +42,7 @@ export class SyncBlockSubscriptionManager {
|
|
|
23
42
|
// causing the cache to be deleted prematurely. We delay deletion to allow
|
|
24
43
|
// the new component to subscribe and cancel the pending deletion.
|
|
25
44
|
_defineProperty(this, "pendingCacheDeletions", new Map());
|
|
45
|
+
// backoff cap (gate ON)
|
|
26
46
|
_defineProperty(this, "retryAttempts", new Map());
|
|
27
47
|
_defineProperty(this, "pendingRetries", new Map());
|
|
28
48
|
this.deps = deps;
|
|
@@ -237,11 +257,17 @@ export class SyncBlockSubscriptionManager {
|
|
|
237
257
|
const unsubscribe = dataProvider.subscribeToBlockUpdates(resourceId, syncBlockInstance => {
|
|
238
258
|
this.handleGraphQLUpdate(syncBlockInstance);
|
|
239
259
|
}, error => {
|
|
240
|
-
var _this$deps$getFireAna2;
|
|
241
260
|
logException(error, {
|
|
242
261
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/graphql-subscription'
|
|
243
262
|
});
|
|
244
|
-
|
|
263
|
+
// EDITOR-7861: a single socket drop is usually transient and
|
|
264
|
+
// recovers on reconnect, so under the gate we don't fire a
|
|
265
|
+
// user-facing error here — it's only surfaced on exhaustion (see
|
|
266
|
+
// scheduleReconnection). Gate OFF keeps the legacy fire-on-drop.
|
|
267
|
+
if (!fg('platform_editor_blocks_patch_3')) {
|
|
268
|
+
var _this$deps$getFireAna2;
|
|
269
|
+
(_this$deps$getFireAna2 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna2 === void 0 ? void 0 : _this$deps$getFireAna2(fetchErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
270
|
+
}
|
|
245
271
|
this.handleSubscriptionTerminated(resourceId);
|
|
246
272
|
}, () => {
|
|
247
273
|
this.handleSubscriptionTerminated(resourceId);
|
|
@@ -270,16 +296,16 @@ export class SyncBlockSubscriptionManager {
|
|
|
270
296
|
}
|
|
271
297
|
}
|
|
272
298
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
* Delay = INITIAL_RETRY_DELAY_MS * (RETRY_BACKOFF_MULTIPLIER ^ attempts)
|
|
276
|
-
* e.g. 1s, 2s, 4s, 8s, 16s
|
|
277
|
-
*/
|
|
299
|
+
// Schedules a reconnection with backoff (see getMaxRetryAttempts /
|
|
300
|
+
// getReconnectionDelay for the gated behaviour).
|
|
278
301
|
scheduleReconnection(resourceId) {
|
|
279
302
|
var _this$retryAttempts$g;
|
|
280
303
|
const attempts = (_this$retryAttempts$g = this.retryAttempts.get(resourceId)) !== null && _this$retryAttempts$g !== void 0 ? _this$retryAttempts$g : 0;
|
|
281
|
-
|
|
304
|
+
const maxAttempts = this.getMaxRetryAttempts();
|
|
305
|
+
if (attempts >= maxAttempts) {
|
|
282
306
|
var _this$deps$getFireAna3;
|
|
307
|
+
// Exhausted all attempts — the only place a WS drop surfaces as a
|
|
308
|
+
// fetch error under the gate (EDITOR-7861).
|
|
283
309
|
const errorMessage = `Subscription reconnection failed after ${attempts} attempts`;
|
|
284
310
|
logException(new Error(errorMessage), {
|
|
285
311
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/max-retries-exhausted'
|
|
@@ -287,7 +313,7 @@ export class SyncBlockSubscriptionManager {
|
|
|
287
313
|
(_this$deps$getFireAna3 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna3 === void 0 ? void 0 : _this$deps$getFireAna3(fetchErrorPayload(errorMessage, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
288
314
|
return;
|
|
289
315
|
}
|
|
290
|
-
const delay =
|
|
316
|
+
const delay = this.getReconnectionDelay(attempts);
|
|
291
317
|
const timer = setTimeout(() => {
|
|
292
318
|
this.pendingRetries.delete(resourceId);
|
|
293
319
|
|
|
@@ -389,7 +415,11 @@ export class SyncBlockSubscriptionManager {
|
|
|
389
415
|
}
|
|
390
416
|
}
|
|
391
417
|
}
|
|
392
|
-
// Reconnection with exponential backoff
|
|
418
|
+
// Reconnection with exponential backoff.
|
|
393
419
|
_defineProperty(SyncBlockSubscriptionManager, "INITIAL_RETRY_DELAY_MS", 1000);
|
|
394
420
|
_defineProperty(SyncBlockSubscriptionManager, "RETRY_BACKOFF_MULTIPLIER", 2);
|
|
395
|
-
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS", 5);
|
|
421
|
+
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS", 5);
|
|
422
|
+
// legacy (gate OFF)
|
|
423
|
+
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS_HARDENED", 8);
|
|
424
|
+
// gate ON (EDITOR-7861)
|
|
425
|
+
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_DELAY_MS", 30000);
|
|
@@ -31,6 +31,7 @@ export var SyncBlockSubscriptionManager = /*#__PURE__*/function () {
|
|
|
31
31
|
// causing the cache to be deleted prematurely. We delay deletion to allow
|
|
32
32
|
// the new component to subscribe and cancel the pending deletion.
|
|
33
33
|
_defineProperty(this, "pendingCacheDeletions", new Map());
|
|
34
|
+
// backoff cap (gate ON)
|
|
34
35
|
_defineProperty(this, "retryAttempts", new Map());
|
|
35
36
|
_defineProperty(this, "pendingRetries", new Map());
|
|
36
37
|
this.deps = deps;
|
|
@@ -41,6 +42,30 @@ export var SyncBlockSubscriptionManager = /*#__PURE__*/function () {
|
|
|
41
42
|
* that need to read the current subscription state.
|
|
42
43
|
*/
|
|
43
44
|
return _createClass(SyncBlockSubscriptionManager, [{
|
|
45
|
+
key: "getMaxRetryAttempts",
|
|
46
|
+
value:
|
|
47
|
+
// EDITOR-7861: higher ceiling lets transient WS-gateway drops self-heal
|
|
48
|
+
// before a terminal failure is surfaced.
|
|
49
|
+
function getMaxRetryAttempts() {
|
|
50
|
+
return fg('platform_editor_blocks_patch_3') ? SyncBlockSubscriptionManager.MAX_RETRY_ATTEMPTS_HARDENED : SyncBlockSubscriptionManager.MAX_RETRY_ATTEMPTS;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Backoff delay for the given attempt.
|
|
54
|
+
// Gate OFF: pure exponential (1s, 2s, 4s, 8s, 16s).
|
|
55
|
+
// Gate ON (EDITOR-7861): exponential capped at MAX_RETRY_DELAY_MS with equal
|
|
56
|
+
// jitter (capped/2 + random*capped/2) — de-synchronises simultaneous
|
|
57
|
+
// reconnects while guaranteeing a non-zero delay (full jitter could hit 0).
|
|
58
|
+
}, {
|
|
59
|
+
key: "getReconnectionDelay",
|
|
60
|
+
value: function getReconnectionDelay(attempts) {
|
|
61
|
+
var exponential = SyncBlockSubscriptionManager.INITIAL_RETRY_DELAY_MS * Math.pow(SyncBlockSubscriptionManager.RETRY_BACKOFF_MULTIPLIER, attempts);
|
|
62
|
+
if (!fg('platform_editor_blocks_patch_3')) {
|
|
63
|
+
return exponential;
|
|
64
|
+
}
|
|
65
|
+
var half = Math.min(exponential, SyncBlockSubscriptionManager.MAX_RETRY_DELAY_MS) / 2;
|
|
66
|
+
return Math.round(half + Math.random() * half);
|
|
67
|
+
}
|
|
68
|
+
}, {
|
|
44
69
|
key: "getSubscriptions",
|
|
45
70
|
value: function getSubscriptions() {
|
|
46
71
|
return this.subscriptions;
|
|
@@ -267,11 +292,17 @@ export var SyncBlockSubscriptionManager = /*#__PURE__*/function () {
|
|
|
267
292
|
var unsubscribe = dataProvider.subscribeToBlockUpdates(resourceId, function (syncBlockInstance) {
|
|
268
293
|
_this5.handleGraphQLUpdate(syncBlockInstance);
|
|
269
294
|
}, function (error) {
|
|
270
|
-
var _this5$deps$getFireAn;
|
|
271
295
|
logException(error, {
|
|
272
296
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/graphql-subscription'
|
|
273
297
|
});
|
|
274
|
-
|
|
298
|
+
// EDITOR-7861: a single socket drop is usually transient and
|
|
299
|
+
// recovers on reconnect, so under the gate we don't fire a
|
|
300
|
+
// user-facing error here — it's only surfaced on exhaustion (see
|
|
301
|
+
// scheduleReconnection). Gate OFF keeps the legacy fire-on-drop.
|
|
302
|
+
if (!fg('platform_editor_blocks_patch_3')) {
|
|
303
|
+
var _this5$deps$getFireAn;
|
|
304
|
+
(_this5$deps$getFireAn = _this5.deps.getFireAnalyticsEvent()) === null || _this5$deps$getFireAn === void 0 || _this5$deps$getFireAn(fetchErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
305
|
+
}
|
|
275
306
|
_this5.handleSubscriptionTerminated(resourceId);
|
|
276
307
|
}, function () {
|
|
277
308
|
_this5.handleSubscriptionTerminated(resourceId);
|
|
@@ -302,19 +333,19 @@ export var SyncBlockSubscriptionManager = /*#__PURE__*/function () {
|
|
|
302
333
|
}
|
|
303
334
|
}
|
|
304
335
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
* Delay = INITIAL_RETRY_DELAY_MS * (RETRY_BACKOFF_MULTIPLIER ^ attempts)
|
|
308
|
-
* e.g. 1s, 2s, 4s, 8s, 16s
|
|
309
|
-
*/
|
|
336
|
+
// Schedules a reconnection with backoff (see getMaxRetryAttempts /
|
|
337
|
+
// getReconnectionDelay for the gated behaviour).
|
|
310
338
|
}, {
|
|
311
339
|
key: "scheduleReconnection",
|
|
312
340
|
value: function scheduleReconnection(resourceId) {
|
|
313
341
|
var _this$retryAttempts$g,
|
|
314
342
|
_this6 = this;
|
|
315
343
|
var attempts = (_this$retryAttempts$g = this.retryAttempts.get(resourceId)) !== null && _this$retryAttempts$g !== void 0 ? _this$retryAttempts$g : 0;
|
|
316
|
-
|
|
344
|
+
var maxAttempts = this.getMaxRetryAttempts();
|
|
345
|
+
if (attempts >= maxAttempts) {
|
|
317
346
|
var _this$deps$getFireAna;
|
|
347
|
+
// Exhausted all attempts — the only place a WS drop surfaces as a
|
|
348
|
+
// fetch error under the gate (EDITOR-7861).
|
|
318
349
|
var errorMessage = "Subscription reconnection failed after ".concat(attempts, " attempts");
|
|
319
350
|
logException(new Error(errorMessage), {
|
|
320
351
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/max-retries-exhausted'
|
|
@@ -322,7 +353,7 @@ export var SyncBlockSubscriptionManager = /*#__PURE__*/function () {
|
|
|
322
353
|
(_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 || _this$deps$getFireAna(fetchErrorPayload(errorMessage, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
323
354
|
return;
|
|
324
355
|
}
|
|
325
|
-
var delay =
|
|
356
|
+
var delay = this.getReconnectionDelay(attempts);
|
|
326
357
|
var timer = setTimeout(function () {
|
|
327
358
|
_this6.pendingRetries.delete(resourceId);
|
|
328
359
|
|
|
@@ -480,7 +511,11 @@ export var SyncBlockSubscriptionManager = /*#__PURE__*/function () {
|
|
|
480
511
|
}
|
|
481
512
|
}]);
|
|
482
513
|
}();
|
|
483
|
-
// Reconnection with exponential backoff
|
|
514
|
+
// Reconnection with exponential backoff.
|
|
484
515
|
_defineProperty(SyncBlockSubscriptionManager, "INITIAL_RETRY_DELAY_MS", 1000);
|
|
485
516
|
_defineProperty(SyncBlockSubscriptionManager, "RETRY_BACKOFF_MULTIPLIER", 2);
|
|
486
|
-
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS", 5);
|
|
517
|
+
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS", 5);
|
|
518
|
+
// legacy (gate OFF)
|
|
519
|
+
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS_HARDENED", 8);
|
|
520
|
+
// gate ON (EDITOR-7861)
|
|
521
|
+
_defineProperty(SyncBlockSubscriptionManager, "MAX_RETRY_DELAY_MS", 30000);
|
|
@@ -33,8 +33,12 @@ export declare class SyncBlockSubscriptionManager {
|
|
|
33
33
|
private static readonly INITIAL_RETRY_DELAY_MS;
|
|
34
34
|
private static readonly RETRY_BACKOFF_MULTIPLIER;
|
|
35
35
|
private static readonly MAX_RETRY_ATTEMPTS;
|
|
36
|
+
private static readonly MAX_RETRY_ATTEMPTS_HARDENED;
|
|
37
|
+
private static readonly MAX_RETRY_DELAY_MS;
|
|
36
38
|
private retryAttempts;
|
|
37
39
|
private pendingRetries;
|
|
40
|
+
private getMaxRetryAttempts;
|
|
41
|
+
private getReconnectionDelay;
|
|
38
42
|
constructor(deps: SyncBlockSubscriptionManagerDeps);
|
|
39
43
|
/**
|
|
40
44
|
* Returns the subscriptions map. Used by external consumers (e.g. batch fetcher, flush)
|
|
@@ -62,11 +66,6 @@ export declare class SyncBlockSubscriptionManager {
|
|
|
62
66
|
* stale entry and scheduling a reconnection with exponential backoff.
|
|
63
67
|
*/
|
|
64
68
|
private handleSubscriptionTerminated;
|
|
65
|
-
/**
|
|
66
|
-
* Schedules a reconnection attempt with exponential backoff.
|
|
67
|
-
* Delay = INITIAL_RETRY_DELAY_MS * (RETRY_BACKOFF_MULTIPLIER ^ attempts)
|
|
68
|
-
* e.g. 1s, 2s, 4s, 8s, 16s
|
|
69
|
-
*/
|
|
70
69
|
private scheduleReconnection;
|
|
71
70
|
/**
|
|
72
71
|
* Resets the retry counter for a resource. Called when a successful
|
package/package.json
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"uuid": "^3.1.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@atlaskit/editor-common": "^116.
|
|
33
|
+
"@atlaskit/editor-common": "^116.14.0",
|
|
34
34
|
"react": "^18.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
"name": "@atlaskit/editor-synced-block-provider",
|
|
77
|
-
"version": "8.1.
|
|
77
|
+
"version": "8.1.10",
|
|
78
78
|
"description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
|
|
79
79
|
"author": "Atlassian Pty Ltd",
|
|
80
80
|
"license": "Apache-2.0",
|