@atlaskit/editor-synced-block-provider 2.15.5 → 2.15.6

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,15 @@
1
1
  # @atlaskit/editor-synced-block-provider
2
2
 
3
+ ## 2.15.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [`d40079fdeef5d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d40079fdeef5d) -
8
+ EDITOR-4044 Fix a race condition in source sync block dirty tracking logic
9
+ - [`267f0abf6b4cf`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/267f0abf6b4cf) -
10
+ EDITOR-4044 Fix a race condition in reference sync block dirty tracking logic
11
+ - Updated dependencies
12
+
3
13
  ## 2.15.5
4
14
 
5
15
  ### Patch Changes
@@ -574,42 +574,50 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
574
574
  });
575
575
  });
576
576
  if (!(blocks.length === 0)) {
577
- _context4.next = 10;
577
+ _context4.next = 11;
578
578
  break;
579
579
  }
580
+ this.isCacheDirty = false;
580
581
  return _context4.abrupt("return", true);
581
- case 10:
582
- _context4.next = 12;
582
+ case 11:
583
+ // reset isCacheDirty early to prevent race condition
584
+ // There is a race condition where if a user makes changes (create/delete) to a reference sync block
585
+ // on a live page and the reference sync block is being saved while the user
586
+ // is still making changes, the new changes might not be saved if they all happen
587
+ // exactly at a time when the updateReferenceData is being executed asynchronously.
588
+ this.isCacheDirty = false;
589
+ _context4.next = 14;
583
590
  return this.dataProvider.updateReferenceData(blocks);
584
- case 12:
591
+ case 14:
585
592
  updateResult = _context4.sent;
586
593
  if (!updateResult.success) {
587
594
  success = false;
588
595
  (_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 || _this$fireAnalyticsEv9.call(this, (0, _errorHandling.updateReferenceErrorPayload)(updateResult.error || 'Failed to update reference synced blocks on the document'));
589
596
  }
590
- _context4.next = 21;
597
+ _context4.next = 23;
591
598
  break;
592
- case 16:
593
- _context4.prev = 16;
599
+ case 18:
600
+ _context4.prev = 18;
594
601
  _context4.t0 = _context4["catch"](3);
595
602
  success = false;
596
603
  (0, _monitoring.logException)(_context4.t0, {
597
604
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
598
605
  });
599
606
  (_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 || _this$fireAnalyticsEv0.call(this, (0, _errorHandling.updateReferenceErrorPayload)(_context4.t0.message));
600
- case 21:
601
- _context4.prev = 21;
602
- if (success) {
603
- this.isCacheDirty = false;
607
+ case 23:
608
+ _context4.prev = 23;
609
+ if (!success) {
610
+ // set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
611
+ this.isCacheDirty = true;
604
612
  }
605
- return _context4.finish(21);
606
- case 24:
613
+ return _context4.finish(23);
614
+ case 26:
607
615
  return _context4.abrupt("return", success);
608
- case 25:
616
+ case 27:
609
617
  case "end":
610
618
  return _context4.stop();
611
619
  }
612
- }, _callee3, this, [[3, 16, 21, 24]]);
620
+ }, _callee3, this, [[3, 18, 23, 26]]);
613
621
  }));
614
622
  function flush() {
615
623
  return _flush.apply(this, arguments);
@@ -109,6 +109,13 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
109
109
  }
110
110
  });
111
111
  bodiedSyncBlockData.push(syncBlockData);
112
+
113
+ // reset isDirty early to prevent race condition
114
+ // There is a race condition where if a user makes changes to a source sync block
115
+ // on a live page and the source sync block is being saved while the user
116
+ // is still making changes, the new changes might not be saved if they all happen
117
+ // exactly at a time when the writeNodesData is being executed asynchronously.
118
+ syncBlockData.isDirty = false;
112
119
  }
113
120
  });
114
121
  if (!(bodiedSyncBlockNodes.length === 0)) {
@@ -122,11 +129,11 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
122
129
  case 10:
123
130
  writeResults = _context.sent;
124
131
  writeResults.forEach(function (result) {
125
- // set isDirty to false on write success and unrecoverable errors like not found
126
- if (result.resourceId && (result.error === _types.SyncBlockError.NotFound || !result.error)) {
132
+ // set isDirty to true for cases where it failed to save the sync block to the BE
133
+ if (result.resourceId && result.error && result.error !== _types.SyncBlockError.NotFound) {
127
134
  var cachedData = _this2.syncBlockCache.get(result.resourceId);
128
135
  if (cachedData) {
129
- cachedData.isDirty = false;
136
+ cachedData.isDirty = true;
130
137
  }
131
138
  }
132
139
  });
@@ -441,8 +441,16 @@ export class ReferenceSyncBlockStoreManager {
441
441
  });
442
442
  });
443
443
  if (blocks.length === 0) {
444
+ this.isCacheDirty = false;
444
445
  return true;
445
446
  }
447
+
448
+ // reset isCacheDirty early to prevent race condition
449
+ // There is a race condition where if a user makes changes (create/delete) to a reference sync block
450
+ // on a live page and the reference sync block is being saved while the user
451
+ // is still making changes, the new changes might not be saved if they all happen
452
+ // exactly at a time when the updateReferenceData is being executed asynchronously.
453
+ this.isCacheDirty = false;
446
454
  const updateResult = await this.dataProvider.updateReferenceData(blocks);
447
455
  if (!updateResult.success) {
448
456
  var _this$fireAnalyticsEv10;
@@ -457,8 +465,9 @@ export class ReferenceSyncBlockStoreManager {
457
465
  });
458
466
  (_this$fireAnalyticsEv11 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv11 === void 0 ? void 0 : _this$fireAnalyticsEv11.call(this, updateReferenceErrorPayload(error.message));
459
467
  } finally {
460
- if (success) {
461
- this.isCacheDirty = false;
468
+ if (!success) {
469
+ // set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
470
+ this.isCacheDirty = true;
462
471
  }
463
472
  }
464
473
  return success;
@@ -82,6 +82,13 @@ export class SourceSyncBlockStoreManager {
82
82
  }
83
83
  });
84
84
  bodiedSyncBlockData.push(syncBlockData);
85
+
86
+ // reset isDirty early to prevent race condition
87
+ // There is a race condition where if a user makes changes to a source sync block
88
+ // on a live page and the source sync block is being saved while the user
89
+ // is still making changes, the new changes might not be saved if they all happen
90
+ // exactly at a time when the writeNodesData is being executed asynchronously.
91
+ syncBlockData.isDirty = false;
85
92
  }
86
93
  });
87
94
  if (bodiedSyncBlockNodes.length === 0) {
@@ -89,11 +96,11 @@ export class SourceSyncBlockStoreManager {
89
96
  }
90
97
  const writeResults = await this.dataProvider.writeNodesData(bodiedSyncBlockNodes, bodiedSyncBlockData);
91
98
  writeResults.forEach(result => {
92
- // set isDirty to false on write success and unrecoverable errors like not found
93
- if (result.resourceId && (result.error === SyncBlockError.NotFound || !result.error)) {
99
+ // set isDirty to true for cases where it failed to save the sync block to the BE
100
+ if (result.resourceId && result.error && result.error !== SyncBlockError.NotFound) {
94
101
  const cachedData = this.syncBlockCache.get(result.resourceId);
95
102
  if (cachedData) {
96
- cachedData.isDirty = false;
103
+ cachedData.isDirty = true;
97
104
  }
98
105
  }
99
106
  });
@@ -568,42 +568,50 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
568
568
  });
569
569
  });
570
570
  if (!(blocks.length === 0)) {
571
- _context4.next = 10;
571
+ _context4.next = 11;
572
572
  break;
573
573
  }
574
+ this.isCacheDirty = false;
574
575
  return _context4.abrupt("return", true);
575
- case 10:
576
- _context4.next = 12;
576
+ case 11:
577
+ // reset isCacheDirty early to prevent race condition
578
+ // There is a race condition where if a user makes changes (create/delete) to a reference sync block
579
+ // on a live page and the reference sync block is being saved while the user
580
+ // is still making changes, the new changes might not be saved if they all happen
581
+ // exactly at a time when the updateReferenceData is being executed asynchronously.
582
+ this.isCacheDirty = false;
583
+ _context4.next = 14;
577
584
  return this.dataProvider.updateReferenceData(blocks);
578
- case 12:
585
+ case 14:
579
586
  updateResult = _context4.sent;
580
587
  if (!updateResult.success) {
581
588
  success = false;
582
589
  (_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 || _this$fireAnalyticsEv9.call(this, updateReferenceErrorPayload(updateResult.error || 'Failed to update reference synced blocks on the document'));
583
590
  }
584
- _context4.next = 21;
591
+ _context4.next = 23;
585
592
  break;
586
- case 16:
587
- _context4.prev = 16;
593
+ case 18:
594
+ _context4.prev = 18;
588
595
  _context4.t0 = _context4["catch"](3);
589
596
  success = false;
590
597
  logException(_context4.t0, {
591
598
  location: 'editor-synced-block-provider/referenceSyncBlockStoreManager'
592
599
  });
593
600
  (_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 || _this$fireAnalyticsEv0.call(this, updateReferenceErrorPayload(_context4.t0.message));
594
- case 21:
595
- _context4.prev = 21;
596
- if (success) {
597
- this.isCacheDirty = false;
601
+ case 23:
602
+ _context4.prev = 23;
603
+ if (!success) {
604
+ // set isCacheDirty back to true for cases where it failed to update the reference synced blocks on the BE
605
+ this.isCacheDirty = true;
598
606
  }
599
- return _context4.finish(21);
600
- case 24:
607
+ return _context4.finish(23);
608
+ case 26:
601
609
  return _context4.abrupt("return", success);
602
- case 25:
610
+ case 27:
603
611
  case "end":
604
612
  return _context4.stop();
605
613
  }
606
- }, _callee3, this, [[3, 16, 21, 24]]);
614
+ }, _callee3, this, [[3, 18, 23, 26]]);
607
615
  }));
608
616
  function flush() {
609
617
  return _flush.apply(this, arguments);
@@ -103,6 +103,13 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
103
103
  }
104
104
  });
105
105
  bodiedSyncBlockData.push(syncBlockData);
106
+
107
+ // reset isDirty early to prevent race condition
108
+ // There is a race condition where if a user makes changes to a source sync block
109
+ // on a live page and the source sync block is being saved while the user
110
+ // is still making changes, the new changes might not be saved if they all happen
111
+ // exactly at a time when the writeNodesData is being executed asynchronously.
112
+ syncBlockData.isDirty = false;
106
113
  }
107
114
  });
108
115
  if (!(bodiedSyncBlockNodes.length === 0)) {
@@ -116,11 +123,11 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
116
123
  case 10:
117
124
  writeResults = _context.sent;
118
125
  writeResults.forEach(function (result) {
119
- // set isDirty to false on write success and unrecoverable errors like not found
120
- if (result.resourceId && (result.error === SyncBlockError.NotFound || !result.error)) {
126
+ // set isDirty to true for cases where it failed to save the sync block to the BE
127
+ if (result.resourceId && result.error && result.error !== SyncBlockError.NotFound) {
121
128
  var cachedData = _this2.syncBlockCache.get(result.resourceId);
122
129
  if (cachedData) {
123
- cachedData.isDirty = false;
130
+ cachedData.isDirty = true;
124
131
  }
125
132
  }
126
133
  });
package/package.json CHANGED
@@ -33,7 +33,7 @@
33
33
  "uuid": "^3.1.0"
34
34
  },
35
35
  "peerDependencies": {
36
- "@atlaskit/editor-common": "^110.46.0",
36
+ "@atlaskit/editor-common": "^110.48.0",
37
37
  "react": "^18.2.0"
38
38
  },
39
39
  "devDependencies": {
@@ -76,7 +76,7 @@
76
76
  }
77
77
  },
78
78
  "name": "@atlaskit/editor-synced-block-provider",
79
- "version": "2.15.5",
79
+ "version": "2.15.6",
80
80
  "description": "Synced Block Provider for @atlaskit/editor-plugin-synced-block",
81
81
  "author": "Atlassian Pty Ltd",
82
82
  "license": "Apache-2.0",