@atlaskit/collab-provider 9.26.1 → 9.26.3

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,17 @@
1
1
  # @atlaskit/collab-provider
2
2
 
3
+ ## 9.26.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#91887](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/91887) [`232026623493`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/232026623493) - Add out of sync detection and correction for catchup
8
+
9
+ ## 9.26.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [#90942](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/90942) [`30e989b2e4bb`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/30e989b2e4bb) - catchupV2 is a noop when document is locked
14
+
3
15
  ## 9.26.1
4
16
 
5
17
  ### Patch Changes
@@ -328,7 +328,7 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
328
328
  };
329
329
  }());
330
330
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "fetchCatchupv2", /*#__PURE__*/function () {
331
- var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(fromVersion, clientId) {
331
+ var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(fromVersion, clientId, catchUpOutofSync) {
332
332
  var _yield$utils$requestS2, steps, metadata, errorNotFound, errorCatchupv2;
333
333
  return _regenerator.default.wrap(function _callee3$(_context3) {
334
334
  while (1) switch (_context3.prev = _context3.next) {
@@ -339,7 +339,8 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
339
339
  _context3.t2 = "document/".concat(encodeURIComponent(_this.config.documentAri), "/catchupv2");
340
340
  _context3.t3 = {
341
341
  version: fromVersion,
342
- clientId: clientId
342
+ clientId: clientId,
343
+ catchUpOutofSync: catchUpOutofSync
343
344
  };
344
345
  _context3.t4 = _objectSpread;
345
346
  _context3.t5 = _objectSpread;
@@ -419,7 +420,7 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
419
420
  }
420
421
  }, _callee3, null, [[0, 31]]);
421
422
  }));
422
- return function (_x3, _x4) {
423
+ return function (_x3, _x4, _x5) {
423
424
  return _ref3.apply(this, arguments);
424
425
  };
425
426
  }());
@@ -492,7 +493,7 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
492
493
  }
493
494
  }, _callee4, null, [[0, 30]]);
494
495
  }));
495
- return function (_x5, _x6) {
496
+ return function (_x6, _x7) {
496
497
  return _ref4.apply(this, arguments);
497
498
  };
498
499
  }());
@@ -627,7 +628,7 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
627
628
  }
628
629
  }, _callee5, null, [[1, 9]]);
629
630
  }));
630
- return function auth(_x7) {
631
+ return function auth(_x8) {
631
632
  return _ref5.apply(this, arguments);
632
633
  };
633
634
  }();
@@ -652,7 +653,7 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
652
653
  }
653
654
  }, _callee6);
654
655
  }));
655
- return function auth(_x8) {
656
+ return function auth(_x9) {
656
657
  return _ref6.apply(this, arguments);
657
658
  };
658
659
  }();
@@ -739,7 +740,7 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
739
740
  }
740
741
  }, _callee7);
741
742
  }));
742
- return function (_x9) {
743
+ return function (_x10) {
743
744
  return _ref9.apply(this, arguments);
744
745
  };
745
746
  }());
@@ -8,6 +8,9 @@ exports.catchupv2 = void 0;
8
8
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
9
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
10
10
  var _utils = require("../helpers/utils");
11
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
12
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
13
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
11
14
  var logger = (0, _utils.createLogger)('Catchupv2', 'red');
12
15
  var catchupv2 = exports.catchupv2 = /*#__PURE__*/function () {
13
16
  var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(opt) {
@@ -18,7 +21,7 @@ var catchupv2 = exports.catchupv2 = /*#__PURE__*/function () {
18
21
  fromVersion = opt.getCurrentPmVersion();
19
22
  _context.prev = 1;
20
23
  _context.next = 4;
21
- return opt.fetchCatchupv2(fromVersion, opt.clientId);
24
+ return opt.fetchCatchupv2(fromVersion, opt.clientId, opt.catchUpOutofSync);
22
25
  case 4:
23
26
  _yield$opt$fetchCatch = _context.sent;
24
27
  steps = _yield$opt$fetchCatch.steps;
@@ -40,21 +43,43 @@ var catchupv2 = exports.catchupv2 = /*#__PURE__*/function () {
40
43
  };
41
44
  opt.onStepsAdded(stepsPayload);
42
45
  opt.updateMetadata(metadata);
43
- _context.next = 26;
44
- break;
45
- case 21:
46
- _context.prev = 21;
46
+ return _context.abrupt("return", Boolean(opt.clientId && isOutOfSync(fromVersion, opt.getCurrentPmVersion(), steps, opt.clientId)));
47
+ case 22:
48
+ _context.prev = 22;
47
49
  _context.t1 = _context["catch"](14);
48
50
  (_opt$analyticsHelper2 = opt.analyticsHelper) === null || _opt$analyticsHelper2 === void 0 || _opt$analyticsHelper2.sendErrorEvent(_context.t1, 'Failed to apply catchupv2 result in the editor');
49
51
  logger("Apply catchupv2 steps failed:", _context.t1.message);
50
52
  throw _context.t1;
51
- case 26:
53
+ case 27:
52
54
  case "end":
53
55
  return _context.stop();
54
56
  }
55
- }, _callee, null, [[1, 9], [14, 21]]);
57
+ }, _callee, null, [[1, 9], [14, 22]]);
56
58
  }));
57
59
  return function catchupv2(_x) {
58
60
  return _ref.apply(this, arguments);
59
61
  };
60
- }();
62
+ }();
63
+ var isOutOfSync = function isOutOfSync(fromVersion, currentVersion, steps, clientId) {
64
+ return (
65
+ // If version number hasn't increased, and steps are not from our client, we're out of sync
66
+ Boolean(fromVersion >= currentVersion && checkForeignSteps(steps, clientId))
67
+ );
68
+ };
69
+ var checkForeignSteps = function checkForeignSteps(steps, clientId) {
70
+ var _iterator = _createForOfIteratorHelper(steps),
71
+ _step;
72
+ try {
73
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
74
+ var step = _step.value;
75
+ if (step.clientId !== clientId) {
76
+ return true;
77
+ }
78
+ }
79
+ } catch (err) {
80
+ _iterator.e(err);
81
+ } finally {
82
+ _iterator.f();
83
+ }
84
+ return false;
85
+ };
@@ -47,17 +47,18 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
47
47
  * @param metadataService
48
48
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
49
49
  */
50
- function DocumentService(participantsService, analyticsHelper, fetchCatchup, fetchCatchupv2, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService) {
50
+ function DocumentService(participantsService, analyticsHelper, fetchCatchup, fetchCatchupv2, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService, isNameSpaceLocked) {
51
51
  var _this = this;
52
- var enableErrorOnFailedDocumentApply = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;
53
- var reconcileOnRecovery = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : false;
54
- var options = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : {
52
+ var enableErrorOnFailedDocumentApply = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : false;
53
+ var reconcileOnRecovery = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : false;
54
+ var options = arguments.length > 13 && arguments[13] !== undefined ? arguments[13] : {
55
55
  __livePage: false
56
56
  };
57
57
  (0, _classCallCheck2.default)(this, DocumentService);
58
58
  // Fires analytics to editor when collab editor cannot sync up
59
59
  (0, _defineProperty2.default)(this, "stepRejectCounter", 0);
60
60
  (0, _defineProperty2.default)(this, "aggressiveCatchup", false);
61
+ (0, _defineProperty2.default)(this, "catchUpOutofSync", false);
61
62
  /**
62
63
  * To prevent calling catchup to often, use lodash throttle to reduce the frequency
63
64
  */
@@ -155,43 +156,52 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
155
156
  logger("Queue is paused. Aborting.");
156
157
  return _context2.abrupt("return");
157
158
  case 4:
159
+ if (!_this.isNameSpaceLocked()) {
160
+ _context2.next = 7;
161
+ break;
162
+ }
163
+ logger("catchupv2: Document is locked. Aborting.");
164
+ return _context2.abrupt("return");
165
+ case 7:
158
166
  _this.stepQueue.pauseQueue();
159
- _context2.prev = 5;
160
- _context2.next = 8;
167
+ _context2.prev = 8;
168
+ _context2.next = 11;
161
169
  return (0, _catchupv.catchupv2)({
162
170
  getCurrentPmVersion: _this.getCurrentPmVersion,
163
171
  fetchCatchupv2: _this.fetchCatchupv2,
164
172
  updateMetadata: _this.metadataService.updateMetadata,
165
173
  analyticsHelper: _this.analyticsHelper,
166
174
  clientId: _this.clientId,
167
- onStepsAdded: _this.onStepsAdded
175
+ onStepsAdded: _this.onStepsAdded,
176
+ catchUpOutofSync: _this.catchUpOutofSync
168
177
  });
169
- case 8:
178
+ case 11:
179
+ _this.catchUpOutofSync = _context2.sent;
170
180
  latency = new Date().getTime() - start;
171
181
  (_this$analyticsHelper3 = _this.analyticsHelper) === null || _this$analyticsHelper3 === void 0 || _this$analyticsHelper3.sendActionEvent(_const.EVENT_ACTION.CATCHUP, _const.EVENT_STATUS.SUCCESS, {
172
182
  latency: latency
173
183
  });
174
- _context2.next = 16;
184
+ _context2.next = 20;
175
185
  break;
176
- case 12:
177
- _context2.prev = 12;
178
- _context2.t0 = _context2["catch"](5);
186
+ case 16:
187
+ _context2.prev = 16;
188
+ _context2.t0 = _context2["catch"](8);
179
189
  _latency2 = new Date().getTime() - start;
180
190
  (_this$analyticsHelper4 = _this.analyticsHelper) === null || _this$analyticsHelper4 === void 0 || _this$analyticsHelper4.sendActionEvent(_const.EVENT_ACTION.CATCHUP, _const.EVENT_STATUS.FAILURE, {
181
191
  latency: _latency2
182
192
  });
183
- case 16:
184
- _context2.prev = 16;
193
+ case 20:
194
+ _context2.prev = 20;
185
195
  _this.stepQueue.resumeQueue();
186
196
  _this.processQueue();
187
197
  _this.sendStepsFromCurrentState(); // this will eventually retry catchup as it calls throttledCommitStep which will either catchup on onStepsAdded or onErrorHandled
188
198
  _this.stepRejectCounter = 0;
189
- return _context2.finish(16);
190
- case 22:
199
+ return _context2.finish(20);
200
+ case 26:
191
201
  case "end":
192
202
  return _context2.stop();
193
203
  }
194
- }, _callee2, null, [[5, 12, 16, 22]]);
204
+ }, _callee2, null, [[8, 16, 20, 26]]);
195
205
  })));
196
206
  (0, _defineProperty2.default)(this, "getCurrentPmVersion", function () {
197
207
  var _this$getState;
@@ -653,6 +663,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
653
663
  this.getUserId = getUserId;
654
664
  this.onErrorHandled = onErrorHandled;
655
665
  this.metadataService = metadataService;
666
+ this.isNameSpaceLocked = isNameSpaceLocked;
656
667
  this.enableErrorOnFailedDocumentApply = enableErrorOnFailedDocumentApply;
657
668
  this.reconcileOnRecovery = reconcileOnRecovery;
658
669
  this.options = options;
@@ -274,12 +274,12 @@ var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
274
274
  _this.participantsService = new _participantsService.ParticipantsService(_this.analyticsHelper, undefined, _this.emitCallback, _this.config.getUser, _this.channel.broadcast, _this.channel.sendPresenceJoined, _this.getPresenceData, _this.setUserId);
275
275
  _this.metadataService = new _metadataService.MetadataService(_this.emitCallback, _this.channel.sendMetadata);
276
276
  var reconcileOnRecovery = (0, _featureFlags.getCollabProviderFeatureFlag)('reconcileOnRecovery', _this.config.featureFlags);
277
+ _this.namespaceService = new _namespaceService.NamespaceService();
277
278
  _this.documentService = new _documentService.DocumentService(_this.participantsService, _this.analyticsHelper, _this.channel.fetchCatchup, _this.channel.fetchCatchupv2, _this.channel.fetchReconcile, _this.emitCallback, _this.channel.broadcast, function () {
278
279
  return _this.userId;
279
- }, _this.onErrorHandled, _this.metadataService, _this.config.enableErrorOnFailedDocumentApply, reconcileOnRecovery, {
280
+ }, _this.onErrorHandled, _this.metadataService, _this.namespaceService.getIsNamespaceLocked.bind(_this.namespaceService), _this.config.enableErrorOnFailedDocumentApply, reconcileOnRecovery, {
280
281
  __livePage: _this.config.__livePage || false
281
282
  });
282
- _this.namespaceService = new _namespaceService.NamespaceService();
283
283
  _this.api = new _api.Api(config, _this.documentService, _this.channel);
284
284
  _this.sendStepsTimer = setInterval(function () {
285
285
  logger('Intervally sendStepsFromCurrentState');
@@ -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.26.1";
8
+ var version = exports.version = "9.26.3";
9
9
  var nextMajorVersion = exports.nextMajorVersion = function nextMajorVersion() {
10
10
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
11
11
  };
@@ -215,7 +215,7 @@ export class Channel extends Emitter {
215
215
  throw error;
216
216
  }
217
217
  });
218
- _defineProperty(this, "fetchCatchupv2", async (fromVersion, clientId) => {
218
+ _defineProperty(this, "fetchCatchupv2", async (fromVersion, clientId, catchUpOutofSync) => {
219
219
  try {
220
220
  const {
221
221
  steps,
@@ -224,7 +224,8 @@ export class Channel extends Emitter {
224
224
  path: `document/${encodeURIComponent(this.config.documentAri)}/catchupv2`,
225
225
  queryParams: {
226
226
  version: fromVersion,
227
- clientId: clientId
227
+ clientId: clientId,
228
+ catchUpOutofSync
228
229
  },
229
230
  requestInit: {
230
231
  headers: {
@@ -8,7 +8,7 @@ export const catchupv2 = async opt => {
8
8
  ({
9
9
  steps,
10
10
  metadata
11
- } = await opt.fetchCatchupv2(fromVersion, opt.clientId));
11
+ } = await opt.fetchCatchupv2(fromVersion, opt.clientId, opt.catchUpOutofSync));
12
12
  } catch (error) {
13
13
  var _opt$analyticsHelper;
14
14
  (_opt$analyticsHelper = opt.analyticsHelper) === null || _opt$analyticsHelper === void 0 ? void 0 : _opt$analyticsHelper.sendErrorEvent(error, 'Error while fetching catchupv2 from server');
@@ -23,10 +23,22 @@ export const catchupv2 = async opt => {
23
23
  };
24
24
  opt.onStepsAdded(stepsPayload);
25
25
  opt.updateMetadata(metadata);
26
+ return Boolean(opt.clientId && isOutOfSync(fromVersion, opt.getCurrentPmVersion(), steps, opt.clientId));
26
27
  } catch (error) {
27
28
  var _opt$analyticsHelper2;
28
29
  (_opt$analyticsHelper2 = opt.analyticsHelper) === null || _opt$analyticsHelper2 === void 0 ? void 0 : _opt$analyticsHelper2.sendErrorEvent(error, 'Failed to apply catchupv2 result in the editor');
29
30
  logger(`Apply catchupv2 steps failed:`, error.message);
30
31
  throw error;
31
32
  }
33
+ };
34
+ const isOutOfSync = (fromVersion, currentVersion, steps, clientId) =>
35
+ // If version number hasn't increased, and steps are not from our client, we're out of sync
36
+ Boolean(fromVersion >= currentVersion && checkForeignSteps(steps, clientId));
37
+ const checkForeignSteps = (steps, clientId) => {
38
+ for (const step of steps) {
39
+ if (step.clientId !== clientId) {
40
+ return true;
41
+ }
42
+ }
43
+ return false;
32
44
  };
@@ -34,12 +34,13 @@ export class DocumentService {
34
34
  * @param metadataService
35
35
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
36
36
  */
37
- constructor(participantsService, analyticsHelper, fetchCatchup, fetchCatchupv2, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService, enableErrorOnFailedDocumentApply = false, reconcileOnRecovery = false, options = {
37
+ constructor(participantsService, analyticsHelper, fetchCatchup, fetchCatchupv2, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService, isNameSpaceLocked, enableErrorOnFailedDocumentApply = false, reconcileOnRecovery = false, options = {
38
38
  __livePage: false
39
39
  }) {
40
40
  // Fires analytics to editor when collab editor cannot sync up
41
41
  _defineProperty(this, "stepRejectCounter", 0);
42
42
  _defineProperty(this, "aggressiveCatchup", false);
43
+ _defineProperty(this, "catchUpOutofSync", false);
43
44
  /**
44
45
  * To prevent calling catchup to often, use lodash throttle to reduce the frequency
45
46
  */
@@ -111,16 +112,32 @@ export class DocumentService {
111
112
  logger(`Queue is paused. Aborting.`);
112
113
  return;
113
114
  }
115
+
116
+ /**
117
+ * If the database is in a transitionary state (i.e locked),
118
+ * it likely that another user may already be in the process of catching up.
119
+ *
120
+ * If multiple users are trying to catch up at the same time, it can lead to
121
+ * the database being stuck in a transitionary state due to duplicated page recovery requests.
122
+ * We don't wanna be stuck in a transitionary state as that will cause issues with
123
+ * content reconciliation and other operations.
124
+ */
125
+ // check if the document is locked -> noop
126
+ if (this.isNameSpaceLocked()) {
127
+ logger(`catchupv2: Document is locked. Aborting.`);
128
+ return;
129
+ }
114
130
  this.stepQueue.pauseQueue();
115
131
  try {
116
132
  var _this$analyticsHelper3;
117
- await catchupv2({
133
+ this.catchUpOutofSync = await catchupv2({
118
134
  getCurrentPmVersion: this.getCurrentPmVersion,
119
135
  fetchCatchupv2: this.fetchCatchupv2,
120
136
  updateMetadata: this.metadataService.updateMetadata,
121
137
  analyticsHelper: this.analyticsHelper,
122
138
  clientId: this.clientId,
123
- onStepsAdded: this.onStepsAdded
139
+ onStepsAdded: this.onStepsAdded,
140
+ catchUpOutofSync: this.catchUpOutofSync
124
141
  });
125
142
  const latency = new Date().getTime() - start;
126
143
  (_this$analyticsHelper3 = this.analyticsHelper) === null || _this$analyticsHelper3 === void 0 ? void 0 : _this$analyticsHelper3.sendActionEvent(EVENT_ACTION.CATCHUP, EVENT_STATUS.SUCCESS, {
@@ -517,6 +534,7 @@ export class DocumentService {
517
534
  this.getUserId = getUserId;
518
535
  this.onErrorHandled = onErrorHandled;
519
536
  this.metadataService = metadataService;
537
+ this.isNameSpaceLocked = isNameSpaceLocked;
520
538
  this.enableErrorOnFailedDocumentApply = enableErrorOnFailedDocumentApply;
521
539
  this.reconcileOnRecovery = reconcileOnRecovery;
522
540
  this.options = options;
@@ -229,10 +229,10 @@ export class Provider extends Emitter {
229
229
  this.participantsService = new ParticipantsService(this.analyticsHelper, undefined, this.emitCallback, this.config.getUser, this.channel.broadcast, this.channel.sendPresenceJoined, this.getPresenceData, this.setUserId);
230
230
  this.metadataService = new MetadataService(this.emitCallback, this.channel.sendMetadata);
231
231
  const reconcileOnRecovery = getCollabProviderFeatureFlag('reconcileOnRecovery', this.config.featureFlags);
232
- this.documentService = new DocumentService(this.participantsService, this.analyticsHelper, this.channel.fetchCatchup, this.channel.fetchCatchupv2, this.channel.fetchReconcile, this.emitCallback, this.channel.broadcast, () => this.userId, this.onErrorHandled, this.metadataService, this.config.enableErrorOnFailedDocumentApply, reconcileOnRecovery, {
232
+ this.namespaceService = new NamespaceService();
233
+ this.documentService = new DocumentService(this.participantsService, this.analyticsHelper, this.channel.fetchCatchup, this.channel.fetchCatchupv2, this.channel.fetchReconcile, this.emitCallback, this.channel.broadcast, () => this.userId, this.onErrorHandled, this.metadataService, this.namespaceService.getIsNamespaceLocked.bind(this.namespaceService), this.config.enableErrorOnFailedDocumentApply, reconcileOnRecovery, {
233
234
  __livePage: this.config.__livePage || false
234
235
  });
235
- this.namespaceService = new NamespaceService();
236
236
  this.api = new Api(config, this.documentService, this.channel);
237
237
  this.sendStepsTimer = setInterval(() => {
238
238
  logger('Intervally sendStepsFromCurrentState');
@@ -1,5 +1,5 @@
1
1
  export const name = "@atlaskit/collab-provider";
2
- export const version = "9.26.1";
2
+ export const version = "9.26.3";
3
3
  export const nextMajorVersion = () => {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -321,7 +321,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
321
321
  };
322
322
  }());
323
323
  _defineProperty(_assertThisInitialized(_this), "fetchCatchupv2", /*#__PURE__*/function () {
324
- var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(fromVersion, clientId) {
324
+ var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(fromVersion, clientId, catchUpOutofSync) {
325
325
  var _yield$utils$requestS2, steps, metadata, errorNotFound, errorCatchupv2;
326
326
  return _regeneratorRuntime.wrap(function _callee3$(_context3) {
327
327
  while (1) switch (_context3.prev = _context3.next) {
@@ -332,7 +332,8 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
332
332
  _context3.t2 = "document/".concat(encodeURIComponent(_this.config.documentAri), "/catchupv2");
333
333
  _context3.t3 = {
334
334
  version: fromVersion,
335
- clientId: clientId
335
+ clientId: clientId,
336
+ catchUpOutofSync: catchUpOutofSync
336
337
  };
337
338
  _context3.t4 = _objectSpread;
338
339
  _context3.t5 = _objectSpread;
@@ -412,7 +413,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
412
413
  }
413
414
  }, _callee3, null, [[0, 31]]);
414
415
  }));
415
- return function (_x3, _x4) {
416
+ return function (_x3, _x4, _x5) {
416
417
  return _ref3.apply(this, arguments);
417
418
  };
418
419
  }());
@@ -485,7 +486,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
485
486
  }
486
487
  }, _callee4, null, [[0, 30]]);
487
488
  }));
488
- return function (_x5, _x6) {
489
+ return function (_x6, _x7) {
489
490
  return _ref4.apply(this, arguments);
490
491
  };
491
492
  }());
@@ -620,7 +621,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
620
621
  }
621
622
  }, _callee5, null, [[1, 9]]);
622
623
  }));
623
- return function auth(_x7) {
624
+ return function auth(_x8) {
624
625
  return _ref5.apply(this, arguments);
625
626
  };
626
627
  }();
@@ -645,7 +646,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
645
646
  }
646
647
  }, _callee6);
647
648
  }));
648
- return function auth(_x8) {
649
+ return function auth(_x9) {
649
650
  return _ref6.apply(this, arguments);
650
651
  };
651
652
  }();
@@ -732,7 +733,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
732
733
  }
733
734
  }, _callee7);
734
735
  }));
735
- return function (_x9) {
736
+ return function (_x10) {
736
737
  return _ref9.apply(this, arguments);
737
738
  };
738
739
  }());
@@ -1,4 +1,7 @@
1
1
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
3
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
2
5
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
6
  import { createLogger } from '../helpers/utils';
4
7
  var logger = createLogger('Catchupv2', 'red');
@@ -11,7 +14,7 @@ export var catchupv2 = /*#__PURE__*/function () {
11
14
  fromVersion = opt.getCurrentPmVersion();
12
15
  _context.prev = 1;
13
16
  _context.next = 4;
14
- return opt.fetchCatchupv2(fromVersion, opt.clientId);
17
+ return opt.fetchCatchupv2(fromVersion, opt.clientId, opt.catchUpOutofSync);
15
18
  case 4:
16
19
  _yield$opt$fetchCatch = _context.sent;
17
20
  steps = _yield$opt$fetchCatch.steps;
@@ -33,21 +36,43 @@ export var catchupv2 = /*#__PURE__*/function () {
33
36
  };
34
37
  opt.onStepsAdded(stepsPayload);
35
38
  opt.updateMetadata(metadata);
36
- _context.next = 26;
37
- break;
38
- case 21:
39
- _context.prev = 21;
39
+ return _context.abrupt("return", Boolean(opt.clientId && isOutOfSync(fromVersion, opt.getCurrentPmVersion(), steps, opt.clientId)));
40
+ case 22:
41
+ _context.prev = 22;
40
42
  _context.t1 = _context["catch"](14);
41
43
  (_opt$analyticsHelper2 = opt.analyticsHelper) === null || _opt$analyticsHelper2 === void 0 || _opt$analyticsHelper2.sendErrorEvent(_context.t1, 'Failed to apply catchupv2 result in the editor');
42
44
  logger("Apply catchupv2 steps failed:", _context.t1.message);
43
45
  throw _context.t1;
44
- case 26:
46
+ case 27:
45
47
  case "end":
46
48
  return _context.stop();
47
49
  }
48
- }, _callee, null, [[1, 9], [14, 21]]);
50
+ }, _callee, null, [[1, 9], [14, 22]]);
49
51
  }));
50
52
  return function catchupv2(_x) {
51
53
  return _ref.apply(this, arguments);
52
54
  };
53
- }();
55
+ }();
56
+ var isOutOfSync = function isOutOfSync(fromVersion, currentVersion, steps, clientId) {
57
+ return (
58
+ // If version number hasn't increased, and steps are not from our client, we're out of sync
59
+ Boolean(fromVersion >= currentVersion && checkForeignSteps(steps, clientId))
60
+ );
61
+ };
62
+ var checkForeignSteps = function checkForeignSteps(steps, clientId) {
63
+ var _iterator = _createForOfIteratorHelper(steps),
64
+ _step;
65
+ try {
66
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
67
+ var step = _step.value;
68
+ if (step.clientId !== clientId) {
69
+ return true;
70
+ }
71
+ }
72
+ } catch (err) {
73
+ _iterator.e(err);
74
+ } finally {
75
+ _iterator.f();
76
+ }
77
+ return false;
78
+ };
@@ -40,17 +40,18 @@ export var DocumentService = /*#__PURE__*/function () {
40
40
  * @param metadataService
41
41
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
42
42
  */
43
- function DocumentService(participantsService, analyticsHelper, fetchCatchup, fetchCatchupv2, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService) {
43
+ function DocumentService(participantsService, analyticsHelper, fetchCatchup, fetchCatchupv2, fetchReconcile, providerEmitCallback, broadcast, getUserId, onErrorHandled, metadataService, isNameSpaceLocked) {
44
44
  var _this = this;
45
- var enableErrorOnFailedDocumentApply = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;
46
- var reconcileOnRecovery = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : false;
47
- var options = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : {
45
+ var enableErrorOnFailedDocumentApply = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : false;
46
+ var reconcileOnRecovery = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : false;
47
+ var options = arguments.length > 13 && arguments[13] !== undefined ? arguments[13] : {
48
48
  __livePage: false
49
49
  };
50
50
  _classCallCheck(this, DocumentService);
51
51
  // Fires analytics to editor when collab editor cannot sync up
52
52
  _defineProperty(this, "stepRejectCounter", 0);
53
53
  _defineProperty(this, "aggressiveCatchup", false);
54
+ _defineProperty(this, "catchUpOutofSync", false);
54
55
  /**
55
56
  * To prevent calling catchup to often, use lodash throttle to reduce the frequency
56
57
  */
@@ -148,43 +149,52 @@ export var DocumentService = /*#__PURE__*/function () {
148
149
  logger("Queue is paused. Aborting.");
149
150
  return _context2.abrupt("return");
150
151
  case 4:
152
+ if (!_this.isNameSpaceLocked()) {
153
+ _context2.next = 7;
154
+ break;
155
+ }
156
+ logger("catchupv2: Document is locked. Aborting.");
157
+ return _context2.abrupt("return");
158
+ case 7:
151
159
  _this.stepQueue.pauseQueue();
152
- _context2.prev = 5;
153
- _context2.next = 8;
160
+ _context2.prev = 8;
161
+ _context2.next = 11;
154
162
  return catchupv2({
155
163
  getCurrentPmVersion: _this.getCurrentPmVersion,
156
164
  fetchCatchupv2: _this.fetchCatchupv2,
157
165
  updateMetadata: _this.metadataService.updateMetadata,
158
166
  analyticsHelper: _this.analyticsHelper,
159
167
  clientId: _this.clientId,
160
- onStepsAdded: _this.onStepsAdded
168
+ onStepsAdded: _this.onStepsAdded,
169
+ catchUpOutofSync: _this.catchUpOutofSync
161
170
  });
162
- case 8:
171
+ case 11:
172
+ _this.catchUpOutofSync = _context2.sent;
163
173
  latency = new Date().getTime() - start;
164
174
  (_this$analyticsHelper3 = _this.analyticsHelper) === null || _this$analyticsHelper3 === void 0 || _this$analyticsHelper3.sendActionEvent(EVENT_ACTION.CATCHUP, EVENT_STATUS.SUCCESS, {
165
175
  latency: latency
166
176
  });
167
- _context2.next = 16;
177
+ _context2.next = 20;
168
178
  break;
169
- case 12:
170
- _context2.prev = 12;
171
- _context2.t0 = _context2["catch"](5);
179
+ case 16:
180
+ _context2.prev = 16;
181
+ _context2.t0 = _context2["catch"](8);
172
182
  _latency2 = new Date().getTime() - start;
173
183
  (_this$analyticsHelper4 = _this.analyticsHelper) === null || _this$analyticsHelper4 === void 0 || _this$analyticsHelper4.sendActionEvent(EVENT_ACTION.CATCHUP, EVENT_STATUS.FAILURE, {
174
184
  latency: _latency2
175
185
  });
176
- case 16:
177
- _context2.prev = 16;
186
+ case 20:
187
+ _context2.prev = 20;
178
188
  _this.stepQueue.resumeQueue();
179
189
  _this.processQueue();
180
190
  _this.sendStepsFromCurrentState(); // this will eventually retry catchup as it calls throttledCommitStep which will either catchup on onStepsAdded or onErrorHandled
181
191
  _this.stepRejectCounter = 0;
182
- return _context2.finish(16);
183
- case 22:
192
+ return _context2.finish(20);
193
+ case 26:
184
194
  case "end":
185
195
  return _context2.stop();
186
196
  }
187
- }, _callee2, null, [[5, 12, 16, 22]]);
197
+ }, _callee2, null, [[8, 16, 20, 26]]);
188
198
  })));
189
199
  _defineProperty(this, "getCurrentPmVersion", function () {
190
200
  var _this$getState;
@@ -646,6 +656,7 @@ export var DocumentService = /*#__PURE__*/function () {
646
656
  this.getUserId = getUserId;
647
657
  this.onErrorHandled = onErrorHandled;
648
658
  this.metadataService = metadataService;
659
+ this.isNameSpaceLocked = isNameSpaceLocked;
649
660
  this.enableErrorOnFailedDocumentApply = enableErrorOnFailedDocumentApply;
650
661
  this.reconcileOnRecovery = reconcileOnRecovery;
651
662
  this.options = options;
@@ -267,12 +267,12 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
267
267
  _this.participantsService = new ParticipantsService(_this.analyticsHelper, undefined, _this.emitCallback, _this.config.getUser, _this.channel.broadcast, _this.channel.sendPresenceJoined, _this.getPresenceData, _this.setUserId);
268
268
  _this.metadataService = new MetadataService(_this.emitCallback, _this.channel.sendMetadata);
269
269
  var reconcileOnRecovery = getCollabProviderFeatureFlag('reconcileOnRecovery', _this.config.featureFlags);
270
+ _this.namespaceService = new NamespaceService();
270
271
  _this.documentService = new DocumentService(_this.participantsService, _this.analyticsHelper, _this.channel.fetchCatchup, _this.channel.fetchCatchupv2, _this.channel.fetchReconcile, _this.emitCallback, _this.channel.broadcast, function () {
271
272
  return _this.userId;
272
- }, _this.onErrorHandled, _this.metadataService, _this.config.enableErrorOnFailedDocumentApply, reconcileOnRecovery, {
273
+ }, _this.onErrorHandled, _this.metadataService, _this.namespaceService.getIsNamespaceLocked.bind(_this.namespaceService), _this.config.enableErrorOnFailedDocumentApply, reconcileOnRecovery, {
273
274
  __livePage: _this.config.__livePage || false
274
275
  });
275
- _this.namespaceService = new NamespaceService();
276
276
  _this.api = new Api(config, _this.documentService, _this.channel);
277
277
  _this.sendStepsTimer = setInterval(function () {
278
278
  logger('Intervally sendStepsFromCurrentState');
@@ -1,5 +1,5 @@
1
1
  export var name = "@atlaskit/collab-provider";
2
- export var version = "9.26.1";
2
+ export var version = "9.26.3";
3
3
  export var nextMajorVersion = function nextMajorVersion() {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -39,7 +39,7 @@ export declare class Channel extends Emitter<ChannelEvent> {
39
39
  private onConnect;
40
40
  private onReceiveData;
41
41
  fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>;
42
- fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined) => Promise<Catchupv2Response>;
42
+ fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined, catchUpOutofSync: boolean | undefined) => Promise<Catchupv2Response>;
43
43
  fetchReconcile: (currentStateDoc: string, reason: string) => Promise<ReconcileResponse>;
44
44
  /**
45
45
  * Send message to the back-end service over the channel. Timestamp will be added server side.
@@ -1,2 +1,2 @@
1
1
  import type { Catchupv2Options } from '../types';
2
- export declare const catchupv2: (opt: Catchupv2Options) => Promise<void>;
2
+ export declare const catchupv2: (opt: Catchupv2Options) => Promise<boolean>;
@@ -19,6 +19,7 @@ export declare class DocumentService {
19
19
  private getUserId;
20
20
  private onErrorHandled;
21
21
  private metadataService;
22
+ private isNameSpaceLocked;
22
23
  private enableErrorOnFailedDocumentApply;
23
24
  private reconcileOnRecovery;
24
25
  private options;
@@ -27,6 +28,7 @@ export declare class DocumentService {
27
28
  private stepQueue;
28
29
  private stepRejectCounter;
29
30
  private aggressiveCatchup;
31
+ private catchUpOutofSync;
30
32
  private clientId?;
31
33
  /**
32
34
  *
@@ -43,7 +45,7 @@ export declare class DocumentService {
43
45
  * @param metadataService
44
46
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
45
47
  */
46
- constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined) => Promise<Catchupv2Response>, fetchReconcile: (currentStateDoc: string, reason: 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, options?: {
48
+ constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined, catchUpOutofSync: boolean) => Promise<Catchupv2Response>, fetchReconcile: (currentStateDoc: string, reason: 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, isNameSpaceLocked: () => boolean, enableErrorOnFailedDocumentApply?: boolean, reconcileOnRecovery?: boolean, options?: {
47
49
  __livePage: boolean;
48
50
  });
49
51
  /**
@@ -209,11 +209,12 @@ export interface CatchupOptions {
209
209
  }
210
210
  export interface Catchupv2Options {
211
211
  getCurrentPmVersion: () => number;
212
- fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined) => Promise<Catchupv2Response>;
212
+ fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined, catchUpOutofSync: boolean) => Promise<Catchupv2Response>;
213
213
  updateMetadata: (metadata: Metadata | undefined) => void;
214
214
  analyticsHelper: AnalyticsHelper | undefined;
215
215
  clientId: number | string | undefined;
216
216
  onStepsAdded: (data: StepsPayload) => void;
217
+ catchUpOutofSync: boolean;
217
218
  }
218
219
  export type ProductInformation = {
219
220
  product: string;
@@ -39,7 +39,7 @@ export declare class Channel extends Emitter<ChannelEvent> {
39
39
  private onConnect;
40
40
  private onReceiveData;
41
41
  fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>;
42
- fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined) => Promise<Catchupv2Response>;
42
+ fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined, catchUpOutofSync: boolean | undefined) => Promise<Catchupv2Response>;
43
43
  fetchReconcile: (currentStateDoc: string, reason: string) => Promise<ReconcileResponse>;
44
44
  /**
45
45
  * Send message to the back-end service over the channel. Timestamp will be added server side.
@@ -1,2 +1,2 @@
1
1
  import type { Catchupv2Options } from '../types';
2
- export declare const catchupv2: (opt: Catchupv2Options) => Promise<void>;
2
+ export declare const catchupv2: (opt: Catchupv2Options) => Promise<boolean>;
@@ -19,6 +19,7 @@ export declare class DocumentService {
19
19
  private getUserId;
20
20
  private onErrorHandled;
21
21
  private metadataService;
22
+ private isNameSpaceLocked;
22
23
  private enableErrorOnFailedDocumentApply;
23
24
  private reconcileOnRecovery;
24
25
  private options;
@@ -27,6 +28,7 @@ export declare class DocumentService {
27
28
  private stepQueue;
28
29
  private stepRejectCounter;
29
30
  private aggressiveCatchup;
31
+ private catchUpOutofSync;
30
32
  private clientId?;
31
33
  /**
32
34
  *
@@ -43,7 +45,7 @@ export declare class DocumentService {
43
45
  * @param metadataService
44
46
  * @param enableErrorOnFailedDocumentApply - Enable failed document update exceptions.
45
47
  */
46
- constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined) => Promise<Catchupv2Response>, fetchReconcile: (currentStateDoc: string, reason: 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, options?: {
48
+ constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number, clientId: number | string | undefined) => Promise<CatchupResponse>, fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined, catchUpOutofSync: boolean) => Promise<Catchupv2Response>, fetchReconcile: (currentStateDoc: string, reason: 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, isNameSpaceLocked: () => boolean, enableErrorOnFailedDocumentApply?: boolean, reconcileOnRecovery?: boolean, options?: {
47
49
  __livePage: boolean;
48
50
  });
49
51
  /**
@@ -209,11 +209,12 @@ export interface CatchupOptions {
209
209
  }
210
210
  export interface Catchupv2Options {
211
211
  getCurrentPmVersion: () => number;
212
- fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined) => Promise<Catchupv2Response>;
212
+ fetchCatchupv2: (fromVersion: number, clientId: number | string | undefined, catchUpOutofSync: boolean) => Promise<Catchupv2Response>;
213
213
  updateMetadata: (metadata: Metadata | undefined) => void;
214
214
  analyticsHelper: AnalyticsHelper | undefined;
215
215
  clientId: number | string | undefined;
216
216
  onStepsAdded: (data: StepsPayload) => void;
217
+ catchUpOutofSync: boolean;
217
218
  }
218
219
  export type ProductInformation = {
219
220
  product: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/collab-provider",
3
- "version": "9.26.1",
3
+ "version": "9.26.3",
4
4
  "description": "A provider for collaborative editing.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "@atlaskit/analytics-gas-types": "^5.1.0",
41
41
  "@atlaskit/analytics-listeners": "^8.9.0",
42
- "@atlaskit/editor-common": "^78.28.0",
42
+ "@atlaskit/editor-common": "^78.29.0",
43
43
  "@atlaskit/editor-json-transformer": "^8.10.0",
44
44
  "@atlaskit/editor-prosemirror": "3.0.0",
45
45
  "@atlaskit/platform-feature-flags": "^0.2.0",