@atlaskit/editor-synced-block-provider 25.0.2 → 25.0.4
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 +18 -0
- package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +17 -7
- package/dist/cjs/utils/errorHandling.js +23 -1
- package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +36 -26
- package/dist/es2019/utils/errorHandling.js +23 -0
- package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +18 -8
- package/dist/esm/utils/errorHandling.js +22 -0
- package/dist/types/utils/errorHandling.d.ts +5 -0
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @atlaskit/editor-synced-block-provider
|
|
2
2
|
|
|
3
|
+
## 25.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 25.0.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`004b7c3c33232`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/004b7c3c33232) -
|
|
14
|
+
Fire a per-request `syncedBlockGetSourceInfo` success event, tagged with `sourceLocation`, when a
|
|
15
|
+
reference synced block resolves its source info, and tag the missing-source-ARI error with
|
|
16
|
+
`sourceLocation`. Stop adding `sourceLocation` metadata to the shared source-info experience
|
|
17
|
+
events. Gated by the `platform_editor_blocks_patch_12` experiment (with
|
|
18
|
+
`editor_synced_blocks_jira_custom_rich_text`); with the experiment off, events are unchanged.
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
|
|
3
21
|
## 25.0.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -435,15 +435,20 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
435
435
|
// `product` from cached data is preferred when available; fall back to parsing
|
|
436
436
|
// the resourceId.
|
|
437
437
|
var sourceProduct = product !== null && product !== void 0 ? product : (0, _utils.getSourceProductFromResourceIdSafe)(resourceId);
|
|
438
|
+
|
|
439
|
+
// With the experiment off, events and experience calls are identical to master.
|
|
440
|
+
var isPerRequestSourceInfo = (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_blocks_patch_12');
|
|
438
441
|
if (!sourceAri || !product || !blockInstanceId) {
|
|
439
442
|
var _this$fireAnalyticsEv3;
|
|
440
|
-
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 || _this$fireAnalyticsEv3.call(this, (0, _errorHandling.getSourceInfoErrorPayload)('SourceAri, product or blockInstanceId missing', resourceId, sourceProduct));
|
|
443
|
+
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 || _this$fireAnalyticsEv3.call(this, (0, _errorHandling.getSourceInfoErrorPayload)('SourceAri, product or blockInstanceId missing', resourceId, sourceProduct, isPerRequestSourceInfo ? (0, _fieldAwareLocations.getSourceLocation)(sourceAri) : undefined));
|
|
441
444
|
return Promise.resolve(undefined);
|
|
442
445
|
}
|
|
443
446
|
var sourceLocation = (0, _fieldAwareLocations.getSourceLocation)(sourceAri);
|
|
444
|
-
|
|
447
|
+
// The shared experience cannot count requests, so with the experiment on the
|
|
448
|
+
// per-request event below carries `sourceLocation` instead of the experience.
|
|
449
|
+
var experienceMetadata = !isPerRequestSourceInfo && sourceLocation ? {
|
|
445
450
|
sourceLocation: sourceLocation
|
|
446
|
-
};
|
|
451
|
+
} : undefined;
|
|
447
452
|
var withExperienceMetadata = function withExperienceMetadata(options) {
|
|
448
453
|
return experienceMetadata ? _objectSpread(_objectSpread({}, options), {}, {
|
|
449
454
|
metadata: experienceMetadata
|
|
@@ -474,20 +479,25 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
|
|
|
474
479
|
var _this2$fetchSourceInf3;
|
|
475
480
|
(_this2$fetchSourceInf3 = _this2.fetchSourceInfoExperience) === null || _this2$fetchSourceInf3 === void 0 || _this2$fetchSourceInf3.success();
|
|
476
481
|
}
|
|
482
|
+
// Pairs with the error event above as the per-request denominator.
|
|
483
|
+
if (isPerRequestSourceInfo && sourceLocation) {
|
|
484
|
+
var _this2$fireAnalyticsE2;
|
|
485
|
+
(_this2$fireAnalyticsE2 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE2 === void 0 || _this2$fireAnalyticsE2.call(_this2, (0, _errorHandling.getSourceInfoSuccessPayload)(resourceId, blockInstanceId, sourceProduct, sourceLocation));
|
|
486
|
+
}
|
|
477
487
|
} else {
|
|
478
|
-
var _this2$fetchSourceInf4, _this2$
|
|
488
|
+
var _this2$fetchSourceInf4, _this2$fireAnalyticsE3;
|
|
479
489
|
(_this2$fetchSourceInf4 = _this2.fetchSourceInfoExperience) === null || _this2$fetchSourceInf4 === void 0 || _this2$fetchSourceInf4.failure(withExperienceMetadata({
|
|
480
490
|
reason: 'Missing title or url'
|
|
481
491
|
}));
|
|
482
|
-
(_this2$
|
|
492
|
+
(_this2$fireAnalyticsE3 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE3 === void 0 || _this2$fireAnalyticsE3.call(_this2, (0, _errorHandling.getSourceInfoErrorPayload)('Missing title or url', resourceId, sourceProduct, sourceLocation));
|
|
483
493
|
}
|
|
484
494
|
return sourceInfo;
|
|
485
495
|
}).catch(function (error) {
|
|
486
|
-
var _this2$fetchSourceInf5, _this2$
|
|
496
|
+
var _this2$fetchSourceInf5, _this2$fireAnalyticsE4;
|
|
487
497
|
(_this2$fetchSourceInf5 = _this2.fetchSourceInfoExperience) === null || _this2$fetchSourceInf5 === void 0 || _this2$fetchSourceInf5.failure(withExperienceMetadata({
|
|
488
498
|
reason: error.message
|
|
489
499
|
}));
|
|
490
|
-
(_this2$
|
|
500
|
+
(_this2$fireAnalyticsE4 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE4 === void 0 || _this2$fireAnalyticsE4.call(_this2, (0, _errorHandling.getSourceInfoErrorPayload)(error.message, resourceId, sourceProduct, sourceLocation));
|
|
491
501
|
return undefined;
|
|
492
502
|
}).finally(function () {
|
|
493
503
|
_this2.syncBlockSourceInfoRequests.delete(resourceId);
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.fetchSuccessPayload = exports.fetchReferencesErrorPayload = exports.fetchErrorPayload = exports.deleteSuccessPayload = exports.deleteErrorPayload = exports.createSuccessPayload = exports.createSuccessOperationalPayload = exports.createErrorPayload = exports.classifyFetchErrorReason = exports.classifyErrorReason = exports.cacheDeletionForcedPayload = exports.buildFetchErrorAttribution = exports.buildErrorAttribution = exports.addContentSuccessPayload = exports.FETCH_BENIGN_REASONS = void 0;
|
|
8
8
|
exports.getErrorPayload = getErrorPayload;
|
|
9
|
-
exports.updateSuccessPayload = exports.updateReferenceErrorPayload = exports.updateErrorPayload = exports.updateCacheErrorPayload = exports.stringifyError = exports.sourceInfoOrphanedPayload = exports.getSourceInfoErrorPayload = exports.getPiiSafeOriginalError = void 0;
|
|
9
|
+
exports.updateSuccessPayload = exports.updateReferenceErrorPayload = exports.updateErrorPayload = exports.updateCacheErrorPayload = exports.stringifyError = exports.sourceInfoOrphanedPayload = exports.getSourceInfoSuccessPayload = exports.getSourceInfoErrorPayload = exports.getPiiSafeOriginalError = void 0;
|
|
10
10
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
11
11
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
12
12
|
var _enums = require("@atlaskit/editor-common/analytics/types/enums");
|
|
@@ -333,6 +333,28 @@ var fetchSuccessPayload = exports.fetchSuccessPayload = function fetchSuccessPay
|
|
|
333
333
|
})
|
|
334
334
|
};
|
|
335
335
|
};
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Per-request `syncedBlockGetSourceInfo` success event. Pairs with
|
|
339
|
+
* `getSourceInfoErrorPayload` so a success rate can be computed per request.
|
|
340
|
+
*/
|
|
341
|
+
var getSourceInfoSuccessPayload = exports.getSourceInfoSuccessPayload = function getSourceInfoSuccessPayload(resourceId, blockInstanceId, sourceProduct, sourceLocation) {
|
|
342
|
+
return {
|
|
343
|
+
action: _enums.ACTION.FETCHED,
|
|
344
|
+
actionSubject: _enums.ACTION_SUBJECT.SYNCED_BLOCK,
|
|
345
|
+
actionSubjectId: _enums.ACTION_SUBJECT_ID.SYNCED_BLOCK_GET_SOURCE_INFO,
|
|
346
|
+
eventType: _enums.EVENT_TYPE.OPERATIONAL,
|
|
347
|
+
attributes: _objectSpread(_objectSpread(_objectSpread({
|
|
348
|
+
resourceId: resourceId
|
|
349
|
+
}, blockInstanceId && {
|
|
350
|
+
blockInstanceId: blockInstanceId
|
|
351
|
+
}), sourceProduct && {
|
|
352
|
+
sourceProduct: sourceProduct
|
|
353
|
+
}), sourceLocation && {
|
|
354
|
+
sourceLocation: sourceLocation
|
|
355
|
+
})
|
|
356
|
+
};
|
|
357
|
+
};
|
|
336
358
|
var createSuccessPayload = exports.createSuccessPayload = function createSuccessPayload(resourceId, sourceProduct, sourceLocation) {
|
|
337
359
|
return {
|
|
338
360
|
action: _enums.ACTION.INSERTED,
|
|
@@ -3,7 +3,7 @@ import isEqual from 'lodash/isEqual';
|
|
|
3
3
|
import { logException } from '@atlaskit/editor-common/monitoring/error';
|
|
4
4
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
5
5
|
import { isProviderNotReadyError, ProviderNotReadyError, SyncBlockError } from '../common/types';
|
|
6
|
-
import { buildErrorAttribution, buildFetchErrorAttribution, cacheDeletionForcedPayload, fetchErrorPayload, fetchSuccessPayload, getSourceInfoErrorPayload, sourceInfoOrphanedPayload, updateReferenceErrorPayload } from '../utils/errorHandling';
|
|
6
|
+
import { buildErrorAttribution, buildFetchErrorAttribution, cacheDeletionForcedPayload, fetchErrorPayload, fetchSuccessPayload, getSourceInfoErrorPayload, getSourceInfoSuccessPayload, sourceInfoOrphanedPayload, updateReferenceErrorPayload } from '../utils/errorHandling';
|
|
7
7
|
import { getFetchExperience, getFetchSourceInfoExperience, getSaveReferenceExperience } from '../utils/experienceTracking';
|
|
8
8
|
import { getSourceLocation } from '../utils/fieldAwareLocations';
|
|
9
9
|
import { resolveSyncBlockInstance } from '../utils/resolveSyncBlockInstance';
|
|
@@ -343,15 +343,20 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
343
343
|
// `product` from cached data is preferred when available; fall back to parsing
|
|
344
344
|
// the resourceId.
|
|
345
345
|
const sourceProduct = product !== null && product !== void 0 ? product : getSourceProductFromResourceIdSafe(resourceId);
|
|
346
|
+
|
|
347
|
+
// With the experiment off, events and experience calls are identical to master.
|
|
348
|
+
const isPerRequestSourceInfo = isExperimentEnabled('platform_editor_blocks_patch_12');
|
|
346
349
|
if (!sourceAri || !product || !blockInstanceId) {
|
|
347
350
|
var _this$fireAnalyticsEv3;
|
|
348
|
-
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 ? void 0 : _this$fireAnalyticsEv3.call(this, getSourceInfoErrorPayload('SourceAri, product or blockInstanceId missing', resourceId, sourceProduct));
|
|
351
|
+
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 ? void 0 : _this$fireAnalyticsEv3.call(this, getSourceInfoErrorPayload('SourceAri, product or blockInstanceId missing', resourceId, sourceProduct, isPerRequestSourceInfo ? getSourceLocation(sourceAri) : undefined));
|
|
349
352
|
return Promise.resolve(undefined);
|
|
350
353
|
}
|
|
351
354
|
const sourceLocation = getSourceLocation(sourceAri);
|
|
352
|
-
|
|
355
|
+
// The shared experience cannot count requests, so with the experiment on the
|
|
356
|
+
// per-request event below carries `sourceLocation` instead of the experience.
|
|
357
|
+
const experienceMetadata = !isPerRequestSourceInfo && sourceLocation ? {
|
|
353
358
|
sourceLocation
|
|
354
|
-
};
|
|
359
|
+
} : undefined;
|
|
355
360
|
const withExperienceMetadata = options => experienceMetadata ? {
|
|
356
361
|
...options,
|
|
357
362
|
metadata: experienceMetadata
|
|
@@ -381,20 +386,25 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
381
386
|
var _this$fetchSourceInfo4;
|
|
382
387
|
(_this$fetchSourceInfo4 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo4 === void 0 ? void 0 : _this$fetchSourceInfo4.success();
|
|
383
388
|
}
|
|
389
|
+
// Pairs with the error event above as the per-request denominator.
|
|
390
|
+
if (isPerRequestSourceInfo && sourceLocation) {
|
|
391
|
+
var _this$fireAnalyticsEv5;
|
|
392
|
+
(_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 ? void 0 : _this$fireAnalyticsEv5.call(this, getSourceInfoSuccessPayload(resourceId, blockInstanceId, sourceProduct, sourceLocation));
|
|
393
|
+
}
|
|
384
394
|
} else {
|
|
385
|
-
var _this$fetchSourceInfo5, _this$
|
|
395
|
+
var _this$fetchSourceInfo5, _this$fireAnalyticsEv6;
|
|
386
396
|
(_this$fetchSourceInfo5 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo5 === void 0 ? void 0 : _this$fetchSourceInfo5.failure(withExperienceMetadata({
|
|
387
397
|
reason: 'Missing title or url'
|
|
388
398
|
}));
|
|
389
|
-
(_this$
|
|
399
|
+
(_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 ? void 0 : _this$fireAnalyticsEv6.call(this, getSourceInfoErrorPayload('Missing title or url', resourceId, sourceProduct, sourceLocation));
|
|
390
400
|
}
|
|
391
401
|
return sourceInfo;
|
|
392
402
|
}).catch(error => {
|
|
393
|
-
var _this$fetchSourceInfo6, _this$
|
|
403
|
+
var _this$fetchSourceInfo6, _this$fireAnalyticsEv7;
|
|
394
404
|
(_this$fetchSourceInfo6 = this.fetchSourceInfoExperience) === null || _this$fetchSourceInfo6 === void 0 ? void 0 : _this$fetchSourceInfo6.failure(withExperienceMetadata({
|
|
395
405
|
reason: error.message
|
|
396
406
|
}));
|
|
397
|
-
(_this$
|
|
407
|
+
(_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 ? void 0 : _this$fireAnalyticsEv7.call(this, getSourceInfoErrorPayload(error.message, resourceId, sourceProduct, sourceLocation));
|
|
398
408
|
return undefined;
|
|
399
409
|
}).finally(() => {
|
|
400
410
|
this.syncBlockSourceInfoRequests.delete(resourceId);
|
|
@@ -402,11 +412,11 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
402
412
|
this.syncBlockSourceInfoRequests.set(resourceId, sourceInfoPromise);
|
|
403
413
|
return sourceInfoPromise;
|
|
404
414
|
} catch (error) {
|
|
405
|
-
var _this$
|
|
415
|
+
var _this$fireAnalyticsEv8;
|
|
406
416
|
logException(error, {
|
|
407
417
|
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
408
418
|
});
|
|
409
|
-
(_this$
|
|
419
|
+
(_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 ? void 0 : _this$fireAnalyticsEv8.call(this, getSourceInfoErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
410
420
|
}
|
|
411
421
|
return Promise.resolve(undefined);
|
|
412
422
|
}
|
|
@@ -534,12 +544,12 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
534
544
|
data.forEach(syncBlockInstance => {
|
|
535
545
|
var _resolvedSyncBlockIns;
|
|
536
546
|
if (!syncBlockInstance.resourceId) {
|
|
537
|
-
var _syncBlockInstance$er, _syncBlockInstance$er2, _this$
|
|
547
|
+
var _syncBlockInstance$er, _syncBlockInstance$er2, _this$fireAnalyticsEv9, _syncBlockInstance$er3, _syncBlockInstance$er4, _syncBlockInstance$er5;
|
|
538
548
|
const payload = ((_syncBlockInstance$er = syncBlockInstance.error) === null || _syncBlockInstance$er === void 0 ? void 0 : _syncBlockInstance$er.reason) || ((_syncBlockInstance$er2 = syncBlockInstance.error) === null || _syncBlockInstance$er2 === void 0 ? void 0 : _syncBlockInstance$er2.type) || 'Returned sync block instance does not have resource id';
|
|
539
549
|
// No resourceId means we cannot derive a sourceProduct here; intentionally omit.
|
|
540
550
|
// Classify on the structured `type` first, falling back to the free-text
|
|
541
551
|
// `reason`/payload (EDITOR-7862).
|
|
542
|
-
(_this$
|
|
552
|
+
(_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 ? void 0 : _this$fireAnalyticsEv9.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)));
|
|
543
553
|
return;
|
|
544
554
|
}
|
|
545
555
|
const existingSyncBlock = this.getFromCache(syncBlockInstance.resourceId);
|
|
@@ -572,11 +582,11 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
572
582
|
// inflating error-rate metrics with expected transient failures
|
|
573
583
|
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;
|
|
574
584
|
if (!isRetryingEntityNotFound) {
|
|
575
|
-
var _this$
|
|
585
|
+
var _this$fireAnalyticsEv0, _syncBlockInstance$da, _syncBlockInstance$da2;
|
|
576
586
|
// Classify on the structured `type` (a `SyncBlockError` enum value) first,
|
|
577
587
|
// falling back to the free-text `reason` so source-state/permission strings
|
|
578
588
|
// are still bucketed (EDITOR-7862). The emitted `error` attribute is unchanged.
|
|
579
|
-
(_this$
|
|
589
|
+
(_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 ? void 0 : _this$fireAnalyticsEv0.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)));
|
|
580
590
|
}
|
|
581
591
|
if (syncBlockInstance.error.type === SyncBlockError.NotFound || syncBlockInstance.error.type === SyncBlockError.Forbidden) {
|
|
582
592
|
hasExpectedError = true;
|
|
@@ -596,8 +606,8 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
596
606
|
const callbacks = this._subscriptionManager.getSubscriptions().get(syncBlockInstance.resourceId);
|
|
597
607
|
const localIds = callbacks ? Object.keys(callbacks) : [];
|
|
598
608
|
localIds.forEach(localId => {
|
|
599
|
-
var _this$
|
|
600
|
-
(_this$
|
|
609
|
+
var _this$fireAnalyticsEv1, _syncBlockInstance$da3, _syncBlockInstance$da4;
|
|
610
|
+
(_this$fireAnalyticsEv1 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv1 === void 0 ? void 0 : _this$fireAnalyticsEv1.call(this, fetchSuccessPayload(syncBlockInstance.resourceId, localId, (_syncBlockInstance$da3 = (_syncBlockInstance$da4 = syncBlockInstance.data) === null || _syncBlockInstance$da4 === void 0 ? void 0 : _syncBlockInstance$da4.product) !== null && _syncBlockInstance$da3 !== void 0 ? _syncBlockInstance$da3 : getSourceProductFromResourceIdSafe(syncBlockInstance.resourceId)));
|
|
601
611
|
});
|
|
602
612
|
this.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
|
|
603
613
|
});
|
|
@@ -611,8 +621,8 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
611
621
|
// If the cache entry was deleted while the source-info request was
|
|
612
622
|
// in flight, fire an analytics event so the race is observable.
|
|
613
623
|
if (!existingSyncBlock) {
|
|
614
|
-
var _this$
|
|
615
|
-
(_this$
|
|
624
|
+
var _this$fireAnalyticsEv10;
|
|
625
|
+
(_this$fireAnalyticsEv10 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv10 === void 0 ? void 0 : _this$fireAnalyticsEv10.call(this, sourceInfoOrphanedPayload(resourceId, getSourceProductFromResourceIdSafe(resourceId), {
|
|
616
626
|
hasPendingDeletion: this.pendingCacheDeletions.has(resourceId),
|
|
617
627
|
hasSubscribers: this._subscriptionManager.getSubscriptions().has(resourceId)
|
|
618
628
|
}));
|
|
@@ -751,7 +761,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
751
761
|
}
|
|
752
762
|
const currentCount = (_this$cacheDeletionRe = this.cacheDeletionRescheduleCounts.get(resourceId)) !== null && _this$cacheDeletionRe !== void 0 ? _this$cacheDeletionRe : 0;
|
|
753
763
|
if (currentCount >= CACHE_DELETION_MAX_RESCHEDULES) {
|
|
754
|
-
var _this$
|
|
764
|
+
var _this$fireAnalyticsEv11;
|
|
755
765
|
// Stuck guard — force deletion to prevent unbounded memory growth and
|
|
756
766
|
// fire analytics so the stuck state is visible in production telemetry.
|
|
757
767
|
//
|
|
@@ -761,7 +771,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
761
771
|
// continue to render with stale data until their next re-render
|
|
762
772
|
// triggers a new batch fetch — typically within ~1 frame. We accept
|
|
763
773
|
// this brief stale window in exchange for bounded memory growth.
|
|
764
|
-
(_this$
|
|
774
|
+
(_this$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, cacheDeletionForcedPayload(currentCount, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
|
|
765
775
|
logException(new Error(`Cache deletion forced after ${currentCount} reschedules — stuck in-flight guard`), {
|
|
766
776
|
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager/cache-deletion-forced'
|
|
767
777
|
});
|
|
@@ -889,7 +899,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
889
899
|
}
|
|
890
900
|
return this.subscribeToSyncBlock(resourceId, localId, callback);
|
|
891
901
|
} catch (error) {
|
|
892
|
-
var _this$
|
|
902
|
+
var _this$fireAnalyticsEv12;
|
|
893
903
|
// EDITOR-7860: benign not-ready/torn-down case — suppress both the
|
|
894
904
|
// exception-tracker log and the analytics event (checked first so the
|
|
895
905
|
// benign case stays fully silent).
|
|
@@ -899,7 +909,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
899
909
|
logException(error, {
|
|
900
910
|
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
901
911
|
});
|
|
902
|
-
(_this$
|
|
912
|
+
(_this$fireAnalyticsEv12 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv12 === void 0 ? void 0 : _this$fireAnalyticsEv12.call(this, fetchErrorPayload(error.message, undefined, undefined, buildFetchErrorAttribution(error.message)));
|
|
903
913
|
return () => {};
|
|
904
914
|
}
|
|
905
915
|
}
|
|
@@ -1003,15 +1013,15 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
1003
1013
|
(_this$saveExperience = this.saveExperience) === null || _this$saveExperience === void 0 ? void 0 : _this$saveExperience.start();
|
|
1004
1014
|
const updateResult = await this.dataProvider.updateReferenceData(blocks);
|
|
1005
1015
|
if (!updateResult.success) {
|
|
1006
|
-
var _this$saveExperience2, _this$
|
|
1016
|
+
var _this$saveExperience2, _this$fireAnalyticsEv13;
|
|
1007
1017
|
success = false;
|
|
1008
1018
|
(_this$saveExperience2 = this.saveExperience) === null || _this$saveExperience2 === void 0 ? void 0 : _this$saveExperience2.failure({
|
|
1009
1019
|
reason: updateResult.error || 'Failed to update reference synced blocks on the document'
|
|
1010
1020
|
});
|
|
1011
|
-
(_this$
|
|
1021
|
+
(_this$fireAnalyticsEv13 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv13 === void 0 ? void 0 : _this$fireAnalyticsEv13.call(this, updateReferenceErrorPayload(updateResult.error || 'Failed to update reference synced blocks on the document', undefined, undefined, buildErrorAttribution(updateResult.error, updateResult.statusCode)));
|
|
1012
1022
|
}
|
|
1013
1023
|
} catch (error) {
|
|
1014
|
-
var _this$saveExperience3, _this$
|
|
1024
|
+
var _this$saveExperience3, _this$fireAnalyticsEv14;
|
|
1015
1025
|
success = false;
|
|
1016
1026
|
logException(error, {
|
|
1017
1027
|
location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
|
|
@@ -1022,7 +1032,7 @@ export class ReferenceSyncBlockStoreManager {
|
|
|
1022
1032
|
// No `resourceId` available in this catch — sourceProduct is intentionally omitted.
|
|
1023
1033
|
// No structured SyncBlockError/status here, so the attribution `reason` falls back
|
|
1024
1034
|
// to `unknown`.
|
|
1025
|
-
(_this$
|
|
1035
|
+
(_this$fireAnalyticsEv14 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv14 === void 0 ? void 0 : _this$fireAnalyticsEv14.call(this, updateReferenceErrorPayload(error.message, undefined, undefined, buildErrorAttribution()));
|
|
1026
1036
|
} finally {
|
|
1027
1037
|
if (!success) {
|
|
1028
1038
|
// set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
|
|
@@ -319,6 +319,29 @@ export const fetchSuccessPayload = (resourceId, blockInstanceId, sourceProduct)
|
|
|
319
319
|
})
|
|
320
320
|
}
|
|
321
321
|
});
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Per-request `syncedBlockGetSourceInfo` success event. Pairs with
|
|
325
|
+
* `getSourceInfoErrorPayload` so a success rate can be computed per request.
|
|
326
|
+
*/
|
|
327
|
+
export const getSourceInfoSuccessPayload = (resourceId, blockInstanceId, sourceProduct, sourceLocation) => ({
|
|
328
|
+
action: ACTION.FETCHED,
|
|
329
|
+
actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
|
|
330
|
+
actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_GET_SOURCE_INFO,
|
|
331
|
+
eventType: EVENT_TYPE.OPERATIONAL,
|
|
332
|
+
attributes: {
|
|
333
|
+
resourceId,
|
|
334
|
+
...(blockInstanceId && {
|
|
335
|
+
blockInstanceId
|
|
336
|
+
}),
|
|
337
|
+
...(sourceProduct && {
|
|
338
|
+
sourceProduct
|
|
339
|
+
}),
|
|
340
|
+
...(sourceLocation && {
|
|
341
|
+
sourceLocation
|
|
342
|
+
})
|
|
343
|
+
}
|
|
344
|
+
});
|
|
322
345
|
export const createSuccessPayload = (resourceId, sourceProduct, sourceLocation) => {
|
|
323
346
|
return {
|
|
324
347
|
action: ACTION.INSERTED,
|
|
@@ -14,7 +14,7 @@ import isEqual from 'lodash/isEqual';
|
|
|
14
14
|
import { logException } from '@atlaskit/editor-common/monitoring/error';
|
|
15
15
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
16
16
|
import { isProviderNotReadyError, ProviderNotReadyError, SyncBlockError } from '../common/types';
|
|
17
|
-
import { buildErrorAttribution, buildFetchErrorAttribution, cacheDeletionForcedPayload, fetchErrorPayload, fetchSuccessPayload, getSourceInfoErrorPayload, sourceInfoOrphanedPayload, updateReferenceErrorPayload } from '../utils/errorHandling';
|
|
17
|
+
import { buildErrorAttribution, buildFetchErrorAttribution, cacheDeletionForcedPayload, fetchErrorPayload, fetchSuccessPayload, getSourceInfoErrorPayload, getSourceInfoSuccessPayload, sourceInfoOrphanedPayload, updateReferenceErrorPayload } from '../utils/errorHandling';
|
|
18
18
|
import { getFetchExperience, getFetchSourceInfoExperience, getSaveReferenceExperience } from '../utils/experienceTracking';
|
|
19
19
|
import { getSourceLocation } from '../utils/fieldAwareLocations';
|
|
20
20
|
import { resolveSyncBlockInstance } from '../utils/resolveSyncBlockInstance';
|
|
@@ -428,15 +428,20 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
428
428
|
// `product` from cached data is preferred when available; fall back to parsing
|
|
429
429
|
// the resourceId.
|
|
430
430
|
var sourceProduct = product !== null && product !== void 0 ? product : getSourceProductFromResourceIdSafe(resourceId);
|
|
431
|
+
|
|
432
|
+
// With the experiment off, events and experience calls are identical to master.
|
|
433
|
+
var isPerRequestSourceInfo = isExperimentEnabled('platform_editor_blocks_patch_12');
|
|
431
434
|
if (!sourceAri || !product || !blockInstanceId) {
|
|
432
435
|
var _this$fireAnalyticsEv3;
|
|
433
|
-
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 || _this$fireAnalyticsEv3.call(this, getSourceInfoErrorPayload('SourceAri, product or blockInstanceId missing', resourceId, sourceProduct));
|
|
436
|
+
(_this$fireAnalyticsEv3 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv3 === void 0 || _this$fireAnalyticsEv3.call(this, getSourceInfoErrorPayload('SourceAri, product or blockInstanceId missing', resourceId, sourceProduct, isPerRequestSourceInfo ? getSourceLocation(sourceAri) : undefined));
|
|
434
437
|
return Promise.resolve(undefined);
|
|
435
438
|
}
|
|
436
439
|
var sourceLocation = getSourceLocation(sourceAri);
|
|
437
|
-
|
|
440
|
+
// The shared experience cannot count requests, so with the experiment on the
|
|
441
|
+
// per-request event below carries `sourceLocation` instead of the experience.
|
|
442
|
+
var experienceMetadata = !isPerRequestSourceInfo && sourceLocation ? {
|
|
438
443
|
sourceLocation: sourceLocation
|
|
439
|
-
};
|
|
444
|
+
} : undefined;
|
|
440
445
|
var withExperienceMetadata = function withExperienceMetadata(options) {
|
|
441
446
|
return experienceMetadata ? _objectSpread(_objectSpread({}, options), {}, {
|
|
442
447
|
metadata: experienceMetadata
|
|
@@ -467,20 +472,25 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
|
|
|
467
472
|
var _this2$fetchSourceInf3;
|
|
468
473
|
(_this2$fetchSourceInf3 = _this2.fetchSourceInfoExperience) === null || _this2$fetchSourceInf3 === void 0 || _this2$fetchSourceInf3.success();
|
|
469
474
|
}
|
|
475
|
+
// Pairs with the error event above as the per-request denominator.
|
|
476
|
+
if (isPerRequestSourceInfo && sourceLocation) {
|
|
477
|
+
var _this2$fireAnalyticsE2;
|
|
478
|
+
(_this2$fireAnalyticsE2 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE2 === void 0 || _this2$fireAnalyticsE2.call(_this2, getSourceInfoSuccessPayload(resourceId, blockInstanceId, sourceProduct, sourceLocation));
|
|
479
|
+
}
|
|
470
480
|
} else {
|
|
471
|
-
var _this2$fetchSourceInf4, _this2$
|
|
481
|
+
var _this2$fetchSourceInf4, _this2$fireAnalyticsE3;
|
|
472
482
|
(_this2$fetchSourceInf4 = _this2.fetchSourceInfoExperience) === null || _this2$fetchSourceInf4 === void 0 || _this2$fetchSourceInf4.failure(withExperienceMetadata({
|
|
473
483
|
reason: 'Missing title or url'
|
|
474
484
|
}));
|
|
475
|
-
(_this2$
|
|
485
|
+
(_this2$fireAnalyticsE3 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE3 === void 0 || _this2$fireAnalyticsE3.call(_this2, getSourceInfoErrorPayload('Missing title or url', resourceId, sourceProduct, sourceLocation));
|
|
476
486
|
}
|
|
477
487
|
return sourceInfo;
|
|
478
488
|
}).catch(function (error) {
|
|
479
|
-
var _this2$fetchSourceInf5, _this2$
|
|
489
|
+
var _this2$fetchSourceInf5, _this2$fireAnalyticsE4;
|
|
480
490
|
(_this2$fetchSourceInf5 = _this2.fetchSourceInfoExperience) === null || _this2$fetchSourceInf5 === void 0 || _this2$fetchSourceInf5.failure(withExperienceMetadata({
|
|
481
491
|
reason: error.message
|
|
482
492
|
}));
|
|
483
|
-
(_this2$
|
|
493
|
+
(_this2$fireAnalyticsE4 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE4 === void 0 || _this2$fireAnalyticsE4.call(_this2, getSourceInfoErrorPayload(error.message, resourceId, sourceProduct, sourceLocation));
|
|
484
494
|
return undefined;
|
|
485
495
|
}).finally(function () {
|
|
486
496
|
_this2.syncBlockSourceInfoRequests.delete(resourceId);
|
|
@@ -324,6 +324,28 @@ export var fetchSuccessPayload = function fetchSuccessPayload(resourceId, blockI
|
|
|
324
324
|
})
|
|
325
325
|
};
|
|
326
326
|
};
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Per-request `syncedBlockGetSourceInfo` success event. Pairs with
|
|
330
|
+
* `getSourceInfoErrorPayload` so a success rate can be computed per request.
|
|
331
|
+
*/
|
|
332
|
+
export var getSourceInfoSuccessPayload = function getSourceInfoSuccessPayload(resourceId, blockInstanceId, sourceProduct, sourceLocation) {
|
|
333
|
+
return {
|
|
334
|
+
action: ACTION.FETCHED,
|
|
335
|
+
actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
|
|
336
|
+
actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_GET_SOURCE_INFO,
|
|
337
|
+
eventType: EVENT_TYPE.OPERATIONAL,
|
|
338
|
+
attributes: _objectSpread(_objectSpread(_objectSpread({
|
|
339
|
+
resourceId: resourceId
|
|
340
|
+
}, blockInstanceId && {
|
|
341
|
+
blockInstanceId: blockInstanceId
|
|
342
|
+
}), sourceProduct && {
|
|
343
|
+
sourceProduct: sourceProduct
|
|
344
|
+
}), sourceLocation && {
|
|
345
|
+
sourceLocation: sourceLocation
|
|
346
|
+
})
|
|
347
|
+
};
|
|
348
|
+
};
|
|
327
349
|
export var createSuccessPayload = function createSuccessPayload(resourceId, sourceProduct, sourceLocation) {
|
|
328
350
|
return {
|
|
329
351
|
action: ACTION.INSERTED,
|
|
@@ -175,6 +175,11 @@ export declare const sourceInfoOrphanedPayload: (resourceId?: string, sourceProd
|
|
|
175
175
|
export declare const cacheDeletionForcedPayload: (rescheduleCount: number, resourceId?: string, sourceProduct?: string) => RendererSyncBlockEventPayload;
|
|
176
176
|
export declare const fetchReferencesErrorPayload: (error: string, resourceId?: string, sourceProduct?: string) => SyncBlockEventPayload;
|
|
177
177
|
export declare const fetchSuccessPayload: (resourceId: string, blockInstanceId?: string, sourceProduct?: string) => RendererSyncBlockEventPayload;
|
|
178
|
+
/**
|
|
179
|
+
* Per-request `syncedBlockGetSourceInfo` success event. Pairs with
|
|
180
|
+
* `getSourceInfoErrorPayload` so a success rate can be computed per request.
|
|
181
|
+
*/
|
|
182
|
+
export declare const getSourceInfoSuccessPayload: (resourceId: string, blockInstanceId?: string, sourceProduct?: string, sourceLocation?: SyncBlockSourceLocation) => RendererSyncBlockEventPayload;
|
|
178
183
|
export declare const createSuccessPayload: (resourceId: string, sourceProduct?: string, sourceLocation?: SyncBlockSourceLocation) => SyncBlockEventPayload;
|
|
179
184
|
/**
|
|
180
185
|
* Optional enrichment for the `syncedBlockCreate` success event. All fields
|
package/package.json
CHANGED
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
"@atlaskit/browser-apis": "^1.2.0",
|
|
21
21
|
"@atlaskit/editor-json-transformer": "^10.0.0",
|
|
22
22
|
"@atlaskit/editor-prosemirror": "^9.0.0",
|
|
23
|
-
"@atlaskit/emoji": "^73.
|
|
24
|
-
"@atlaskit/mention": "^30.
|
|
23
|
+
"@atlaskit/emoji": "^73.1.0",
|
|
24
|
+
"@atlaskit/mention": "^30.4.0",
|
|
25
25
|
"@atlaskit/node-data-provider": "^30.0.0",
|
|
26
26
|
"@atlaskit/platform-feature-experiments": "^0.3.0",
|
|
27
27
|
"@atlaskit/platform-feature-flags": "^2.2.0",
|
|
28
|
-
"@atlaskit/task-decision": "^21.
|
|
29
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
28
|
+
"@atlaskit/task-decision": "^21.13.0",
|
|
29
|
+
"@atlaskit/tmp-editor-statsig": "^245.0.0",
|
|
30
30
|
"@babel/runtime": "^7.0.0",
|
|
31
31
|
"@compiled/react": "^1.0.2",
|
|
32
32
|
"bind-event-listener": "^3.0.0",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"uuid": "^11.1.1"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@atlaskit/editor-common": "^133.
|
|
39
|
+
"@atlaskit/editor-common": "^133.5.0",
|
|
40
40
|
"react": "^18.2.0 || ^19.2.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"react-dom": "^19.2.0"
|
|
46
46
|
},
|
|
47
47
|
"name": "@atlaskit/editor-synced-block-provider",
|
|
48
|
-
"version": "25.0.
|
|
48
|
+
"version": "25.0.4",
|
|
49
49
|
"description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
|
|
50
50
|
"author": "Atlassian Pty Ltd",
|
|
51
51
|
"license": "Apache-2.0",
|