@atlaskit/editor-synced-block-provider 10.0.3 → 10.0.5
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 +17 -0
- package/dist/cjs/common/types.js +2 -3
- package/dist/cjs/hooks/useFetchSyncBlockData.js +4 -4
- package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +27 -56
- package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +22 -41
- package/dist/cjs/store-manager/syncBlockBatchFetcher.js +6 -12
- package/dist/cjs/store-manager/syncBlockProviderFactoryManager.js +3 -3
- package/dist/cjs/store-manager/syncBlockStoreManager.js +1 -5
- package/dist/cjs/store-manager/syncBlockSubscriptionManager.js +20 -85
- package/dist/cjs/utils/errorHandling.js +13 -32
- package/dist/es2019/common/types.js +2 -3
- package/dist/es2019/hooks/useFetchSyncBlockData.js +4 -5
- package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +26 -50
- package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +23 -42
- package/dist/es2019/store-manager/syncBlockBatchFetcher.js +6 -12
- package/dist/es2019/store-manager/syncBlockProviderFactoryManager.js +3 -3
- package/dist/es2019/store-manager/syncBlockStoreManager.js +1 -5
- package/dist/es2019/store-manager/syncBlockSubscriptionManager.js +25 -81
- package/dist/es2019/utils/errorHandling.js +13 -32
- package/dist/esm/common/types.js +2 -3
- package/dist/esm/hooks/useFetchSyncBlockData.js +4 -4
- package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +27 -56
- package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +22 -41
- package/dist/esm/store-manager/syncBlockBatchFetcher.js +6 -12
- package/dist/esm/store-manager/syncBlockProviderFactoryManager.js +3 -3
- package/dist/esm/store-manager/syncBlockStoreManager.js +1 -5
- package/dist/esm/store-manager/syncBlockSubscriptionManager.js +20 -85
- package/dist/esm/utils/errorHandling.js +13 -32
- package/dist/types/common/types.d.ts +2 -3
- package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +3 -3
- package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +5 -7
- package/dist/types/store-manager/syncBlockSubscriptionManager.d.ts +2 -5
- package/dist/types/utils/errorHandling.d.ts +11 -24
- package/package.json +3 -15
|
@@ -12,7 +12,6 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
|
|
|
12
12
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
13
13
|
var _react = require("react");
|
|
14
14
|
var _monitoring = require("@atlaskit/editor-common/monitoring");
|
|
15
|
-
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
16
15
|
var _ari = require("../clients/block-service/ari");
|
|
17
16
|
var _types = require("../common/types");
|
|
18
17
|
var _errorHandling = require("../utils/errorHandling");
|
|
@@ -308,7 +307,6 @@ var useMemoizedSyncBlockStoreManager = exports.useMemoizedSyncBlockStoreManager
|
|
|
308
307
|
syncBlockStoreManager.setFireAnalyticsEvent(fireAnalyticsEvent);
|
|
309
308
|
}
|
|
310
309
|
|
|
311
|
-
// Gated by platform_synced_block_patch_14:
|
|
312
310
|
// Destroy the SyncBlockStoreManager when:
|
|
313
311
|
// (a) the component unmounts — manager is fully cleaned up, or
|
|
314
312
|
// (b) dataProvider changes — the old manager (now orphaned by the
|
|
@@ -320,9 +318,7 @@ var useMemoizedSyncBlockStoreManager = exports.useMemoizedSyncBlockStoreManager
|
|
|
320
318
|
// changes, triggering the cleanup for the old instance.
|
|
321
319
|
(0, _react.useEffect)(function () {
|
|
322
320
|
return function () {
|
|
323
|
-
|
|
324
|
-
syncBlockStoreManager.destroy();
|
|
325
|
-
}
|
|
321
|
+
syncBlockStoreManager.destroy();
|
|
326
322
|
};
|
|
327
323
|
}, [syncBlockStoreManager]);
|
|
328
324
|
return syncBlockStoreManager;
|
|
@@ -11,7 +11,6 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
|
|
|
11
11
|
var _bindEventListener = require("bind-event-listener");
|
|
12
12
|
var _browserApis = require("@atlaskit/browser-apis");
|
|
13
13
|
var _monitoring = require("@atlaskit/editor-common/monitoring");
|
|
14
|
-
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
15
14
|
var _errorHandling = require("../utils/errorHandling");
|
|
16
15
|
var _resolveSyncBlockInstance = require("../utils/resolveSyncBlockInstance");
|
|
17
16
|
var _utils = require("../utils/utils");
|
|
@@ -35,12 +34,7 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
35
34
|
(0, _defineProperty2.default)(this, "graphqlSubscriptions", new Map());
|
|
36
35
|
(0, _defineProperty2.default)(this, "subscriptionChangeListeners", new Set());
|
|
37
36
|
(0, _defineProperty2.default)(this, "useRealTimeSubscriptions", false);
|
|
38
|
-
//
|
|
39
|
-
// When a block is moved, the old component unmounts before the new one mounts,
|
|
40
|
-
// causing the cache to be deleted prematurely. We delay deletion to allow
|
|
41
|
-
// the new component to subscribe and cancel the pending deletion.
|
|
42
|
-
(0, _defineProperty2.default)(this, "pendingCacheDeletions", new Map());
|
|
43
|
-
// backoff cap (gate ON)
|
|
37
|
+
// backoff cap
|
|
44
38
|
(0, _defineProperty2.default)(this, "retryAttempts", new Map());
|
|
45
39
|
(0, _defineProperty2.default)(this, "pendingRetries", new Map());
|
|
46
40
|
// Resources whose reconnection exhausted while the tab was hidden: parked here and
|
|
@@ -74,21 +68,17 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
74
68
|
// EDITOR-7861: higher ceiling lets transient WS-gateway drops self-heal
|
|
75
69
|
// before a terminal failure is surfaced.
|
|
76
70
|
function getMaxRetryAttempts() {
|
|
77
|
-
return
|
|
71
|
+
return SyncBlockSubscriptionManager.MAX_RETRY_ATTEMPTS_HARDENED;
|
|
78
72
|
}
|
|
79
73
|
|
|
80
|
-
// Backoff delay for the given attempt
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
// jitter
|
|
84
|
-
// reconnects while guaranteeing a non-zero delay (full jitter could hit 0).
|
|
74
|
+
// Backoff delay for the given attempt (EDITOR-7861): exponential capped at
|
|
75
|
+
// MAX_RETRY_DELAY_MS with equal jitter (capped/2 + random*capped/2) —
|
|
76
|
+
// de-synchronises simultaneous reconnects while guaranteeing a non-zero delay
|
|
77
|
+
// (full jitter could hit 0).
|
|
85
78
|
}, {
|
|
86
79
|
key: "getReconnectionDelay",
|
|
87
80
|
value: function getReconnectionDelay(attempts) {
|
|
88
81
|
var exponential = SyncBlockSubscriptionManager.INITIAL_RETRY_DELAY_MS * Math.pow(SyncBlockSubscriptionManager.RETRY_BACKOFF_MULTIPLIER, attempts);
|
|
89
|
-
if (!(0, _platformFeatureFlags.fg)('platform_editor_blocks_patch_3')) {
|
|
90
|
-
return exponential;
|
|
91
|
-
}
|
|
92
82
|
var half = Math.min(exponential, SyncBlockSubscriptionManager.MAX_RETRY_DELAY_MS) / 2;
|
|
93
83
|
return Math.round(half + Math.random() * half);
|
|
94
84
|
}
|
|
@@ -141,7 +131,7 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
141
131
|
(0, _monitoring.logException)(error, {
|
|
142
132
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/notifySubscriptionChangeListeners'
|
|
143
133
|
});
|
|
144
|
-
(_this3$deps$getFireAn = _this3.deps.getFireAnalyticsEvent()) === null || _this3$deps$getFireAn === void 0 || _this3$deps$getFireAn((0, _errorHandling.fetchErrorPayload)(error.message, undefined, undefined, (0, _errorHandling.buildFetchErrorAttribution)(
|
|
134
|
+
(_this3$deps$getFireAn = _this3.deps.getFireAnalyticsEvent()) === null || _this3$deps$getFireAn === void 0 || _this3$deps$getFireAn((0, _errorHandling.fetchErrorPayload)(error.message, undefined, undefined, (0, _errorHandling.buildFetchErrorAttribution)(error.message)));
|
|
145
135
|
}
|
|
146
136
|
});
|
|
147
137
|
}
|
|
@@ -166,16 +156,7 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
166
156
|
// This handles the case where a block is moved - the old component unmounts
|
|
167
157
|
// (scheduling deletion) but the new component mounts and subscribes before
|
|
168
158
|
// the deletion timeout fires.
|
|
169
|
-
|
|
170
|
-
// Under the flag, cache deletion is owned by the store manager.
|
|
171
|
-
// With the flag off, the legacy 1s timer path is preserved.
|
|
172
|
-
var pendingDeletion = this.pendingCacheDeletions.get(resourceId);
|
|
173
|
-
if ((0, _platformFeatureFlags.fg)('platform_synced_block_patch_14')) {
|
|
174
|
-
this.deps.cancelPendingCacheDeletion(resourceId);
|
|
175
|
-
} else if (pendingDeletion) {
|
|
176
|
-
clearTimeout(pendingDeletion);
|
|
177
|
-
this.pendingCacheDeletions.delete(resourceId);
|
|
178
|
-
}
|
|
159
|
+
this.deps.cancelPendingCacheDeletion(resourceId);
|
|
179
160
|
|
|
180
161
|
// add to subscriptions map
|
|
181
162
|
var resourceSubscriptions = this.subscriptions.get(resourceId) || {};
|
|
@@ -216,30 +197,9 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
216
197
|
// Notify listeners that subscription was removed
|
|
217
198
|
_this4.notifySubscriptionChangeListeners();
|
|
218
199
|
|
|
219
|
-
//
|
|
200
|
+
// Delegate cache deletion to the store manager
|
|
220
201
|
// which uses a 30s grace period with guard re-checks.
|
|
221
|
-
|
|
222
|
-
_this4.deps.scheduleCacheDeletion(resourceId);
|
|
223
|
-
} else {
|
|
224
|
-
// Legacy path (unchanged): delay cache deletion to handle
|
|
225
|
-
// block moves (unmount/remount). When a block is moved, the
|
|
226
|
-
// old component unmounts before the new one mounts. By
|
|
227
|
-
// delaying deletion, we give the new component time to
|
|
228
|
-
// subscribe and cancel this pending deletion, preserving
|
|
229
|
-
// the cached data.
|
|
230
|
-
// TODO: EDITOR-4152 - Rework this logic (superseded by
|
|
231
|
-
// `platform_synced_block_patch_14`).
|
|
232
|
-
var deletionTimeout = setTimeout(function () {
|
|
233
|
-
var hasSubscribers = _this4.subscriptions.has(resourceId);
|
|
234
|
-
|
|
235
|
-
// Only delete if still no subscribers (wasn't re-subscribed)
|
|
236
|
-
if (!hasSubscribers) {
|
|
237
|
-
_this4.deps.deleteFromCache(resourceId);
|
|
238
|
-
}
|
|
239
|
-
_this4.pendingCacheDeletions.delete(resourceId);
|
|
240
|
-
}, 1000);
|
|
241
|
-
_this4.pendingCacheDeletions.set(resourceId, deletionTimeout);
|
|
242
|
-
}
|
|
202
|
+
_this4.deps.scheduleCacheDeletion(resourceId);
|
|
243
203
|
} else {
|
|
244
204
|
_this4.subscriptions.set(resourceId, resourceSubscriptions);
|
|
245
205
|
}
|
|
@@ -322,17 +282,10 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
322
282
|
(0, _monitoring.logException)(error, {
|
|
323
283
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/graphql-subscription'
|
|
324
284
|
});
|
|
325
|
-
// EDITOR-7861: a single socket drop is usually transient and
|
|
326
|
-
//
|
|
327
|
-
//
|
|
328
|
-
//
|
|
329
|
-
// This branch only runs when the gate is OFF, so buildFetchErrorAttribution
|
|
330
|
-
// would return undefined; the structured attribution (EDITOR-7862) is therefore
|
|
331
|
-
// applied at the gate-ON exhaustion site in scheduleReconnection instead.
|
|
332
|
-
if (!(0, _platformFeatureFlags.fg)('platform_editor_blocks_patch_3')) {
|
|
333
|
-
var _this6$deps$getFireAn;
|
|
334
|
-
(_this6$deps$getFireAn = _this6.deps.getFireAnalyticsEvent()) === null || _this6$deps$getFireAn === void 0 || _this6$deps$getFireAn((0, _errorHandling.fetchErrorPayload)(error.message, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId)));
|
|
335
|
-
}
|
|
285
|
+
// EDITOR-7861: a single socket drop is usually transient and recovers
|
|
286
|
+
// on reconnect, so we don't fire a user-facing error here — it's only
|
|
287
|
+
// surfaced on exhaustion, where the structured attribution
|
|
288
|
+
// (EDITOR-7862) is applied too. See scheduleReconnection.
|
|
336
289
|
_this6.handleSubscriptionTerminated(resourceId);
|
|
337
290
|
}, function () {
|
|
338
291
|
_this6.handleSubscriptionTerminated(resourceId);
|
|
@@ -375,24 +328,23 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
375
328
|
if (attempts >= maxAttempts) {
|
|
376
329
|
var _this$deps$getFireAna2;
|
|
377
330
|
// Exhausted all attempts — the only place a WS drop surfaces as a
|
|
378
|
-
// fetch error
|
|
331
|
+
// fetch error (EDITOR-7861).
|
|
379
332
|
var errorMessage = "Subscription reconnection failed after ".concat(attempts, " attempts");
|
|
380
333
|
|
|
381
334
|
// Tab hidden at exhaustion: don't surface a terminal failure (user isn't
|
|
382
335
|
// looking, and most exhaustions self-recover once foregrounded). Park + re-arm
|
|
383
336
|
// on wake, emitting a benign `deferred` signal so suppression stays auditable.
|
|
384
|
-
|
|
385
|
-
if (shouldDefer) {
|
|
337
|
+
if (this.isDocumentHidden()) {
|
|
386
338
|
var _this$deps$getFireAna;
|
|
387
339
|
this.deferredExhausted.add(resourceId);
|
|
388
340
|
this.registerWakeListeners();
|
|
389
|
-
(_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 || _this$deps$getFireAna((0, _errorHandling.fetchErrorPayload)(errorMessage, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId), (0, _errorHandling.buildFetchErrorAttribution)(
|
|
341
|
+
(_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 || _this$deps$getFireAna((0, _errorHandling.fetchErrorPayload)(errorMessage, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId), (0, _errorHandling.buildFetchErrorAttribution)(errorMessage, undefined, /* deferred */true)));
|
|
390
342
|
return;
|
|
391
343
|
}
|
|
392
344
|
(0, _monitoring.logException)(new Error(errorMessage), {
|
|
393
345
|
location: 'editor-synced-block-provider/syncBlockSubscriptionManager/max-retries-exhausted'
|
|
394
346
|
});
|
|
395
|
-
(_this$deps$getFireAna2 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna2 === void 0 || _this$deps$getFireAna2((0, _errorHandling.fetchErrorPayload)(errorMessage, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId), (0, _errorHandling.buildFetchErrorAttribution)(
|
|
347
|
+
(_this$deps$getFireAna2 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna2 === void 0 || _this$deps$getFireAna2((0, _errorHandling.fetchErrorPayload)(errorMessage, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId), (0, _errorHandling.buildFetchErrorAttribution)(errorMessage)));
|
|
396
348
|
return;
|
|
397
349
|
}
|
|
398
350
|
var delay = this.getReconnectionDelay(attempts);
|
|
@@ -613,21 +565,6 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
613
565
|
this.titleSubscriptions.clear();
|
|
614
566
|
this.subscriptionChangeListeners.clear();
|
|
615
567
|
this.useRealTimeSubscriptions = false;
|
|
616
|
-
|
|
617
|
-
// Clear any pending cache deletions
|
|
618
|
-
var _iterator5 = _createForOfIteratorHelper(this.pendingCacheDeletions.values()),
|
|
619
|
-
_step5;
|
|
620
|
-
try {
|
|
621
|
-
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
622
|
-
var timeout = _step5.value;
|
|
623
|
-
clearTimeout(timeout);
|
|
624
|
-
}
|
|
625
|
-
} catch (err) {
|
|
626
|
-
_iterator5.e(err);
|
|
627
|
-
} finally {
|
|
628
|
-
_iterator5.f();
|
|
629
|
-
}
|
|
630
|
-
this.pendingCacheDeletions.clear();
|
|
631
568
|
}
|
|
632
569
|
}, {
|
|
633
570
|
key: "shouldUseRealTime",
|
|
@@ -667,7 +604,7 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
667
604
|
// Prefer the structured `type` (a `SyncBlockError` enum value) for classification
|
|
668
605
|
// and fall back to the free-text `reason` so source-state/permission strings are
|
|
669
606
|
// still bucketed (EDITOR-7862). The emitted free-text `error` attribute is unchanged.
|
|
670
|
-
(_this$deps$getFireAna3 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna3 === void 0 || _this$deps$getFireAna3((0, _errorHandling.fetchErrorPayload)(errorMessage, syncBlockInstance.resourceId, (_syncBlockInstance$da3 = (_syncBlockInstance$da4 = syncBlockInstance.data) === null || _syncBlockInstance$da4 === void 0 ? void 0 : _syncBlockInstance$da4.product) !== null && _syncBlockInstance$da3 !== void 0 ? _syncBlockInstance$da3 : (0, _utils.getSourceProductFromResourceIdSafe)(syncBlockInstance.resourceId), (0, _errorHandling.buildFetchErrorAttribution)((
|
|
607
|
+
(_this$deps$getFireAna3 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna3 === void 0 || _this$deps$getFireAna3((0, _errorHandling.fetchErrorPayload)(errorMessage, syncBlockInstance.resourceId, (_syncBlockInstance$da3 = (_syncBlockInstance$da4 = syncBlockInstance.data) === null || _syncBlockInstance$da4 === void 0 ? void 0 : _syncBlockInstance$da4.product) !== null && _syncBlockInstance$da3 !== void 0 ? _syncBlockInstance$da3 : (0, _utils.getSourceProductFromResourceIdSafe)(syncBlockInstance.resourceId), (0, _errorHandling.buildFetchErrorAttribution)(((_syncBlockInstance$er3 = syncBlockInstance.error) === null || _syncBlockInstance$er3 === void 0 ? void 0 : _syncBlockInstance$er3.type) || ((_syncBlockInstance$er4 = syncBlockInstance.error) === null || _syncBlockInstance$er4 === void 0 ? void 0 : _syncBlockInstance$er4.reason), (_syncBlockInstance$er5 = syncBlockInstance.error) === null || _syncBlockInstance$er5 === void 0 ? void 0 : _syncBlockInstance$er5.statusCode)));
|
|
671
608
|
}
|
|
672
609
|
}
|
|
673
610
|
}]);
|
|
@@ -675,10 +612,8 @@ var SyncBlockSubscriptionManager = exports.SyncBlockSubscriptionManager = /*#__P
|
|
|
675
612
|
// Reconnection with exponential backoff.
|
|
676
613
|
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "INITIAL_RETRY_DELAY_MS", 1000);
|
|
677
614
|
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "RETRY_BACKOFF_MULTIPLIER", 2);
|
|
678
|
-
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS", 5);
|
|
679
|
-
// legacy (gate OFF)
|
|
680
615
|
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "MAX_RETRY_ATTEMPTS_HARDENED", 8);
|
|
681
|
-
//
|
|
616
|
+
// EDITOR-7861
|
|
682
617
|
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "MAX_RETRY_DELAY_MS", 30000);
|
|
683
618
|
// Coalesce wake-event bursts into one re-arm sweep to avoid a reconnection storm.
|
|
684
619
|
(0, _defineProperty2.default)(SyncBlockSubscriptionManager, "WAKE_DEBOUNCE_MS", 1000);
|
|
@@ -70,17 +70,9 @@ var classifyErrorReason = exports.classifyErrorReason = function classifyErrorRe
|
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Builds the {@link ErrorAttributionAttributes} for a failed synced-block operation from
|
|
73
|
-
* the raw result `error` field and optional backend `statusCode
|
|
74
|
-
* when the `platform_editor_blocks_patch_3` gate is OFF, so the new `reason`/`statusCode`
|
|
75
|
-
* attributes are only emitted once the gate is rolled out (EDITOR-7796).
|
|
76
|
-
*
|
|
77
|
-
* `gateEnabled` is injected by the caller (the store managers evaluate `fg(...)`) so this
|
|
78
|
-
* helper stays pure and trivially unit-testable for both gate states.
|
|
73
|
+
* the raw result `error` field and optional backend `statusCode` (EDITOR-7796).
|
|
79
74
|
*/
|
|
80
|
-
var buildErrorAttribution = exports.buildErrorAttribution = function buildErrorAttribution(
|
|
81
|
-
if (!gateEnabled) {
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
75
|
+
var buildErrorAttribution = exports.buildErrorAttribution = function buildErrorAttribution(error, statusCode) {
|
|
84
76
|
return _objectSpread({
|
|
85
77
|
reason: classifyErrorReason(error)
|
|
86
78
|
}, statusCode !== undefined && {
|
|
@@ -195,17 +187,10 @@ var classifyFetchErrorReason = exports.classifyFetchErrorReason = function class
|
|
|
195
187
|
/**
|
|
196
188
|
* Builds the {@link FetchErrorAttributionAttributes} for a failed fetch/subscribe
|
|
197
189
|
* synced-block operation from the raw `error` field and optional backend `statusCode`.
|
|
198
|
-
*
|
|
199
|
-
* `
|
|
200
|
-
* (EDITOR-7862). The existing free-text `error` attribute is always left unchanged.
|
|
201
|
-
*
|
|
202
|
-
* `gateEnabled` is injected by the caller (the store managers evaluate `fg(...)`) so this
|
|
203
|
-
* helper stays pure and trivially unit-testable for both gate states.
|
|
190
|
+
* Emits the `reason`/`statusCode`/`benign` attributes (EDITOR-7862). The existing
|
|
191
|
+
* free-text `error` attribute is always left unchanged.
|
|
204
192
|
*/
|
|
205
|
-
var buildFetchErrorAttribution = exports.buildFetchErrorAttribution = function buildFetchErrorAttribution(
|
|
206
|
-
if (!gateEnabled) {
|
|
207
|
-
return undefined;
|
|
208
|
-
}
|
|
193
|
+
var buildFetchErrorAttribution = exports.buildFetchErrorAttribution = function buildFetchErrorAttribution(error, statusCode, deferred) {
|
|
209
194
|
var reason = classifyFetchErrorReason(error);
|
|
210
195
|
return _objectSpread(_objectSpread({
|
|
211
196
|
reason: reason,
|
|
@@ -262,8 +247,8 @@ function getErrorPayload(actionSubjectId, error, resourceId, sourceProduct, attr
|
|
|
262
247
|
var fetchErrorPayload = exports.fetchErrorPayload = function fetchErrorPayload(error, resourceId, sourceProduct, attribution) {
|
|
263
248
|
return (
|
|
264
249
|
// Branch on attribution presence so each call resolves to a concrete overload: with
|
|
265
|
-
// attribution it hits the fetch overload (wider `reason`); without it
|
|
266
|
-
//
|
|
250
|
+
// attribution it hits the fetch overload (wider `reason`); without it, the
|
|
251
|
+
// no-attribution overload. Both produce a fetch event regardless.
|
|
267
252
|
attribution ? getErrorPayload(_analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_FETCH, error, resourceId, sourceProduct, attribution) : getErrorPayload(_analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_FETCH, error, resourceId, sourceProduct)
|
|
268
253
|
);
|
|
269
254
|
};
|
|
@@ -287,8 +272,7 @@ var updateCacheErrorPayload = exports.updateCacheErrorPayload = function updateC
|
|
|
287
272
|
};
|
|
288
273
|
/**
|
|
289
274
|
* Payload for `SYNCED_BLOCK_SOURCE_INFO_ORPHANED`. Fired when source-info
|
|
290
|
-
* resolves into a cache that has already been deleted — should be unreachable
|
|
291
|
-
* under `platform_synced_block_patch_14`.
|
|
275
|
+
* resolves into a cache that has already been deleted — should be unreachable.
|
|
292
276
|
*/
|
|
293
277
|
var sourceInfoOrphanedPayload = exports.sourceInfoOrphanedPayload = function sourceInfoOrphanedPayload(resourceId, sourceProduct, context) {
|
|
294
278
|
return {
|
|
@@ -363,14 +347,13 @@ var createSuccessPayload = exports.createSuccessPayload = function createSuccess
|
|
|
363
347
|
|
|
364
348
|
/**
|
|
365
349
|
* Optional enrichment for the `syncedBlockCreate` success event. All fields
|
|
366
|
-
* optional so
|
|
350
|
+
* optional so legacy payloads are unchanged. `inputMethod`: creating
|
|
367
351
|
* surface (enum, PII-safe). `createdEmpty`: true from an empty selection, false
|
|
368
352
|
* when content was converted.
|
|
369
353
|
*/
|
|
370
354
|
|
|
371
355
|
/**
|
|
372
|
-
* Operational `syncedBlockCreate` success event,
|
|
373
|
-
* `platform_editor_blocks_patch_4`, with the `blockInstanceId` join key and,
|
|
356
|
+
* Operational `syncedBlockCreate` success event with the `blockInstanceId` join key and,
|
|
374
357
|
* when available, the `inputMethod` + `createdEmpty` creation-type signals.
|
|
375
358
|
*/
|
|
376
359
|
var createSuccessOperationalPayload = exports.createSuccessOperationalPayload = function createSuccessOperationalPayload(resourceId, blockInstanceId, sourceProduct, enrichment) {
|
|
@@ -394,8 +377,7 @@ var createSuccessOperationalPayload = exports.createSuccessOperationalPayload =
|
|
|
394
377
|
};
|
|
395
378
|
|
|
396
379
|
/**
|
|
397
|
-
* Operational first-content-added event
|
|
398
|
-
* `platform_editor_blocks_patch_4`. Fired once when a block created empty first
|
|
380
|
+
* Operational first-content-added event. Fired once when a block created empty first
|
|
399
381
|
* gains user content. Join keys only (`resourceId` + `blockInstanceId`), no user
|
|
400
382
|
* content (PII-safe).
|
|
401
383
|
*/
|
|
@@ -431,9 +413,8 @@ var updateSuccessPayload = exports.updateSuccessPayload = function updateSuccess
|
|
|
431
413
|
};
|
|
432
414
|
|
|
433
415
|
/**
|
|
434
|
-
* Optional enrichment for the `syncedBlockDelete` success event
|
|
435
|
-
*
|
|
436
|
-
* is unchanged; `blockInstanceId` is the bare-uuid join key.
|
|
416
|
+
* Optional enrichment for the `syncedBlockDelete` success event. All fields are
|
|
417
|
+
* optional for extensibility; `blockInstanceId` is the bare-uuid join key.
|
|
437
418
|
*/
|
|
438
419
|
|
|
439
420
|
var deleteSuccessPayload = exports.deleteSuccessPayload = function deleteSuccessPayload(resourceId, sourceProduct, enrichment) {
|
|
@@ -40,14 +40,13 @@ export let SyncBlockError = /*#__PURE__*/function (SyncBlockError) {
|
|
|
40
40
|
* asynchronously and `destroy()` nulls it on orphaned managers, so queued/
|
|
41
41
|
* in-flight ops throw `Data provider not set` — previously mis-logged as a real
|
|
42
42
|
* error. These let throw and catch sites agree on one non-string-matched signal
|
|
43
|
-
* so the residual false errors are suppressed.
|
|
44
|
-
* `platform_editor_blocks_patch_3`.
|
|
43
|
+
* so the residual false errors are suppressed.
|
|
45
44
|
*
|
|
46
45
|
* NB: these intentionally live here rather than in a dedicated module to avoid
|
|
47
46
|
* adding a downstream file to consuming Jira packages' Thunderstone complexity.
|
|
48
47
|
*/
|
|
49
48
|
|
|
50
|
-
/** Legacy message — kept identical for
|
|
49
|
+
/** Legacy message — kept identical for historical events. */
|
|
51
50
|
export const PROVIDER_NOT_READY_MESSAGE = 'Data provider not set';
|
|
52
51
|
|
|
53
52
|
/**
|
|
@@ -32,10 +32,10 @@ export const useFetchSyncBlockData = (manager, resourceId, localId, fireAnalytic
|
|
|
32
32
|
// On Jira the data provider is wired asynchronously, so the manager can be
|
|
33
33
|
// constructed with `dataProvider === undefined`. Fetching/subscribing in that
|
|
34
34
|
// window throws `Data provider not set`, logged as a false fetch error
|
|
35
|
-
// (EDITOR-7860).
|
|
35
|
+
// (EDITOR-7860). Check readiness; once the provider resolves a new manager
|
|
36
36
|
// instance is created so `referenceManager` changes identity and the effect
|
|
37
37
|
// below re-runs, subscribing exactly once.
|
|
38
|
-
const isDataProviderReady =
|
|
38
|
+
const isDataProviderReady = (_manager$referenceMan2 = (_manager$referenceMan3 = (_manager$referenceMan4 = manager.referenceManager).hasDataProvider) === null || _manager$referenceMan3 === void 0 ? void 0 : _manager$referenceMan3.call(_manager$referenceMan4)) !== null && _manager$referenceMan2 !== void 0 ? _manager$referenceMan2 : false;
|
|
39
39
|
const reloadData = useCallback(async () => {
|
|
40
40
|
if (isLoading) {
|
|
41
41
|
return;
|
|
@@ -61,8 +61,7 @@ export const useFetchSyncBlockData = (manager, resourceId, localId, fireAnalytic
|
|
|
61
61
|
// EDITOR-7860: benign not-ready throw — emit no error and stay loading
|
|
62
62
|
// so it resolves on retry once the provider is wired. Checked before
|
|
63
63
|
// `logException` so the benign case produces no exception-tracker noise.
|
|
64
|
-
|
|
65
|
-
if (isProviderNotReadyError(error) && fg('platform_editor_blocks_patch_3')) {
|
|
64
|
+
if (isProviderNotReadyError(error)) {
|
|
66
65
|
setFetchState(prev => ({
|
|
67
66
|
...prev,
|
|
68
67
|
isLoading: true
|
|
@@ -72,7 +71,7 @@ export const useFetchSyncBlockData = (manager, resourceId, localId, fireAnalytic
|
|
|
72
71
|
logException(error, {
|
|
73
72
|
location: 'editor-synced-block-provider/useFetchSyncBlockData'
|
|
74
73
|
});
|
|
75
|
-
fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 ? void 0 : fireAnalyticsEvent(fetchErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution(
|
|
74
|
+
fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 ? void 0 : fireAnalyticsEvent(fetchErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId), buildFetchErrorAttribution(error.message)));
|
|
76
75
|
|
|
77
76
|
// Thread the PII-safe original message/name so the renderer can de-opaque
|
|
78
77
|
// this otherwise-bare `errored` failure. `originalMessage` carries the
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import isEqual from 'lodash/isEqual';
|
|
3
3
|
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
4
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
4
|
import { isProviderNotReadyError, ProviderNotReadyError, SyncBlockError } from '../common/types';
|
|
6
5
|
import { buildErrorAttribution, buildFetchErrorAttribution, cacheDeletionForcedPayload, fetchErrorPayload, fetchSuccessPayload, getSourceInfoErrorPayload, sourceInfoOrphanedPayload, updateReferenceErrorPayload } from '../utils/errorHandling';
|
|
7
6
|
import { getFetchExperience, getFetchSourceInfoExperience, getSaveReferenceExperience } from '../utils/experienceTracking';
|
|
@@ -16,7 +15,7 @@ const ENTITY_NOT_FOUND_MAX_RETRIES = 3;
|
|
|
16
15
|
const ENTITY_NOT_FOUND_INITIAL_DELAY_MS = 2000;
|
|
17
16
|
|
|
18
17
|
// Grace period before a cache entry is removed after the last subscriber
|
|
19
|
-
// unsubscribes
|
|
18
|
+
// unsubscribes. Guards are
|
|
20
19
|
// re-checked at fire time; if any are positive, the timer is rescheduled.
|
|
21
20
|
const CACHE_DELETION_GRACE_PERIOD_MS = 30_000;
|
|
22
21
|
// Max reschedules before force-deleting with an analytics event (~5 min).
|
|
@@ -43,8 +42,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
43
42
|
// Track retry attempts for EntityNotFound errors (block may be in the process of being created)
|
|
44
43
|
_defineProperty(this, "entityNotFoundRetryCount", new Map());
|
|
45
44
|
_defineProperty(this, "entityNotFoundRetryTimers", new Map());
|
|
46
|
-
// Pending cache deletion timers keyed by resourceId
|
|
47
|
-
// `platform_synced_block_patch_14`). Cancelled when a subscriber re-attaches.
|
|
45
|
+
// Pending cache deletion timers keyed by resourceId. Cancelled when a subscriber re-attaches.
|
|
48
46
|
_defineProperty(this, "pendingCacheDeletions", new Map());
|
|
49
47
|
// Reschedule counter per resource — reset on actual deletion or re-subscribe.
|
|
50
48
|
_defineProperty(this, "cacheDeletionRescheduleCounts", new Map());
|
|
@@ -59,7 +57,6 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
59
57
|
getDataProvider: () => this.dataProvider,
|
|
60
58
|
getFromCache: rid => this.getFromCache(rid),
|
|
61
59
|
updateCache: inst => this.updateCache(inst),
|
|
62
|
-
deleteFromCache: rid => this.deleteFromCache(rid),
|
|
63
60
|
debouncedBatchedFetchSyncBlocks: rid => this.debouncedBatchedFetchSyncBlocks(rid),
|
|
64
61
|
fetchSyncBlockSourceInfo: rid => this.fetchSyncBlockSourceInfo(rid),
|
|
65
62
|
getFireAnalyticsEvent: () => this.fireAnalyticsEvent,
|
|
@@ -67,7 +64,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
67
64
|
this.isCacheDirty = true;
|
|
68
65
|
},
|
|
69
66
|
// Delegate cache lifecycle to the store manager so guards can be
|
|
70
|
-
// checked atomically
|
|
67
|
+
// checked atomically.
|
|
71
68
|
scheduleCacheDeletion: rid => this.scheduleCacheDeletion(rid),
|
|
72
69
|
cancelPendingCacheDeletion: rid => this.cancelPendingCacheDeletion(rid)
|
|
73
70
|
});
|
|
@@ -426,11 +423,8 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
426
423
|
}
|
|
427
424
|
if (!this.dataProvider) {
|
|
428
425
|
// EDITOR-7860: tag the throw so catch sites can suppress the benign
|
|
429
|
-
// not-ready/torn-down case.
|
|
430
|
-
|
|
431
|
-
throw new ProviderNotReadyError();
|
|
432
|
-
}
|
|
433
|
-
throw new Error('Data provider not set');
|
|
426
|
+
// not-ready/torn-down case.
|
|
427
|
+
throw new ProviderNotReadyError();
|
|
434
428
|
}
|
|
435
429
|
nodesToFetch.forEach(node => {
|
|
436
430
|
this.syncBlockFetchDataRequests.set(node.attrs.resourceId, true);
|
|
@@ -477,7 +471,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
477
471
|
// No resourceId means we cannot derive a sourceProduct here; intentionally omit.
|
|
478
472
|
// Classify on the structured `type` first, falling back to the free-text
|
|
479
473
|
// `reason`/payload (EDITOR-7862).
|
|
480
|
-
(_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 ? void 0 : _this$fireAnalyticsEv8.call(this, fetchErrorPayload(payload, undefined, undefined, buildFetchErrorAttribution(
|
|
474
|
+
(_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 ? void 0 : _this$fireAnalyticsEv8.call(this, fetchErrorPayload(payload, undefined, undefined, buildFetchErrorAttribution(((_syncBlockInstance$er3 = syncBlockInstance.error) === null || _syncBlockInstance$er3 === void 0 ? void 0 : _syncBlockInstance$er3.type) || ((_syncBlockInstance$er4 = syncBlockInstance.error) === null || _syncBlockInstance$er4 === void 0 ? void 0 : _syncBlockInstance$er4.reason) || payload, (_syncBlockInstance$er5 = syncBlockInstance.error) === null || _syncBlockInstance$er5 === void 0 ? void 0 : _syncBlockInstance$er5.statusCode)));
|
|
481
475
|
return;
|
|
482
476
|
}
|
|
483
477
|
const existingSyncBlock = this.getFromCache(syncBlockInstance.resourceId);
|
|
@@ -508,13 +502,13 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
508
502
|
var _this$entityNotFoundR;
|
|
509
503
|
// Skip error analytics when EntityNotFound will be retried, to avoid
|
|
510
504
|
// inflating error-rate metrics with expected transient failures
|
|
511
|
-
const isRetryingEntityNotFound = syncBlockInstance.error.type === SyncBlockError.EntityNotFound && ((_this$entityNotFoundR = this.entityNotFoundRetryCount.get(syncBlockInstance.resourceId)) !== null && _this$entityNotFoundR !== void 0 ? _this$entityNotFoundR : 0) < ENTITY_NOT_FOUND_MAX_RETRIES
|
|
505
|
+
const isRetryingEntityNotFound = syncBlockInstance.error.type === SyncBlockError.EntityNotFound && ((_this$entityNotFoundR = this.entityNotFoundRetryCount.get(syncBlockInstance.resourceId)) !== null && _this$entityNotFoundR !== void 0 ? _this$entityNotFoundR : 0) < ENTITY_NOT_FOUND_MAX_RETRIES;
|
|
512
506
|
if (!isRetryingEntityNotFound) {
|
|
513
507
|
var _this$fireAnalyticsEv9, _syncBlockInstance$da, _syncBlockInstance$da2;
|
|
514
508
|
// Classify on the structured `type` (a `SyncBlockError` enum value) first,
|
|
515
509
|
// falling back to the free-text `reason` so source-state/permission strings
|
|
516
510
|
// are still bucketed (EDITOR-7862). The emitted `error` attribute is unchanged.
|
|
517
|
-
(_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 ? void 0 : _this$fireAnalyticsEv9.call(this, fetchErrorPayload(syncBlockInstance.error.reason || syncBlockInstance.error.type, syncBlockInstance.resourceId, (_syncBlockInstance$da = (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product) !== null && _syncBlockInstance$da !== void 0 ? _syncBlockInstance$da : getSourceProductFromResourceIdSafe(syncBlockInstance.resourceId), buildFetchErrorAttribution(
|
|
511
|
+
(_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 ? void 0 : _this$fireAnalyticsEv9.call(this, fetchErrorPayload(syncBlockInstance.error.reason || syncBlockInstance.error.type, syncBlockInstance.resourceId, (_syncBlockInstance$da = (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product) !== null && _syncBlockInstance$da !== void 0 ? _syncBlockInstance$da : getSourceProductFromResourceIdSafe(syncBlockInstance.resourceId), buildFetchErrorAttribution(syncBlockInstance.error.type || syncBlockInstance.error.reason, syncBlockInstance.error.statusCode)));
|
|
518
512
|
}
|
|
519
513
|
if (syncBlockInstance.error.type === SyncBlockError.NotFound || syncBlockInstance.error.type === SyncBlockError.Forbidden) {
|
|
520
514
|
hasExpectedError = true;
|
|
@@ -522,9 +516,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
522
516
|
// Schedule a retry for EntityNotFound — the source block may be in
|
|
523
517
|
// the process of being created by a collaborator (race condition
|
|
524
518
|
// between NCS propagation and Block Service createBlock call).
|
|
525
|
-
|
|
526
|
-
this.scheduleEntityNotFoundRetry(syncBlockInstance.resourceId);
|
|
527
|
-
}
|
|
519
|
+
this.scheduleEntityNotFoundRetry(syncBlockInstance.resourceId);
|
|
528
520
|
if (!isRetryingEntityNotFound) {
|
|
529
521
|
hasUnexpectedError = true;
|
|
530
522
|
}
|
|
@@ -550,7 +542,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
550
542
|
const existingSyncBlock = this.getFromCache(resourceId);
|
|
551
543
|
// If the cache entry was deleted while the source-info request was
|
|
552
544
|
// in flight, fire an analytics event so the race is observable.
|
|
553
|
-
if (!existingSyncBlock
|
|
545
|
+
if (!existingSyncBlock) {
|
|
554
546
|
var _this$fireAnalyticsEv1;
|
|
555
547
|
(_this$fireAnalyticsEv1 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv1 === void 0 ? void 0 : _this$fireAnalyticsEv1.call(this, sourceInfoOrphanedPayload(resourceId, getSourceProductFromResourceIdSafe(resourceId), {
|
|
556
548
|
hasPendingDeletion: this.pendingCacheDeletions.has(resourceId),
|
|
@@ -602,16 +594,14 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
602
594
|
this._providerFactoryManager.deleteFactory(resourceId);
|
|
603
595
|
// Evict in-flight source-info promise and reset reschedule counter
|
|
604
596
|
// so a stale resolution can't silently merge into a re-fetched entry.
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
this.cacheDeletionRescheduleCounts.delete(resourceId);
|
|
608
|
-
}
|
|
597
|
+
this.syncBlockSourceInfoRequests.delete(resourceId);
|
|
598
|
+
this.cacheDeletionRescheduleCounts.delete(resourceId);
|
|
609
599
|
}
|
|
610
600
|
|
|
611
601
|
/**
|
|
612
602
|
* Returns true if the cache entry for `resourceId` is safe to delete:
|
|
613
603
|
* no active subscribers, no in-flight source-info request, and no
|
|
614
|
-
* queued/in-flight batch fetch
|
|
604
|
+
* queued/in-flight batch fetch.
|
|
615
605
|
*/
|
|
616
606
|
canDeleteCache(resourceId) {
|
|
617
607
|
if (this._subscriptionManager.getSubscriptions().has(resourceId)) {
|
|
@@ -628,14 +618,11 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
628
618
|
|
|
629
619
|
/**
|
|
630
620
|
* Schedules cache deletion for `resourceId` after the grace period
|
|
631
|
-
*
|
|
621
|
+
* Called when the last
|
|
632
622
|
* subscriber unsubscribes. Guards are re-checked at fire time; if any
|
|
633
623
|
* are positive the timer is rescheduled up to MAX_RESCHEDULES times.
|
|
634
624
|
*/
|
|
635
625
|
scheduleCacheDeletion(resourceId) {
|
|
636
|
-
if (!fg('platform_synced_block_patch_14')) {
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
626
|
if (this.isDestroyed) {
|
|
640
627
|
return;
|
|
641
628
|
}
|
|
@@ -663,13 +650,10 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
663
650
|
|
|
664
651
|
/**
|
|
665
652
|
* Cancels any pending cache deletion timer for `resourceId` and resets the
|
|
666
|
-
* reschedule counter
|
|
653
|
+
* reschedule counter. Called
|
|
667
654
|
* when a new subscriber arrives.
|
|
668
655
|
*/
|
|
669
656
|
cancelPendingCacheDeletion(resourceId) {
|
|
670
|
-
if (!fg('platform_synced_block_patch_14')) {
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
657
|
const existing = this.pendingCacheDeletions.get(resourceId);
|
|
674
658
|
if (existing) {
|
|
675
659
|
clearTimeout(existing);
|
|
@@ -687,7 +671,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
687
671
|
onCacheDeletionTimerFire(resourceId) {
|
|
688
672
|
var _this$cacheDeletionRe;
|
|
689
673
|
if (this.canDeleteCache(resourceId)) {
|
|
690
|
-
// `deleteFromCache` resets the reschedule counter
|
|
674
|
+
// `deleteFromCache` resets the reschedule counter.
|
|
691
675
|
this.deleteFromCache(resourceId);
|
|
692
676
|
return;
|
|
693
677
|
}
|
|
@@ -707,7 +691,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
707
691
|
logException(new Error(`Cache deletion forced after ${currentCount} reschedules — stuck in-flight guard`), {
|
|
708
692
|
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager/cache-deletion-forced'
|
|
709
693
|
});
|
|
710
|
-
// `deleteFromCache` resets the reschedule counter
|
|
694
|
+
// `deleteFromCache` resets the reschedule counter.
|
|
711
695
|
this.deleteFromCache(resourceId);
|
|
712
696
|
// If subscribers still exist, kick off a fresh fetch so they get
|
|
713
697
|
// fresh data on the next batch tick instead of holding stale data
|
|
@@ -804,14 +788,14 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
804
788
|
var _this$fireAnalyticsEv11;
|
|
805
789
|
// EDITOR-7860: benign not-ready/torn-down case — suppress both the
|
|
806
790
|
// exception-tracker log and the analytics event (checked first so the
|
|
807
|
-
// benign case stays fully silent).
|
|
808
|
-
if (isProviderNotReadyError(error)
|
|
791
|
+
// benign case stays fully silent).
|
|
792
|
+
if (isProviderNotReadyError(error)) {
|
|
809
793
|
return () => {};
|
|
810
794
|
}
|
|
811
795
|
logException(error, {
|
|
812
796
|
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
813
797
|
});
|
|
814
|
-
(_this$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, fetchErrorPayload(error.message, undefined, undefined, buildFetchErrorAttribution(
|
|
798
|
+
(_this$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, fetchErrorPayload(error.message, undefined, undefined, buildFetchErrorAttribution(error.message)));
|
|
815
799
|
return () => {};
|
|
816
800
|
}
|
|
817
801
|
}
|
|
@@ -919,7 +903,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
919
903
|
(_this$saveExperience2 = this.saveExperience) === null || _this$saveExperience2 === void 0 ? void 0 : _this$saveExperience2.failure({
|
|
920
904
|
reason: updateResult.error || 'Failed to update reference synced blocks on the document'
|
|
921
905
|
});
|
|
922
|
-
(_this$fireAnalyticsEv12 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv12 === void 0 ? void 0 : _this$fireAnalyticsEv12.call(this, updateReferenceErrorPayload(updateResult.error || 'Failed to update reference synced blocks on the document', undefined, undefined, buildErrorAttribution(
|
|
906
|
+
(_this$fireAnalyticsEv12 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv12 === void 0 ? void 0 : _this$fireAnalyticsEv12.call(this, updateReferenceErrorPayload(updateResult.error || 'Failed to update reference synced blocks on the document', undefined, undefined, buildErrorAttribution(updateResult.error, updateResult.statusCode)));
|
|
923
907
|
}
|
|
924
908
|
} catch (error) {
|
|
925
909
|
var _this$saveExperience3, _this$fireAnalyticsEv13;
|
|
@@ -932,8 +916,8 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
932
916
|
});
|
|
933
917
|
// No `resourceId` available in this catch — sourceProduct is intentionally omitted.
|
|
934
918
|
// No structured SyncBlockError/status here, so the attribution `reason` falls back
|
|
935
|
-
// to `unknown
|
|
936
|
-
(_this$fireAnalyticsEv13 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv13 === void 0 ? void 0 : _this$fireAnalyticsEv13.call(this, updateReferenceErrorPayload(error.message, undefined, undefined, buildErrorAttribution(
|
|
919
|
+
// to `unknown`.
|
|
920
|
+
(_this$fireAnalyticsEv13 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv13 === void 0 ? void 0 : _this$fireAnalyticsEv13.call(this, updateReferenceErrorPayload(error.message, undefined, undefined, buildErrorAttribution()));
|
|
937
921
|
} finally {
|
|
938
922
|
if (!success) {
|
|
939
923
|
// set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
|
|
@@ -998,16 +982,8 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
998
982
|
});
|
|
999
983
|
this.fireAnalyticsEvent = undefined;
|
|
1000
984
|
|
|
1001
|
-
//
|
|
1002
|
-
//
|
|
1003
|
-
//
|
|
1004
|
-
// cache data that a sibling/successor manager (e.g. the editor
|
|
1005
|
-
// instance that mounts immediately after the renderer unmounts during
|
|
1006
|
-
// the view-mode transition) is about to read.
|
|
1007
|
-
// Let entries age out naturally instead — the in-memory cache is
|
|
1008
|
-
// naturally bounded by `maxSize` (LRU) and cleared on hard navigation.
|
|
1009
|
-
if (!fg('platform_synced_block_patch_14')) {
|
|
1010
|
-
syncBlockInMemorySessionCache.clear();
|
|
1011
|
-
}
|
|
985
|
+
// `destroy()` is wired to React component unmount via
|
|
986
|
+
// `useMemoizedSyncBlockStoreManager`. Let the in-memory session cache age
|
|
987
|
+
// out naturally instead of clearing it during a view-mode transition.
|
|
1012
988
|
}
|
|
1013
989
|
}
|