@atlaskit/collab-provider 9.22.7 → 9.22.8

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,12 @@
1
1
  # @atlaskit/collab-provider
2
2
 
3
+ ## 9.22.8
4
+
5
+ ### Patch Changes
6
+
7
+ - [#71421](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/71421) [`27695a18c13c`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/27695a18c13c) - Update the recovery process to use reconcile instead of applying local steps
8
+ - Updated dependencies
9
+
3
10
  ## 9.22.7
4
11
 
5
12
  ### Patch Changes
@@ -230,7 +230,7 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
230
230
  metadata: metadata
231
231
  });
232
232
  } else {
233
- // Page is been just restored, need to fix all the participants as well.
233
+ // Page has just been restored, need to fix all the participants as well.
234
234
  var _doc = data.doc,
235
235
  _version = data.version,
236
236
  _userId = data.userId,
@@ -48,6 +48,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
48
48
  function DocumentService(participantsService, analyticsHelper, fetchCatchup, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService) {
49
49
  var _this = this;
50
50
  var enableErrorOnFailedDocumentApply = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
51
+ var reconcileOnRecovery = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;
51
52
  (0, _classCallCheck2.default)(this, DocumentService);
52
53
  // Fires analytics to editor when collab editor cannot sync up
53
54
  (0, _defineProperty2.default)(this, "stepRejectCounter", 0);
@@ -238,81 +239,115 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
238
239
  }
239
240
  });
240
241
  // Triggered when page recovery has emitted an 'init' event on a page client is currently connected to.
241
- (0, _defineProperty2.default)(this, "onRestore", function (_ref4) {
242
- var doc = _ref4.doc,
243
- version = _ref4.version,
244
- metadata = _ref4.metadata;
245
- // Preserve the unconfirmed steps to prevent data loss.
246
- var unconfirmedSteps = _this.getUnconfirmedSteps();
247
- try {
248
- var _this$analyticsHelper11;
249
- // Reset the editor,
250
- // - Replace the document, keep in sync with the server
251
- // - Replace the version number, so editor is in sync with NCS server and can commit new changes.
252
- // - Replace the metadata
253
- // - Reserve the cursor position, in case a cursor jump.
242
+ (0, _defineProperty2.default)(this, "onRestore", /*#__PURE__*/function () {
243
+ var _ref5 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(_ref4) {
244
+ var doc, version, metadata, unconfirmedSteps, currentState, _this$analyticsHelper11, _this$analyticsHelper12, _this$analyticsHelper13;
245
+ return _regenerator.default.wrap(function _callee3$(_context3) {
246
+ while (1) switch (_context3.prev = _context3.next) {
247
+ case 0:
248
+ doc = _ref4.doc, version = _ref4.version, metadata = _ref4.metadata;
249
+ // We preserve these as they will be lost apon this.updateDocument. This is because we are using document recovery.
250
+ // We can then reconcile the document with the preserved state.
251
+ unconfirmedSteps = _this.getUnconfirmedSteps();
252
+ if (!_this.reconcileOnRecovery) {
253
+ _context3.next = 6;
254
+ break;
255
+ }
256
+ _context3.next = 5;
257
+ return _this.getCurrentState();
258
+ case 5:
259
+ currentState = _context3.sent;
260
+ case 6:
261
+ _context3.prev = 6;
262
+ // Reset the editor,
263
+ // - Replace the document, keep in sync with the server
264
+ // - Replace the version number, so editor is in sync with NCS server and can commit new changes.
265
+ // - Replace the metadata
266
+ // - Reserve the cursor position, in case a cursor jump.
254
267
 
255
- _this.updateDocument({
256
- doc: doc,
257
- version: version,
258
- metadata: metadata,
259
- reserveCursor: true
260
- });
261
- _this.metadataService.updateMetadata(metadata);
268
+ _this.updateDocument({
269
+ doc: doc,
270
+ version: version,
271
+ metadata: metadata,
272
+ reserveCursor: true
273
+ });
274
+ _this.metadataService.updateMetadata(metadata);
262
275
 
263
- // Re-apply the unconfirmed steps, not 100% of them can be applied, if document is changed significantly.
264
- if (unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length) {
265
- _this.applyLocalSteps(unconfirmedSteps);
266
- }
267
- (_this$analyticsHelper11 = _this.analyticsHelper) === null || _this$analyticsHelper11 === void 0 || _this$analyticsHelper11.sendActionEvent(_const.EVENT_ACTION.REINITIALISE_DOCUMENT, _const.EVENT_STATUS.SUCCESS, {
268
- numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length,
269
- hasTitle: !!(metadata !== null && metadata !== void 0 && metadata.title)
270
- });
271
- } catch (restoreError) {
272
- var _this$analyticsHelper12, _this$analyticsHelper13;
273
- (_this$analyticsHelper12 = _this.analyticsHelper) === null || _this$analyticsHelper12 === void 0 || _this$analyticsHelper12.sendActionEvent(_const.EVENT_ACTION.REINITIALISE_DOCUMENT, _const.EVENT_STATUS.FAILURE, {
274
- numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length
275
- });
276
- (_this$analyticsHelper13 = _this.analyticsHelper) === null || _this$analyticsHelper13 === void 0 || _this$analyticsHelper13.sendErrorEvent(restoreError, 'Error while reinitialising document');
277
- _this.onErrorHandled({
278
- message: 'Caught error while trying to recover the document',
279
- data: {
280
- status: 500,
281
- // Meaningless, remove when we review error structure
282
- code: _internalErrors.INTERNAL_ERROR_CODE.DOCUMENT_RESTORE_ERROR
276
+ // If there are unconfirmed steps, attempt to reconcile our current state with with recovered document
277
+ if (!(unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length && _this.reconcileOnRecovery && currentState)) {
278
+ _context3.next = 14;
279
+ break;
280
+ }
281
+ _context3.next = 12;
282
+ return _this.fetchReconcile(JSON.stringify(currentState.content));
283
+ case 12:
284
+ _context3.next = 15;
285
+ break;
286
+ case 14:
287
+ if (unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length) {
288
+ _this.applyLocalSteps(unconfirmedSteps);
289
+ }
290
+ case 15:
291
+ (_this$analyticsHelper11 = _this.analyticsHelper) === null || _this$analyticsHelper11 === void 0 || _this$analyticsHelper11.sendActionEvent(_const.EVENT_ACTION.REINITIALISE_DOCUMENT, _const.EVENT_STATUS.SUCCESS, {
292
+ numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length,
293
+ hasTitle: !!(metadata !== null && metadata !== void 0 && metadata.title)
294
+ });
295
+ _context3.next = 23;
296
+ break;
297
+ case 18:
298
+ _context3.prev = 18;
299
+ _context3.t0 = _context3["catch"](6);
300
+ (_this$analyticsHelper12 = _this.analyticsHelper) === null || _this$analyticsHelper12 === void 0 || _this$analyticsHelper12.sendActionEvent(_const.EVENT_ACTION.REINITIALISE_DOCUMENT, _const.EVENT_STATUS.FAILURE, {
301
+ numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length
302
+ });
303
+ (_this$analyticsHelper13 = _this.analyticsHelper) === null || _this$analyticsHelper13 === void 0 || _this$analyticsHelper13.sendErrorEvent(_context3.t0, 'Error while reinitialising document');
304
+ _this.onErrorHandled({
305
+ message: 'Caught error while trying to recover the document',
306
+ data: {
307
+ status: 500,
308
+ // Meaningless, remove when we review error structure
309
+ code: _internalErrors.INTERNAL_ERROR_CODE.DOCUMENT_RESTORE_ERROR
310
+ }
311
+ });
312
+ case 23:
313
+ case "end":
314
+ return _context3.stop();
283
315
  }
284
- });
285
- }
286
- });
287
- (0, _defineProperty2.default)(this, "getFinalAcknowledgedState", /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3() {
316
+ }, _callee3, null, [[6, 18]]);
317
+ }));
318
+ return function (_x) {
319
+ return _ref5.apply(this, arguments);
320
+ };
321
+ }());
322
+ (0, _defineProperty2.default)(this, "getFinalAcknowledgedState", /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4() {
288
323
  var _this$analyticsHelper14, finalAcknowledgedState, currentState, reconcileResponse, measure, _this$analyticsHelper15, _this$analyticsHelper16, _measure2;
289
- return _regenerator.default.wrap(function _callee3$(_context3) {
290
- while (1) switch (_context3.prev = _context3.next) {
324
+ return _regenerator.default.wrap(function _callee4$(_context4) {
325
+ while (1) switch (_context4.prev = _context4.next) {
291
326
  case 0:
292
327
  _this.aggressiveCatchup = true;
293
- _context3.prev = 1;
328
+ _context4.prev = 1;
294
329
  (0, _performance.startMeasure)(_performance.MEASURE_NAME.PUBLISH_PAGE, _this.analyticsHelper);
295
- _context3.prev = 3;
296
- _context3.next = 6;
330
+ _context4.prev = 3;
331
+ _context4.next = 6;
297
332
  return _this.commitUnconfirmedSteps();
298
333
  case 6:
299
- _context3.next = 8;
334
+ _context4.next = 8;
300
335
  return _this.getCurrentState();
301
336
  case 8:
302
- finalAcknowledgedState = _context3.sent;
303
- _context3.next = 20;
337
+ finalAcknowledgedState = _context4.sent;
338
+ _context4.next = 20;
304
339
  break;
305
340
  case 11:
306
- _context3.prev = 11;
307
- _context3.t0 = _context3["catch"](3);
308
- _context3.next = 15;
341
+ _context4.prev = 11;
342
+ _context4.t0 = _context4["catch"](3);
343
+ _context4.next = 15;
309
344
  return _this.getCurrentState();
310
345
  case 15:
311
- currentState = _context3.sent;
312
- _context3.next = 18;
346
+ currentState = _context4.sent;
347
+ _context4.next = 18;
313
348
  return _this.fetchReconcile(JSON.stringify(currentState.content));
314
349
  case 18:
315
- reconcileResponse = _context3.sent;
350
+ reconcileResponse = _context4.sent;
316
351
  finalAcknowledgedState = {
317
352
  content: JSON.parse(reconcileResponse.document),
318
353
  title: currentState.title,
@@ -324,28 +359,28 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
324
359
  latency: measure === null || measure === void 0 ? void 0 : measure.duration
325
360
  });
326
361
  _this.aggressiveCatchup = false;
327
- return _context3.abrupt("return", finalAcknowledgedState);
362
+ return _context4.abrupt("return", finalAcknowledgedState);
328
363
  case 26:
329
- _context3.prev = 26;
330
- _context3.t1 = _context3["catch"](1);
364
+ _context4.prev = 26;
365
+ _context4.t1 = _context4["catch"](1);
331
366
  _this.aggressiveCatchup = false;
332
367
  _measure2 = (0, _performance.stopMeasure)(_performance.MEASURE_NAME.PUBLISH_PAGE, _this.analyticsHelper);
333
368
  (_this$analyticsHelper15 = _this.analyticsHelper) === null || _this$analyticsHelper15 === void 0 || _this$analyticsHelper15.sendActionEvent(_const.EVENT_ACTION.PUBLISH_PAGE, _const.EVENT_STATUS.FAILURE, {
334
369
  latency: _measure2 === null || _measure2 === void 0 ? void 0 : _measure2.duration
335
370
  });
336
- (_this$analyticsHelper16 = _this.analyticsHelper) === null || _this$analyticsHelper16 === void 0 || _this$analyticsHelper16.sendErrorEvent(_context3.t1, 'Error while returning ADF version of the final draft document');
337
- throw _context3.t1;
371
+ (_this$analyticsHelper16 = _this.analyticsHelper) === null || _this$analyticsHelper16 === void 0 || _this$analyticsHelper16.sendErrorEvent(_context4.t1, 'Error while returning ADF version of the final draft document');
372
+ throw _context4.t1;
338
373
  case 33:
339
374
  case "end":
340
- return _context3.stop();
375
+ return _context4.stop();
341
376
  }
342
- }, _callee3, null, [[1, 26], [3, 11]]);
377
+ }, _callee4, null, [[1, 26], [3, 11]]);
343
378
  })));
344
- (0, _defineProperty2.default)(this, "updateDocument", function (_ref6) {
345
- var doc = _ref6.doc,
346
- version = _ref6.version,
347
- metadata = _ref6.metadata,
348
- reserveCursor = _ref6.reserveCursor;
379
+ (0, _defineProperty2.default)(this, "updateDocument", function (_ref7) {
380
+ var doc = _ref7.doc,
381
+ version = _ref7.version,
382
+ metadata = _ref7.metadata,
383
+ reserveCursor = _ref7.reserveCursor;
349
384
  _this.providerEmitCallback('init', _objectSpread({
350
385
  doc: doc,
351
386
  version: version,
@@ -421,15 +456,15 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
421
456
  * Commit the unconfirmed local steps to the back-end service
422
457
  * @throws {Error} Couldn't sync the steps after retrying 30 times
423
458
  */
424
- (0, _defineProperty2.default)(this, "commitUnconfirmedSteps", /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4() {
459
+ (0, _defineProperty2.default)(this, "commitUnconfirmedSteps", /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5() {
425
460
  var unconfirmedSteps, _this$getState6, _this$analyticsHelper21, count, unconfirmedTrs, lastTr, isLastTrConfirmed, _this$analyticsHelper20, nextUnconfirmedSteps, nextUnconfirmedTrs, _this$getUnconfirmedS, state, unconfirmedStepsInfoUGCRemoved, _error2, measure, _this$analyticsHelper22, _this$analyticsHelper23, _measure3;
426
- return _regenerator.default.wrap(function _callee4$(_context4) {
427
- while (1) switch (_context4.prev = _context4.next) {
461
+ return _regenerator.default.wrap(function _callee5$(_context5) {
462
+ while (1) switch (_context5.prev = _context5.next) {
428
463
  case 0:
429
464
  unconfirmedSteps = _this.getUnconfirmedSteps();
430
- _context4.prev = 1;
465
+ _context5.prev = 1;
431
466
  if (!(unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length)) {
432
- _context4.next = 24;
467
+ _context5.next = 24;
433
468
  break;
434
469
  }
435
470
  (0, _performance.startMeasure)(_performance.MEASURE_NAME.COMMIT_UNCONFIRMED_STEPS, _this.analyticsHelper);
@@ -445,11 +480,11 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
445
480
  }
446
481
  case 9:
447
482
  if (isLastTrConfirmed) {
448
- _context4.next = 22;
483
+ _context5.next = 22;
449
484
  break;
450
485
  }
451
486
  _this.sendStepsFromCurrentState();
452
- _context4.next = 13;
487
+ _context5.next = 13;
453
488
  return (0, _utils.sleep)(500);
454
489
  case 13:
455
490
  nextUnconfirmedSteps = _this.getUnconfirmedSteps();
@@ -462,7 +497,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
462
497
  isLastTrConfirmed = true;
463
498
  }
464
499
  if (!(!isLastTrConfirmed && count++ >= _const.ACK_MAX_TRY)) {
465
- _context4.next = 20;
500
+ _context5.next = 20;
466
501
  break;
467
502
  }
468
503
  if (_this.onSyncUpError) {
@@ -483,7 +518,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
483
518
  });
484
519
  throw _error2;
485
520
  case 20:
486
- _context4.next = 9;
521
+ _context5.next = 9;
487
522
  break;
488
523
  case 22:
489
524
  measure = (0, _performance.stopMeasure)(_performance.MEASURE_NAME.COMMIT_UNCONFIRMED_STEPS, _this.analyticsHelper);
@@ -493,23 +528,23 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
493
528
  numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length
494
529
  });
495
530
  case 24:
496
- _context4.next = 32;
531
+ _context5.next = 32;
497
532
  break;
498
533
  case 26:
499
- _context4.prev = 26;
500
- _context4.t0 = _context4["catch"](1);
534
+ _context5.prev = 26;
535
+ _context5.t0 = _context5["catch"](1);
501
536
  _measure3 = (0, _performance.stopMeasure)(_performance.MEASURE_NAME.COMMIT_UNCONFIRMED_STEPS, _this.analyticsHelper);
502
537
  (_this$analyticsHelper22 = _this.analyticsHelper) === null || _this$analyticsHelper22 === void 0 || _this$analyticsHelper22.sendActionEvent(_const.EVENT_ACTION.COMMIT_UNCONFIRMED_STEPS, _const.EVENT_STATUS.FAILURE, {
503
538
  latency: _measure3 === null || _measure3 === void 0 ? void 0 : _measure3.duration,
504
539
  numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length
505
540
  });
506
- (_this$analyticsHelper23 = _this.analyticsHelper) === null || _this$analyticsHelper23 === void 0 || _this$analyticsHelper23.sendErrorEvent(_context4.t0, 'Error while committing unconfirmed steps');
507
- throw _context4.t0;
541
+ (_this$analyticsHelper23 = _this.analyticsHelper) === null || _this$analyticsHelper23 === void 0 || _this$analyticsHelper23.sendErrorEvent(_context5.t0, 'Error while committing unconfirmed steps');
542
+ throw _context5.t0;
508
543
  case 32:
509
544
  case "end":
510
- return _context4.stop();
545
+ return _context5.stop();
511
546
  }
512
- }, _callee4, null, [[1, 26]]);
547
+ }, _callee5, null, [[1, 26]]);
513
548
  })));
514
549
  (0, _defineProperty2.default)(this, "onStepRejectedError", function () {
515
550
  var _this$analyticsHelper24;
@@ -544,6 +579,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
544
579
  this.onErrorHandled = onErrorHandled;
545
580
  this.metadataService = metadataService;
546
581
  this.enableErrorOnFailedDocumentApply = enableErrorOnFailedDocumentApply;
582
+ this.reconcileOnRecovery = reconcileOnRecovery;
547
583
  this.stepQueue = new _stepQueueState.StepQueueState();
548
584
  }
549
585
  (0, _createClass2.default)(DocumentService, [{
@@ -575,8 +611,8 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
575
611
  logger("Processing data. Version \"".concat(version, "\"."));
576
612
  if (steps !== null && steps !== void 0 && steps.length) {
577
613
  try {
578
- var clientIds = steps.map(function (_ref8) {
579
- var clientId = _ref8.clientId;
614
+ var clientIds = steps.map(function (_ref9) {
615
+ var clientId = _ref9.clientId;
580
616
  return clientId;
581
617
  });
582
618
  this.providerEmitCallback('data', {
@@ -604,10 +640,10 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
604
640
  }
605
641
  }, {
606
642
  key: "setup",
607
- value: function setup(_ref9) {
608
- var getState = _ref9.getState,
609
- onSyncUpError = _ref9.onSyncUpError,
610
- clientId = _ref9.clientId;
643
+ value: function setup(_ref10) {
644
+ var getState = _ref10.getState,
645
+ onSyncUpError = _ref10.onSyncUpError,
646
+ clientId = _ref10.clientId;
611
647
  this.getState = getState;
612
648
  this.onSyncUpError = onSyncUpError || noop;
613
649
  this.clientId = clientId;
@@ -9,7 +9,8 @@ exports.getProductSpecificFeatureFlags = void 0;
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var defaultNCSFeatureFlags = {
11
11
  testFF: false,
12
- blockViewOnly: false
12
+ blockViewOnly: false,
13
+ reconcileOnRecovery: false
13
14
  };
14
15
 
15
16
  /**
@@ -18,7 +19,8 @@ var defaultNCSFeatureFlags = {
18
19
  var productKeys = {
19
20
  confluence: {
20
21
  testFF: 'confluence.frontend.collab.provider.testFF',
21
- blockViewOnly: 'confluence.frontend.ncs.block-view-only'
22
+ blockViewOnly: 'confluence.frontend.ncs.block-view-only',
23
+ reconcileOnRecovery: 'confluence.frontend.ncs.reconcile-on-recovery'
22
24
  }
23
25
  };
24
26
  var filterFeatureFlagNames = function filterFeatureFlagNames(flags) {
@@ -265,9 +265,10 @@ var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
265
265
  _this.isProviderInitialized = false;
266
266
  _this.participantsService = new _participantsService.ParticipantsService(_this.analyticsHelper, undefined, _this.emitCallback, _this.config.getUser, _this.channel.broadcast, _this.channel.sendPresenceJoined, _this.getPresenceData, _this.setUserId);
267
267
  _this.metadataService = new _metadataService.MetadataService(_this.emitCallback, _this.channel.sendMetadata);
268
+ var reconcileOnRecovery = (0, _featureFlags.getCollabProviderFeatureFlag)('reconcileOnRecovery', _this.config.featureFlags);
268
269
  _this.documentService = new _documentService.DocumentService(_this.participantsService, _this.analyticsHelper, _this.channel.fetchCatchup, _this.channel.fetchReconcile, _this.emitCallback, _this.channel.broadcast, function () {
269
270
  return _this.userId;
270
- }, _this.onErrorHandled, _this.metadataService, _this.config.enableErrorOnFailedDocumentApply);
271
+ }, _this.onErrorHandled, _this.metadataService, _this.config.enableErrorOnFailedDocumentApply, reconcileOnRecovery);
271
272
  _this.namespaceService = new _namespaceService.NamespaceService();
272
273
  _this.api = new _api.Api(config, _this.documentService, _this.channel);
273
274
  _this.sendStepsTimer = setInterval(function () {
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.version = exports.nextMajorVersion = exports.name = void 0;
7
7
  var name = exports.name = "@atlaskit/collab-provider";
8
- var version = exports.version = "9.22.7";
8
+ var version = exports.version = "9.22.8";
9
9
  var nextMajorVersion = exports.nextMajorVersion = function nextMajorVersion() {
10
10
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
11
11
  };
@@ -161,7 +161,7 @@ export class Channel extends Emitter {
161
161
  metadata
162
162
  });
163
163
  } else {
164
- // Page is been just restored, need to fix all the participants as well.
164
+ // Page has just been restored, need to fix all the participants as well.
165
165
  const {
166
166
  doc,
167
167
  version,
@@ -32,7 +32,7 @@ export class DocumentService {
32
32
  * @param metadataService
33
33
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
34
34
  */
35
- constructor(participantsService, analyticsHelper, fetchCatchup, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService, enableErrorOnFailedDocumentApply = false) {
35
+ constructor(participantsService, analyticsHelper, fetchCatchup, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService, enableErrorOnFailedDocumentApply = false, reconcileOnRecovery = false) {
36
36
  // Fires analytics to editor when collab editor cannot sync up
37
37
  _defineProperty(this, "stepRejectCounter", 0);
38
38
  _defineProperty(this, "aggressiveCatchup", false);
@@ -196,13 +196,18 @@ export class DocumentService {
196
196
  }
197
197
  });
198
198
  // Triggered when page recovery has emitted an 'init' event on a page client is currently connected to.
199
- _defineProperty(this, "onRestore", ({
199
+ _defineProperty(this, "onRestore", async ({
200
200
  doc,
201
201
  version,
202
202
  metadata
203
203
  }) => {
204
- // Preserve the unconfirmed steps to prevent data loss.
204
+ // We preserve these as they will be lost apon this.updateDocument. This is because we are using document recovery.
205
+ // We can then reconcile the document with the preserved state.
205
206
  const unconfirmedSteps = this.getUnconfirmedSteps();
207
+ let currentState;
208
+ if (this.reconcileOnRecovery) {
209
+ currentState = await this.getCurrentState();
210
+ }
206
211
  try {
207
212
  var _this$analyticsHelper11;
208
213
  // Reset the editor,
@@ -219,8 +224,10 @@ export class DocumentService {
219
224
  });
220
225
  this.metadataService.updateMetadata(metadata);
221
226
 
222
- // Re-apply the unconfirmed steps, not 100% of them can be applied, if document is changed significantly.
223
- if (unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length) {
227
+ // If there are unconfirmed steps, attempt to reconcile our current state with with recovered document
228
+ if (unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length && this.reconcileOnRecovery && currentState) {
229
+ await this.fetchReconcile(JSON.stringify(currentState.content));
230
+ } else if (unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length) {
224
231
  this.applyLocalSteps(unconfirmedSteps);
225
232
  }
226
233
  (_this$analyticsHelper11 = this.analyticsHelper) === null || _this$analyticsHelper11 === void 0 ? void 0 : _this$analyticsHelper11.sendActionEvent(EVENT_ACTION.REINITIALISE_DOCUMENT, EVENT_STATUS.SUCCESS, {
@@ -455,6 +462,7 @@ export class DocumentService {
455
462
  this.onErrorHandled = onErrorHandled;
456
463
  this.metadataService = metadataService;
457
464
  this.enableErrorOnFailedDocumentApply = enableErrorOnFailedDocumentApply;
465
+ this.reconcileOnRecovery = reconcileOnRecovery;
458
466
  this.stepQueue = new StepQueueState();
459
467
  }
460
468
  processQueue() {
@@ -1,6 +1,7 @@
1
1
  const defaultNCSFeatureFlags = {
2
2
  testFF: false,
3
- blockViewOnly: false
3
+ blockViewOnly: false,
4
+ reconcileOnRecovery: false
4
5
  };
5
6
 
6
7
  /**
@@ -9,7 +10,8 @@ const defaultNCSFeatureFlags = {
9
10
  const productKeys = {
10
11
  confluence: {
11
12
  testFF: 'confluence.frontend.collab.provider.testFF',
12
- blockViewOnly: 'confluence.frontend.ncs.block-view-only'
13
+ blockViewOnly: 'confluence.frontend.ncs.block-view-only',
14
+ reconcileOnRecovery: 'confluence.frontend.ncs.reconcile-on-recovery'
13
15
  }
14
16
  };
15
17
  const filterFeatureFlagNames = flags => {
@@ -220,7 +220,8 @@ export class Provider extends Emitter {
220
220
  this.isProviderInitialized = false;
221
221
  this.participantsService = new ParticipantsService(this.analyticsHelper, undefined, this.emitCallback, this.config.getUser, this.channel.broadcast, this.channel.sendPresenceJoined, this.getPresenceData, this.setUserId);
222
222
  this.metadataService = new MetadataService(this.emitCallback, this.channel.sendMetadata);
223
- this.documentService = new DocumentService(this.participantsService, this.analyticsHelper, this.channel.fetchCatchup, this.channel.fetchReconcile, this.emitCallback, this.channel.broadcast, () => this.userId, this.onErrorHandled, this.metadataService, this.config.enableErrorOnFailedDocumentApply);
223
+ const reconcileOnRecovery = getCollabProviderFeatureFlag('reconcileOnRecovery', this.config.featureFlags);
224
+ this.documentService = new DocumentService(this.participantsService, this.analyticsHelper, this.channel.fetchCatchup, this.channel.fetchReconcile, this.emitCallback, this.channel.broadcast, () => this.userId, this.onErrorHandled, this.metadataService, this.config.enableErrorOnFailedDocumentApply, reconcileOnRecovery);
224
225
  this.namespaceService = new NamespaceService();
225
226
  this.api = new Api(config, this.documentService, this.channel);
226
227
  this.sendStepsTimer = setInterval(() => {
@@ -1,5 +1,5 @@
1
1
  export const name = "@atlaskit/collab-provider";
2
- export const version = "9.22.7";
2
+ export const version = "9.22.8";
3
3
  export const nextMajorVersion = () => {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -223,7 +223,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
223
223
  metadata: metadata
224
224
  });
225
225
  } else {
226
- // Page is been just restored, need to fix all the participants as well.
226
+ // Page has just been restored, need to fix all the participants as well.
227
227
  var _doc = data.doc,
228
228
  _version = data.version,
229
229
  _userId = data.userId,
@@ -41,6 +41,7 @@ export var DocumentService = /*#__PURE__*/function () {
41
41
  function DocumentService(participantsService, analyticsHelper, fetchCatchup, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService) {
42
42
  var _this = this;
43
43
  var enableErrorOnFailedDocumentApply = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
44
+ var reconcileOnRecovery = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;
44
45
  _classCallCheck(this, DocumentService);
45
46
  // Fires analytics to editor when collab editor cannot sync up
46
47
  _defineProperty(this, "stepRejectCounter", 0);
@@ -231,81 +232,115 @@ export var DocumentService = /*#__PURE__*/function () {
231
232
  }
232
233
  });
233
234
  // Triggered when page recovery has emitted an 'init' event on a page client is currently connected to.
234
- _defineProperty(this, "onRestore", function (_ref4) {
235
- var doc = _ref4.doc,
236
- version = _ref4.version,
237
- metadata = _ref4.metadata;
238
- // Preserve the unconfirmed steps to prevent data loss.
239
- var unconfirmedSteps = _this.getUnconfirmedSteps();
240
- try {
241
- var _this$analyticsHelper11;
242
- // Reset the editor,
243
- // - Replace the document, keep in sync with the server
244
- // - Replace the version number, so editor is in sync with NCS server and can commit new changes.
245
- // - Replace the metadata
246
- // - Reserve the cursor position, in case a cursor jump.
235
+ _defineProperty(this, "onRestore", /*#__PURE__*/function () {
236
+ var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref4) {
237
+ var doc, version, metadata, unconfirmedSteps, currentState, _this$analyticsHelper11, _this$analyticsHelper12, _this$analyticsHelper13;
238
+ return _regeneratorRuntime.wrap(function _callee3$(_context3) {
239
+ while (1) switch (_context3.prev = _context3.next) {
240
+ case 0:
241
+ doc = _ref4.doc, version = _ref4.version, metadata = _ref4.metadata;
242
+ // We preserve these as they will be lost apon this.updateDocument. This is because we are using document recovery.
243
+ // We can then reconcile the document with the preserved state.
244
+ unconfirmedSteps = _this.getUnconfirmedSteps();
245
+ if (!_this.reconcileOnRecovery) {
246
+ _context3.next = 6;
247
+ break;
248
+ }
249
+ _context3.next = 5;
250
+ return _this.getCurrentState();
251
+ case 5:
252
+ currentState = _context3.sent;
253
+ case 6:
254
+ _context3.prev = 6;
255
+ // Reset the editor,
256
+ // - Replace the document, keep in sync with the server
257
+ // - Replace the version number, so editor is in sync with NCS server and can commit new changes.
258
+ // - Replace the metadata
259
+ // - Reserve the cursor position, in case a cursor jump.
247
260
 
248
- _this.updateDocument({
249
- doc: doc,
250
- version: version,
251
- metadata: metadata,
252
- reserveCursor: true
253
- });
254
- _this.metadataService.updateMetadata(metadata);
261
+ _this.updateDocument({
262
+ doc: doc,
263
+ version: version,
264
+ metadata: metadata,
265
+ reserveCursor: true
266
+ });
267
+ _this.metadataService.updateMetadata(metadata);
255
268
 
256
- // Re-apply the unconfirmed steps, not 100% of them can be applied, if document is changed significantly.
257
- if (unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length) {
258
- _this.applyLocalSteps(unconfirmedSteps);
259
- }
260
- (_this$analyticsHelper11 = _this.analyticsHelper) === null || _this$analyticsHelper11 === void 0 || _this$analyticsHelper11.sendActionEvent(EVENT_ACTION.REINITIALISE_DOCUMENT, EVENT_STATUS.SUCCESS, {
261
- numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length,
262
- hasTitle: !!(metadata !== null && metadata !== void 0 && metadata.title)
263
- });
264
- } catch (restoreError) {
265
- var _this$analyticsHelper12, _this$analyticsHelper13;
266
- (_this$analyticsHelper12 = _this.analyticsHelper) === null || _this$analyticsHelper12 === void 0 || _this$analyticsHelper12.sendActionEvent(EVENT_ACTION.REINITIALISE_DOCUMENT, EVENT_STATUS.FAILURE, {
267
- numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length
268
- });
269
- (_this$analyticsHelper13 = _this.analyticsHelper) === null || _this$analyticsHelper13 === void 0 || _this$analyticsHelper13.sendErrorEvent(restoreError, 'Error while reinitialising document');
270
- _this.onErrorHandled({
271
- message: 'Caught error while trying to recover the document',
272
- data: {
273
- status: 500,
274
- // Meaningless, remove when we review error structure
275
- code: INTERNAL_ERROR_CODE.DOCUMENT_RESTORE_ERROR
269
+ // If there are unconfirmed steps, attempt to reconcile our current state with with recovered document
270
+ if (!(unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length && _this.reconcileOnRecovery && currentState)) {
271
+ _context3.next = 14;
272
+ break;
273
+ }
274
+ _context3.next = 12;
275
+ return _this.fetchReconcile(JSON.stringify(currentState.content));
276
+ case 12:
277
+ _context3.next = 15;
278
+ break;
279
+ case 14:
280
+ if (unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length) {
281
+ _this.applyLocalSteps(unconfirmedSteps);
282
+ }
283
+ case 15:
284
+ (_this$analyticsHelper11 = _this.analyticsHelper) === null || _this$analyticsHelper11 === void 0 || _this$analyticsHelper11.sendActionEvent(EVENT_ACTION.REINITIALISE_DOCUMENT, EVENT_STATUS.SUCCESS, {
285
+ numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length,
286
+ hasTitle: !!(metadata !== null && metadata !== void 0 && metadata.title)
287
+ });
288
+ _context3.next = 23;
289
+ break;
290
+ case 18:
291
+ _context3.prev = 18;
292
+ _context3.t0 = _context3["catch"](6);
293
+ (_this$analyticsHelper12 = _this.analyticsHelper) === null || _this$analyticsHelper12 === void 0 || _this$analyticsHelper12.sendActionEvent(EVENT_ACTION.REINITIALISE_DOCUMENT, EVENT_STATUS.FAILURE, {
294
+ numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length
295
+ });
296
+ (_this$analyticsHelper13 = _this.analyticsHelper) === null || _this$analyticsHelper13 === void 0 || _this$analyticsHelper13.sendErrorEvent(_context3.t0, 'Error while reinitialising document');
297
+ _this.onErrorHandled({
298
+ message: 'Caught error while trying to recover the document',
299
+ data: {
300
+ status: 500,
301
+ // Meaningless, remove when we review error structure
302
+ code: INTERNAL_ERROR_CODE.DOCUMENT_RESTORE_ERROR
303
+ }
304
+ });
305
+ case 23:
306
+ case "end":
307
+ return _context3.stop();
276
308
  }
277
- });
278
- }
279
- });
280
- _defineProperty(this, "getFinalAcknowledgedState", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
309
+ }, _callee3, null, [[6, 18]]);
310
+ }));
311
+ return function (_x) {
312
+ return _ref5.apply(this, arguments);
313
+ };
314
+ }());
315
+ _defineProperty(this, "getFinalAcknowledgedState", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
281
316
  var _this$analyticsHelper14, finalAcknowledgedState, currentState, reconcileResponse, measure, _this$analyticsHelper15, _this$analyticsHelper16, _measure2;
282
- return _regeneratorRuntime.wrap(function _callee3$(_context3) {
283
- while (1) switch (_context3.prev = _context3.next) {
317
+ return _regeneratorRuntime.wrap(function _callee4$(_context4) {
318
+ while (1) switch (_context4.prev = _context4.next) {
284
319
  case 0:
285
320
  _this.aggressiveCatchup = true;
286
- _context3.prev = 1;
321
+ _context4.prev = 1;
287
322
  startMeasure(MEASURE_NAME.PUBLISH_PAGE, _this.analyticsHelper);
288
- _context3.prev = 3;
289
- _context3.next = 6;
323
+ _context4.prev = 3;
324
+ _context4.next = 6;
290
325
  return _this.commitUnconfirmedSteps();
291
326
  case 6:
292
- _context3.next = 8;
327
+ _context4.next = 8;
293
328
  return _this.getCurrentState();
294
329
  case 8:
295
- finalAcknowledgedState = _context3.sent;
296
- _context3.next = 20;
330
+ finalAcknowledgedState = _context4.sent;
331
+ _context4.next = 20;
297
332
  break;
298
333
  case 11:
299
- _context3.prev = 11;
300
- _context3.t0 = _context3["catch"](3);
301
- _context3.next = 15;
334
+ _context4.prev = 11;
335
+ _context4.t0 = _context4["catch"](3);
336
+ _context4.next = 15;
302
337
  return _this.getCurrentState();
303
338
  case 15:
304
- currentState = _context3.sent;
305
- _context3.next = 18;
339
+ currentState = _context4.sent;
340
+ _context4.next = 18;
306
341
  return _this.fetchReconcile(JSON.stringify(currentState.content));
307
342
  case 18:
308
- reconcileResponse = _context3.sent;
343
+ reconcileResponse = _context4.sent;
309
344
  finalAcknowledgedState = {
310
345
  content: JSON.parse(reconcileResponse.document),
311
346
  title: currentState.title,
@@ -317,28 +352,28 @@ export var DocumentService = /*#__PURE__*/function () {
317
352
  latency: measure === null || measure === void 0 ? void 0 : measure.duration
318
353
  });
319
354
  _this.aggressiveCatchup = false;
320
- return _context3.abrupt("return", finalAcknowledgedState);
355
+ return _context4.abrupt("return", finalAcknowledgedState);
321
356
  case 26:
322
- _context3.prev = 26;
323
- _context3.t1 = _context3["catch"](1);
357
+ _context4.prev = 26;
358
+ _context4.t1 = _context4["catch"](1);
324
359
  _this.aggressiveCatchup = false;
325
360
  _measure2 = stopMeasure(MEASURE_NAME.PUBLISH_PAGE, _this.analyticsHelper);
326
361
  (_this$analyticsHelper15 = _this.analyticsHelper) === null || _this$analyticsHelper15 === void 0 || _this$analyticsHelper15.sendActionEvent(EVENT_ACTION.PUBLISH_PAGE, EVENT_STATUS.FAILURE, {
327
362
  latency: _measure2 === null || _measure2 === void 0 ? void 0 : _measure2.duration
328
363
  });
329
- (_this$analyticsHelper16 = _this.analyticsHelper) === null || _this$analyticsHelper16 === void 0 || _this$analyticsHelper16.sendErrorEvent(_context3.t1, 'Error while returning ADF version of the final draft document');
330
- throw _context3.t1;
364
+ (_this$analyticsHelper16 = _this.analyticsHelper) === null || _this$analyticsHelper16 === void 0 || _this$analyticsHelper16.sendErrorEvent(_context4.t1, 'Error while returning ADF version of the final draft document');
365
+ throw _context4.t1;
331
366
  case 33:
332
367
  case "end":
333
- return _context3.stop();
368
+ return _context4.stop();
334
369
  }
335
- }, _callee3, null, [[1, 26], [3, 11]]);
370
+ }, _callee4, null, [[1, 26], [3, 11]]);
336
371
  })));
337
- _defineProperty(this, "updateDocument", function (_ref6) {
338
- var doc = _ref6.doc,
339
- version = _ref6.version,
340
- metadata = _ref6.metadata,
341
- reserveCursor = _ref6.reserveCursor;
372
+ _defineProperty(this, "updateDocument", function (_ref7) {
373
+ var doc = _ref7.doc,
374
+ version = _ref7.version,
375
+ metadata = _ref7.metadata,
376
+ reserveCursor = _ref7.reserveCursor;
342
377
  _this.providerEmitCallback('init', _objectSpread({
343
378
  doc: doc,
344
379
  version: version,
@@ -414,15 +449,15 @@ export var DocumentService = /*#__PURE__*/function () {
414
449
  * Commit the unconfirmed local steps to the back-end service
415
450
  * @throws {Error} Couldn't sync the steps after retrying 30 times
416
451
  */
417
- _defineProperty(this, "commitUnconfirmedSteps", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
452
+ _defineProperty(this, "commitUnconfirmedSteps", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
418
453
  var unconfirmedSteps, _this$getState6, _this$analyticsHelper21, count, unconfirmedTrs, lastTr, isLastTrConfirmed, _this$analyticsHelper20, nextUnconfirmedSteps, nextUnconfirmedTrs, _this$getUnconfirmedS, state, unconfirmedStepsInfoUGCRemoved, _error2, measure, _this$analyticsHelper22, _this$analyticsHelper23, _measure3;
419
- return _regeneratorRuntime.wrap(function _callee4$(_context4) {
420
- while (1) switch (_context4.prev = _context4.next) {
454
+ return _regeneratorRuntime.wrap(function _callee5$(_context5) {
455
+ while (1) switch (_context5.prev = _context5.next) {
421
456
  case 0:
422
457
  unconfirmedSteps = _this.getUnconfirmedSteps();
423
- _context4.prev = 1;
458
+ _context5.prev = 1;
424
459
  if (!(unconfirmedSteps !== null && unconfirmedSteps !== void 0 && unconfirmedSteps.length)) {
425
- _context4.next = 24;
460
+ _context5.next = 24;
426
461
  break;
427
462
  }
428
463
  startMeasure(MEASURE_NAME.COMMIT_UNCONFIRMED_STEPS, _this.analyticsHelper);
@@ -438,11 +473,11 @@ export var DocumentService = /*#__PURE__*/function () {
438
473
  }
439
474
  case 9:
440
475
  if (isLastTrConfirmed) {
441
- _context4.next = 22;
476
+ _context5.next = 22;
442
477
  break;
443
478
  }
444
479
  _this.sendStepsFromCurrentState();
445
- _context4.next = 13;
480
+ _context5.next = 13;
446
481
  return sleep(500);
447
482
  case 13:
448
483
  nextUnconfirmedSteps = _this.getUnconfirmedSteps();
@@ -455,7 +490,7 @@ export var DocumentService = /*#__PURE__*/function () {
455
490
  isLastTrConfirmed = true;
456
491
  }
457
492
  if (!(!isLastTrConfirmed && count++ >= ACK_MAX_TRY)) {
458
- _context4.next = 20;
493
+ _context5.next = 20;
459
494
  break;
460
495
  }
461
496
  if (_this.onSyncUpError) {
@@ -476,7 +511,7 @@ export var DocumentService = /*#__PURE__*/function () {
476
511
  });
477
512
  throw _error2;
478
513
  case 20:
479
- _context4.next = 9;
514
+ _context5.next = 9;
480
515
  break;
481
516
  case 22:
482
517
  measure = stopMeasure(MEASURE_NAME.COMMIT_UNCONFIRMED_STEPS, _this.analyticsHelper);
@@ -486,23 +521,23 @@ export var DocumentService = /*#__PURE__*/function () {
486
521
  numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length
487
522
  });
488
523
  case 24:
489
- _context4.next = 32;
524
+ _context5.next = 32;
490
525
  break;
491
526
  case 26:
492
- _context4.prev = 26;
493
- _context4.t0 = _context4["catch"](1);
527
+ _context5.prev = 26;
528
+ _context5.t0 = _context5["catch"](1);
494
529
  _measure3 = stopMeasure(MEASURE_NAME.COMMIT_UNCONFIRMED_STEPS, _this.analyticsHelper);
495
530
  (_this$analyticsHelper22 = _this.analyticsHelper) === null || _this$analyticsHelper22 === void 0 || _this$analyticsHelper22.sendActionEvent(EVENT_ACTION.COMMIT_UNCONFIRMED_STEPS, EVENT_STATUS.FAILURE, {
496
531
  latency: _measure3 === null || _measure3 === void 0 ? void 0 : _measure3.duration,
497
532
  numUnconfirmedSteps: unconfirmedSteps === null || unconfirmedSteps === void 0 ? void 0 : unconfirmedSteps.length
498
533
  });
499
- (_this$analyticsHelper23 = _this.analyticsHelper) === null || _this$analyticsHelper23 === void 0 || _this$analyticsHelper23.sendErrorEvent(_context4.t0, 'Error while committing unconfirmed steps');
500
- throw _context4.t0;
534
+ (_this$analyticsHelper23 = _this.analyticsHelper) === null || _this$analyticsHelper23 === void 0 || _this$analyticsHelper23.sendErrorEvent(_context5.t0, 'Error while committing unconfirmed steps');
535
+ throw _context5.t0;
501
536
  case 32:
502
537
  case "end":
503
- return _context4.stop();
538
+ return _context5.stop();
504
539
  }
505
- }, _callee4, null, [[1, 26]]);
540
+ }, _callee5, null, [[1, 26]]);
506
541
  })));
507
542
  _defineProperty(this, "onStepRejectedError", function () {
508
543
  var _this$analyticsHelper24;
@@ -537,6 +572,7 @@ export var DocumentService = /*#__PURE__*/function () {
537
572
  this.onErrorHandled = onErrorHandled;
538
573
  this.metadataService = metadataService;
539
574
  this.enableErrorOnFailedDocumentApply = enableErrorOnFailedDocumentApply;
575
+ this.reconcileOnRecovery = reconcileOnRecovery;
540
576
  this.stepQueue = new StepQueueState();
541
577
  }
542
578
  _createClass(DocumentService, [{
@@ -568,8 +604,8 @@ export var DocumentService = /*#__PURE__*/function () {
568
604
  logger("Processing data. Version \"".concat(version, "\"."));
569
605
  if (steps !== null && steps !== void 0 && steps.length) {
570
606
  try {
571
- var clientIds = steps.map(function (_ref8) {
572
- var clientId = _ref8.clientId;
607
+ var clientIds = steps.map(function (_ref9) {
608
+ var clientId = _ref9.clientId;
573
609
  return clientId;
574
610
  });
575
611
  this.providerEmitCallback('data', {
@@ -597,10 +633,10 @@ export var DocumentService = /*#__PURE__*/function () {
597
633
  }
598
634
  }, {
599
635
  key: "setup",
600
- value: function setup(_ref9) {
601
- var getState = _ref9.getState,
602
- onSyncUpError = _ref9.onSyncUpError,
603
- clientId = _ref9.clientId;
636
+ value: function setup(_ref10) {
637
+ var getState = _ref10.getState,
638
+ onSyncUpError = _ref10.onSyncUpError,
639
+ clientId = _ref10.clientId;
604
640
  this.getState = getState;
605
641
  this.onSyncUpError = onSyncUpError || noop;
606
642
  this.clientId = clientId;
@@ -1,7 +1,8 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
2
  var defaultNCSFeatureFlags = {
3
3
  testFF: false,
4
- blockViewOnly: false
4
+ blockViewOnly: false,
5
+ reconcileOnRecovery: false
5
6
  };
6
7
 
7
8
  /**
@@ -10,7 +11,8 @@ var defaultNCSFeatureFlags = {
10
11
  var productKeys = {
11
12
  confluence: {
12
13
  testFF: 'confluence.frontend.collab.provider.testFF',
13
- blockViewOnly: 'confluence.frontend.ncs.block-view-only'
14
+ blockViewOnly: 'confluence.frontend.ncs.block-view-only',
15
+ reconcileOnRecovery: 'confluence.frontend.ncs.reconcile-on-recovery'
14
16
  }
15
17
  };
16
18
  var filterFeatureFlagNames = function filterFeatureFlagNames(flags) {
@@ -258,9 +258,10 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
258
258
  _this.isProviderInitialized = false;
259
259
  _this.participantsService = new ParticipantsService(_this.analyticsHelper, undefined, _this.emitCallback, _this.config.getUser, _this.channel.broadcast, _this.channel.sendPresenceJoined, _this.getPresenceData, _this.setUserId);
260
260
  _this.metadataService = new MetadataService(_this.emitCallback, _this.channel.sendMetadata);
261
+ var reconcileOnRecovery = getCollabProviderFeatureFlag('reconcileOnRecovery', _this.config.featureFlags);
261
262
  _this.documentService = new DocumentService(_this.participantsService, _this.analyticsHelper, _this.channel.fetchCatchup, _this.channel.fetchReconcile, _this.emitCallback, _this.channel.broadcast, function () {
262
263
  return _this.userId;
263
- }, _this.onErrorHandled, _this.metadataService, _this.config.enableErrorOnFailedDocumentApply);
264
+ }, _this.onErrorHandled, _this.metadataService, _this.config.enableErrorOnFailedDocumentApply, reconcileOnRecovery);
264
265
  _this.namespaceService = new NamespaceService();
265
266
  _this.api = new Api(config, _this.documentService, _this.channel);
266
267
  _this.sendStepsTimer = setInterval(function () {
@@ -1,5 +1,5 @@
1
1
  export var name = "@atlaskit/collab-provider";
2
- export var version = "9.22.7";
2
+ export var version = "9.22.8";
3
3
  export var nextMajorVersion = function nextMajorVersion() {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -19,6 +19,7 @@ export declare class DocumentService {
19
19
  private onErrorHandled;
20
20
  private metadataService;
21
21
  private enableErrorOnFailedDocumentApply;
22
+ private reconcileOnRecovery;
22
23
  private getState;
23
24
  private onSyncUpError?;
24
25
  private stepQueue;
@@ -39,7 +40,7 @@ export declare class DocumentService {
39
40
  * @param metadataService
40
41
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
41
42
  */
42
- constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchReconcile: (currentStateDoc: string) => Promise<ReconcileResponse>, providerEmitCallback: (evt: keyof CollabEvents, data: any) => void, broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, getUserId: () => string | undefined, onErrorHandled: (error: InternalError) => void, metadataService: MetadataService, enableErrorOnFailedDocumentApply?: boolean);
43
+ constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchReconcile: (currentStateDoc: string) => Promise<ReconcileResponse>, providerEmitCallback: (evt: keyof CollabEvents, data: any) => void, broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, getUserId: () => string | undefined, onErrorHandled: (error: InternalError) => void, metadataService: MetadataService, enableErrorOnFailedDocumentApply?: boolean, reconcileOnRecovery?: boolean);
43
44
  /**
44
45
  * To prevent calling catchup to often, use lodash throttle to reduce the frequency
45
46
  */
@@ -61,7 +62,7 @@ export declare class DocumentService {
61
62
  * Called when we receive steps from the service
62
63
  */
63
64
  onStepsAdded: (data: StepsPayload) => void;
64
- onRestore: ({ doc, version, metadata }: CollabInitPayload) => void;
65
+ onRestore: ({ doc, version, metadata }: CollabInitPayload) => Promise<void>;
65
66
  getFinalAcknowledgedState: () => Promise<ResolvedEditorState>;
66
67
  updateDocument: ({ doc, version, metadata, reserveCursor, }: CollabInitPayload) => void;
67
68
  private updateDocumentAnalytics;
@@ -1,6 +1,7 @@
1
1
  export interface NCSFeatureFlags {
2
2
  testFF?: boolean;
3
3
  blockViewOnly?: boolean;
4
+ reconcileOnRecovery?: boolean;
4
5
  }
5
6
  export interface WithNCSFeatureFlags {
6
7
  featureFlags?: NCSFeatureFlags;
@@ -19,6 +19,7 @@ export declare class DocumentService {
19
19
  private onErrorHandled;
20
20
  private metadataService;
21
21
  private enableErrorOnFailedDocumentApply;
22
+ private reconcileOnRecovery;
22
23
  private getState;
23
24
  private onSyncUpError?;
24
25
  private stepQueue;
@@ -39,7 +40,7 @@ export declare class DocumentService {
39
40
  * @param metadataService
40
41
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
41
42
  */
42
- constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchReconcile: (currentStateDoc: string) => Promise<ReconcileResponse>, providerEmitCallback: (evt: keyof CollabEvents, data: any) => void, broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, getUserId: () => string | undefined, onErrorHandled: (error: InternalError) => void, metadataService: MetadataService, enableErrorOnFailedDocumentApply?: boolean);
43
+ constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchReconcile: (currentStateDoc: string) => Promise<ReconcileResponse>, providerEmitCallback: (evt: keyof CollabEvents, data: any) => void, broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, getUserId: () => string | undefined, onErrorHandled: (error: InternalError) => void, metadataService: MetadataService, enableErrorOnFailedDocumentApply?: boolean, reconcileOnRecovery?: boolean);
43
44
  /**
44
45
  * To prevent calling catchup to often, use lodash throttle to reduce the frequency
45
46
  */
@@ -61,7 +62,7 @@ export declare class DocumentService {
61
62
  * Called when we receive steps from the service
62
63
  */
63
64
  onStepsAdded: (data: StepsPayload) => void;
64
- onRestore: ({ doc, version, metadata }: CollabInitPayload) => void;
65
+ onRestore: ({ doc, version, metadata }: CollabInitPayload) => Promise<void>;
65
66
  getFinalAcknowledgedState: () => Promise<ResolvedEditorState>;
66
67
  updateDocument: ({ doc, version, metadata, reserveCursor, }: CollabInitPayload) => void;
67
68
  private updateDocumentAnalytics;
@@ -1,6 +1,7 @@
1
1
  export interface NCSFeatureFlags {
2
2
  testFF?: boolean;
3
3
  blockViewOnly?: boolean;
4
+ reconcileOnRecovery?: boolean;
4
5
  }
5
6
  export interface WithNCSFeatureFlags {
6
7
  featureFlags?: NCSFeatureFlags;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/collab-provider",
3
- "version": "9.22.7",
3
+ "version": "9.22.8",
4
4
  "description": "A provider for collaborative editing.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -36,7 +36,7 @@
36
36
  "dependencies": {
37
37
  "@atlaskit/analytics-gas-types": "^5.1.0",
38
38
  "@atlaskit/analytics-listeners": "^8.9.0",
39
- "@atlaskit/editor-common": "^77.3.0",
39
+ "@atlaskit/editor-common": "^77.5.0",
40
40
  "@atlaskit/editor-json-transformer": "^8.10.0",
41
41
  "@atlaskit/editor-prosemirror": "3.0.0",
42
42
  "@atlaskit/prosemirror-collab": "^0.2.0",