@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 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
- var experienceMetadata = sourceLocation && {
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$fireAnalyticsE2;
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$fireAnalyticsE2 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE2 === void 0 || _this2$fireAnalyticsE2.call(_this2, (0, _errorHandling.getSourceInfoErrorPayload)('Missing title or url', resourceId, sourceProduct, sourceLocation));
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$fireAnalyticsE3;
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$fireAnalyticsE3 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE3 === void 0 || _this2$fireAnalyticsE3.call(_this2, (0, _errorHandling.getSourceInfoErrorPayload)(error.message, resourceId, sourceProduct, sourceLocation));
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
- const experienceMetadata = sourceLocation && {
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$fireAnalyticsEv5;
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$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 ? void 0 : _this$fireAnalyticsEv5.call(this, getSourceInfoErrorPayload('Missing title or url', resourceId, sourceProduct, sourceLocation));
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$fireAnalyticsEv6;
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$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 ? void 0 : _this$fireAnalyticsEv6.call(this, getSourceInfoErrorPayload(error.message, resourceId, sourceProduct, sourceLocation));
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$fireAnalyticsEv7;
415
+ var _this$fireAnalyticsEv8;
406
416
  logException(error, {
407
417
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
408
418
  });
409
- (_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 ? void 0 : _this$fireAnalyticsEv7.call(this, getSourceInfoErrorPayload(error.message, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
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$fireAnalyticsEv8, _syncBlockInstance$er3, _syncBlockInstance$er4, _syncBlockInstance$er5;
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$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)));
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$fireAnalyticsEv9, _syncBlockInstance$da, _syncBlockInstance$da2;
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$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)));
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$fireAnalyticsEv0, _syncBlockInstance$da3, _syncBlockInstance$da4;
600
- (_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 ? void 0 : _this$fireAnalyticsEv0.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)));
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$fireAnalyticsEv1;
615
- (_this$fireAnalyticsEv1 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv1 === void 0 ? void 0 : _this$fireAnalyticsEv1.call(this, sourceInfoOrphanedPayload(resourceId, getSourceProductFromResourceIdSafe(resourceId), {
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$fireAnalyticsEv10;
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$fireAnalyticsEv10 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv10 === void 0 ? void 0 : _this$fireAnalyticsEv10.call(this, cacheDeletionForcedPayload(currentCount, resourceId, getSourceProductFromResourceIdSafe(resourceId)));
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$fireAnalyticsEv11;
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$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, fetchErrorPayload(error.message, undefined, undefined, buildFetchErrorAttribution(error.message)));
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$fireAnalyticsEv12;
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$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)));
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$fireAnalyticsEv13;
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$fireAnalyticsEv13 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv13 === void 0 ? void 0 : _this$fireAnalyticsEv13.call(this, updateReferenceErrorPayload(error.message, undefined, undefined, buildErrorAttribution()));
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
- var experienceMetadata = sourceLocation && {
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$fireAnalyticsE2;
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$fireAnalyticsE2 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE2 === void 0 || _this2$fireAnalyticsE2.call(_this2, getSourceInfoErrorPayload('Missing title or url', resourceId, sourceProduct, sourceLocation));
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$fireAnalyticsE3;
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$fireAnalyticsE3 = _this2.fireAnalyticsEvent) === null || _this2$fireAnalyticsE3 === void 0 || _this2$fireAnalyticsE3.call(_this2, getSourceInfoErrorPayload(error.message, resourceId, sourceProduct, sourceLocation));
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.0.0",
24
- "@atlaskit/mention": "^30.3.0",
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.12.0",
29
- "@atlaskit/tmp-editor-statsig": "^244.0.0",
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.1.0",
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.2",
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",