@atlaskit/collab-provider 10.10.2 → 10.11.0
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 +12 -0
- package/dist/cjs/document/document-service.js +13 -2
- package/dist/cjs/document/null-document-service.js +1 -0
- package/dist/cjs/errors/ncs-errors.js +1 -0
- package/dist/cjs/helpers/const.js +1 -0
- package/dist/cjs/provider/commit-step.js +14 -2
- package/dist/cjs/provider/index.js +4 -1
- package/dist/cjs/version-wrapper.js +1 -1
- package/dist/es2019/document/document-service.js +13 -2
- package/dist/es2019/document/null-document-service.js +1 -0
- package/dist/es2019/errors/ncs-errors.js +1 -0
- package/dist/es2019/helpers/const.js +1 -0
- package/dist/es2019/provider/commit-step.js +14 -2
- package/dist/es2019/provider/index.js +4 -1
- package/dist/es2019/version-wrapper.js +1 -1
- package/dist/esm/document/document-service.js +13 -2
- package/dist/esm/document/null-document-service.js +1 -0
- package/dist/esm/errors/ncs-errors.js +1 -0
- package/dist/esm/helpers/const.js +1 -0
- package/dist/esm/provider/commit-step.js +14 -2
- package/dist/esm/provider/index.js +4 -1
- package/dist/esm/version-wrapper.js +1 -1
- package/dist/types/document/document-service.d.ts +7 -0
- package/dist/types/document/null-document-service.d.ts +1 -0
- package/dist/types/errors/ncs-errors.d.ts +11 -2
- package/dist/types/helpers/const.d.ts +2 -1
- package/dist/types/provider/commit-step.d.ts +3 -1
- package/dist/types/types.d.ts +1 -0
- package/dist/types-ts4.5/document/document-service.d.ts +7 -0
- package/dist/types-ts4.5/document/null-document-service.d.ts +1 -0
- package/dist/types-ts4.5/errors/ncs-errors.d.ts +11 -2
- package/dist/types-ts4.5/helpers/const.d.ts +2 -1
- package/dist/types-ts4.5/provider/commit-step.d.ts +3 -1
- package/dist/types-ts4.5/types.d.ts +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @atlaskit/collab-provider
|
|
2
2
|
|
|
3
|
+
## 10.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#130166](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/130166)
|
|
8
|
+
[`1d522a3c3f04a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1d522a3c3f04a) -
|
|
9
|
+
handle corrupt step validation errors and tag first steps from client
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
|
|
3
15
|
## 10.10.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -66,6 +66,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
|
|
|
66
66
|
(0, _defineProperty2.default)(this, "aggressiveCatchup", false);
|
|
67
67
|
(0, _defineProperty2.default)(this, "catchUpOutofSync", false);
|
|
68
68
|
(0, _defineProperty2.default)(this, "hasRecovered", false);
|
|
69
|
+
(0, _defineProperty2.default)(this, "numberOfStepCommitsSent", 0);
|
|
69
70
|
/**
|
|
70
71
|
* To prevent calling catchup to often, use lodash throttle to reduce the frequency
|
|
71
72
|
* @param reason - optional reason to attach.
|
|
@@ -77,6 +78,14 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
|
|
|
77
78
|
// TODO: ED-26957 - why shouldn't this be leading?
|
|
78
79
|
trailing: true
|
|
79
80
|
}));
|
|
81
|
+
/**
|
|
82
|
+
* Updates the number of commits sent since connect/reconnect
|
|
83
|
+
* This is used to track the number of commits sent to the server.
|
|
84
|
+
* currently we are validating the first steps from a user after connect/reconnect - CEPS-710
|
|
85
|
+
*/
|
|
86
|
+
(0, _defineProperty2.default)(this, "setNumberOfCommitsSent", function (steps) {
|
|
87
|
+
_this.numberOfStepCommitsSent = steps;
|
|
88
|
+
});
|
|
80
89
|
/**
|
|
81
90
|
* Called when:
|
|
82
91
|
* * session established(offline -> online)
|
|
@@ -114,7 +123,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
|
|
|
114
123
|
analyticsHelper: _this.analyticsHelper,
|
|
115
124
|
clientId: _this.clientId,
|
|
116
125
|
onStepsAdded: _this.onStepsAdded,
|
|
117
|
-
catchUpOutofSync: _this.catchUpOutofSync,
|
|
126
|
+
catchUpOutofSync: reason === _const.CatchupEventReason.CORRUPT_STEP ? true : _this.catchUpOutofSync,
|
|
118
127
|
reason: reason,
|
|
119
128
|
onCatchupComplete: function onCatchupComplete(steps) {
|
|
120
129
|
// We want to capture the number of steps made while offline vs. online
|
|
@@ -971,7 +980,9 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
|
|
|
971
980
|
__livePage: this.options.__livePage,
|
|
972
981
|
hasRecovered: this.hasRecovered,
|
|
973
982
|
collabMode: this.participantsService.getCollabMode(),
|
|
974
|
-
reason: reason
|
|
983
|
+
reason: reason,
|
|
984
|
+
numberOfStepCommitsSent: this.numberOfStepCommitsSent,
|
|
985
|
+
setNumberOfCommitsSent: this.setNumberOfCommitsSent
|
|
975
986
|
});
|
|
976
987
|
}
|
|
977
988
|
}]);
|
|
@@ -17,6 +17,7 @@ var NullDocumentService = exports.NullDocumentService = /*#__PURE__*/function ()
|
|
|
17
17
|
return _this;
|
|
18
18
|
});
|
|
19
19
|
(0, _defineProperty2.default)(this, "onErrorHandled", function () {});
|
|
20
|
+
(0, _defineProperty2.default)(this, "setNumberOfCommitsSent", function () {});
|
|
20
21
|
}
|
|
21
22
|
return (0, _createClass2.default)(NullDocumentService, [{
|
|
22
23
|
key: "updateDocument",
|
|
@@ -24,6 +24,7 @@ var NCS_ERROR_CODE = exports.NCS_ERROR_CODE = /*#__PURE__*/function (NCS_ERROR_C
|
|
|
24
24
|
NCS_ERROR_CODE["INVALID_CLOUD_ID"] = "INVALID_CLOUD_ID";
|
|
25
25
|
NCS_ERROR_CODE["RATE_LIMIT_ERROR"] = "RATE_LIMIT_ERROR";
|
|
26
26
|
NCS_ERROR_CODE["PROSEMIRROR_SCHEMA_VALIDATION_ERROR"] = "PROSEMIRROR_SCHEMA_VALIDATION_ERROR";
|
|
27
|
+
NCS_ERROR_CODE["CORRUPT_STEP_FAILED_TO_SAVE"] = "CORRUPT_STEP_FAILED_TO_SAVE";
|
|
27
28
|
return NCS_ERROR_CODE;
|
|
28
29
|
}({}); // TODO: ED-26957 - Import emitted error codes from NCS
|
|
29
30
|
// NCS Errors
|
|
@@ -51,5 +51,6 @@ var CatchupEventReason = exports.CatchupEventReason = /*#__PURE__*/function (Cat
|
|
|
51
51
|
CatchupEventReason["STEPS_REJECTED"] = "onStepsRejected";
|
|
52
52
|
CatchupEventReason["PROCESS_STEPS"] = "processSteps";
|
|
53
53
|
CatchupEventReason["RECONNECTED"] = "reconnected";
|
|
54
|
+
CatchupEventReason["CORRUPT_STEP"] = "corruptStep";
|
|
54
55
|
return CatchupEventReason;
|
|
55
56
|
}({});
|
|
@@ -8,6 +8,7 @@ exports.readyToCommit = exports.lastBroadcastRequestAcked = exports.commitStepQu
|
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _countBy = _interopRequireDefault(require("lodash/countBy"));
|
|
10
10
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
11
|
+
var _featureGateJsClient = _interopRequireDefault(require("@atlaskit/feature-gate-js-client"));
|
|
11
12
|
var _const = require("../helpers/const");
|
|
12
13
|
var _types = require("../types");
|
|
13
14
|
var _ncsErrors = require("../errors/ncs-errors");
|
|
@@ -31,7 +32,9 @@ var commitStepQueue = exports.commitStepQueue = function commitStepQueue(_ref) {
|
|
|
31
32
|
__livePage = _ref.__livePage,
|
|
32
33
|
hasRecovered = _ref.hasRecovered,
|
|
33
34
|
collabMode = _ref.collabMode,
|
|
34
|
-
reason = _ref.reason
|
|
35
|
+
reason = _ref.reason,
|
|
36
|
+
numberOfStepCommitsSent = _ref.numberOfStepCommitsSent,
|
|
37
|
+
setNumberOfCommitsSent = _ref.setNumberOfCommitsSent;
|
|
35
38
|
// this timer is for waiting to send the next batch in between acks from the BE
|
|
36
39
|
var commitWaitTimer;
|
|
37
40
|
// if publishing and not waiting for an ACK, then clear the commit timer and proceed, skipping the timer
|
|
@@ -101,11 +104,17 @@ var commitStepQueue = exports.commitStepQueue = function commitStepQueue(_ref) {
|
|
|
101
104
|
version: version
|
|
102
105
|
});
|
|
103
106
|
try {
|
|
107
|
+
var _FeatureGates$getExpe;
|
|
108
|
+
var n = (_FeatureGates$getExpe = _featureGateJsClient.default.getExperimentValue('validate-first-n-steps-experiment', 'steps', 0)) !== null && _FeatureGates$getExpe !== void 0 ? _FeatureGates$getExpe : 0;
|
|
109
|
+
var isExperimentEnabled = n > 0;
|
|
110
|
+
// skip validation if FG is on and we have already sent n steps, or if FG is off
|
|
111
|
+
var skipValidation = isExperimentEnabled ? numberOfStepCommitsSent >= n : true;
|
|
104
112
|
broadcast('steps:commit', {
|
|
105
113
|
collabMode: collabMode,
|
|
106
114
|
steps: stepsWithClientAndUserId,
|
|
107
115
|
version: version,
|
|
108
|
-
userId: userId
|
|
116
|
+
userId: userId,
|
|
117
|
+
skipValidation: skipValidation
|
|
109
118
|
}, function (response) {
|
|
110
119
|
exports.lastBroadcastRequestAcked = lastBroadcastRequestAcked = true;
|
|
111
120
|
var latency = new Date().getTime() - start;
|
|
@@ -150,6 +159,9 @@ var commitStepQueue = exports.commitStepQueue = function commitStepQueue(_ref) {
|
|
|
150
159
|
});
|
|
151
160
|
}
|
|
152
161
|
});
|
|
162
|
+
if (isExperimentEnabled && numberOfStepCommitsSent < n) {
|
|
163
|
+
setNumberOfCommitsSent(numberOfStepCommitsSent + 1);
|
|
164
|
+
}
|
|
153
165
|
} catch (error) {
|
|
154
166
|
// if the broadcast failed for any reason, we shouldn't keep the queue locked as the BE has not recieved any message
|
|
155
167
|
exports.readyToCommit = readyToCommit = true;
|
|
@@ -117,6 +117,7 @@ var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
|
|
|
117
117
|
initial: !initialized
|
|
118
118
|
});
|
|
119
119
|
var unconfirmedStepsLength = (_this$documentService = _this.documentService.getUnconfirmedSteps()) === null || _this$documentService === void 0 ? void 0 : _this$documentService.length;
|
|
120
|
+
_this.documentService.setNumberOfCommitsSent(0);
|
|
120
121
|
|
|
121
122
|
// if buffering is enabled and the provider is initialized before connection,
|
|
122
123
|
// send any unconfirmed steps
|
|
@@ -213,12 +214,14 @@ var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
|
|
|
213
214
|
* @param {InternalError} error The error to handle
|
|
214
215
|
*/
|
|
215
216
|
(0, _defineProperty2.default)(_this, "onErrorHandled", function (error) {
|
|
216
|
-
var _error$data, _error$data2;
|
|
217
|
+
var _error$data, _error$data2, _error$data3;
|
|
217
218
|
// User tried committing steps but they were rejected because:
|
|
218
219
|
// HEAD_VERSION_UPDATE_FAILED: the collab service's latest stored step tail version didn't correspond to the head version of the first step submitted
|
|
219
220
|
// VERSION_NUMBER_ALREADY_EXISTS: while storing the steps there was a conflict meaning someone else wrote steps into the database more quickly
|
|
220
221
|
if (((_error$data = error.data) === null || _error$data === void 0 ? void 0 : _error$data.code) === _ncsErrors.NCS_ERROR_CODE.HEAD_VERSION_UPDATE_FAILED || ((_error$data2 = error.data) === null || _error$data2 === void 0 ? void 0 : _error$data2.code) === _ncsErrors.NCS_ERROR_CODE.VERSION_NUMBER_ALREADY_EXISTS) {
|
|
221
222
|
_this.documentService.onStepRejectedError();
|
|
223
|
+
} else if (((_error$data3 = error.data) === null || _error$data3 === void 0 ? void 0 : _error$data3.code) === _ncsErrors.NCS_ERROR_CODE.CORRUPT_STEP_FAILED_TO_SAVE) {
|
|
224
|
+
_this.documentService.throttledCatchupv2(_const.CatchupEventReason.CORRUPT_STEP);
|
|
222
225
|
} else {
|
|
223
226
|
var _this$analyticsHelper2;
|
|
224
227
|
(_this$analyticsHelper2 = _this.analyticsHelper) === null || _this$analyticsHelper2 === void 0 || _this$analyticsHelper2.sendErrorEvent(error, 'Error handled');
|
|
@@ -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 = "10.
|
|
8
|
+
var version = exports.version = "10.11.0";
|
|
9
9
|
var nextMajorVersion = exports.nextMajorVersion = function nextMajorVersion() {
|
|
10
10
|
return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
|
|
11
11
|
};
|
|
@@ -48,6 +48,7 @@ export class DocumentService {
|
|
|
48
48
|
_defineProperty(this, "aggressiveCatchup", false);
|
|
49
49
|
_defineProperty(this, "catchUpOutofSync", false);
|
|
50
50
|
_defineProperty(this, "hasRecovered", false);
|
|
51
|
+
_defineProperty(this, "numberOfStepCommitsSent", 0);
|
|
51
52
|
/**
|
|
52
53
|
* To prevent calling catchup to often, use lodash throttle to reduce the frequency
|
|
53
54
|
* @param reason - optional reason to attach.
|
|
@@ -57,6 +58,14 @@ export class DocumentService {
|
|
|
57
58
|
// TODO: ED-26957 - why shouldn't this be leading?
|
|
58
59
|
trailing: true
|
|
59
60
|
}));
|
|
61
|
+
/**
|
|
62
|
+
* Updates the number of commits sent since connect/reconnect
|
|
63
|
+
* This is used to track the number of commits sent to the server.
|
|
64
|
+
* currently we are validating the first steps from a user after connect/reconnect - CEPS-710
|
|
65
|
+
*/
|
|
66
|
+
_defineProperty(this, "setNumberOfCommitsSent", steps => {
|
|
67
|
+
this.numberOfStepCommitsSent = steps;
|
|
68
|
+
});
|
|
60
69
|
/**
|
|
61
70
|
* Called when:
|
|
62
71
|
* * session established(offline -> online)
|
|
@@ -107,7 +116,7 @@ export class DocumentService {
|
|
|
107
116
|
analyticsHelper: this.analyticsHelper,
|
|
108
117
|
clientId: this.clientId,
|
|
109
118
|
onStepsAdded: this.onStepsAdded,
|
|
110
|
-
catchUpOutofSync: this.catchUpOutofSync,
|
|
119
|
+
catchUpOutofSync: reason === CatchupEventReason.CORRUPT_STEP ? true : this.catchUpOutofSync,
|
|
111
120
|
reason,
|
|
112
121
|
onCatchupComplete: steps => {
|
|
113
122
|
// We want to capture the number of steps made while offline vs. online
|
|
@@ -845,7 +854,9 @@ export class DocumentService {
|
|
|
845
854
|
__livePage: this.options.__livePage,
|
|
846
855
|
hasRecovered: this.hasRecovered,
|
|
847
856
|
collabMode: this.participantsService.getCollabMode(),
|
|
848
|
-
reason
|
|
857
|
+
reason,
|
|
858
|
+
numberOfStepCommitsSent: this.numberOfStepCommitsSent,
|
|
859
|
+
setNumberOfCommitsSent: this.setNumberOfCommitsSent
|
|
849
860
|
});
|
|
850
861
|
}
|
|
851
862
|
}
|
|
@@ -18,6 +18,7 @@ export let NCS_ERROR_CODE = /*#__PURE__*/function (NCS_ERROR_CODE) {
|
|
|
18
18
|
NCS_ERROR_CODE["INVALID_CLOUD_ID"] = "INVALID_CLOUD_ID";
|
|
19
19
|
NCS_ERROR_CODE["RATE_LIMIT_ERROR"] = "RATE_LIMIT_ERROR";
|
|
20
20
|
NCS_ERROR_CODE["PROSEMIRROR_SCHEMA_VALIDATION_ERROR"] = "PROSEMIRROR_SCHEMA_VALIDATION_ERROR";
|
|
21
|
+
NCS_ERROR_CODE["CORRUPT_STEP_FAILED_TO_SAVE"] = "CORRUPT_STEP_FAILED_TO_SAVE";
|
|
21
22
|
return NCS_ERROR_CODE;
|
|
22
23
|
}({});
|
|
23
24
|
|
|
@@ -45,5 +45,6 @@ export let CatchupEventReason = /*#__PURE__*/function (CatchupEventReason) {
|
|
|
45
45
|
CatchupEventReason["STEPS_REJECTED"] = "onStepsRejected";
|
|
46
46
|
CatchupEventReason["PROCESS_STEPS"] = "processSteps";
|
|
47
47
|
CatchupEventReason["RECONNECTED"] = "reconnected";
|
|
48
|
+
CatchupEventReason["CORRUPT_STEP"] = "corruptStep";
|
|
48
49
|
return CatchupEventReason;
|
|
49
50
|
}({});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import countBy from 'lodash/countBy';
|
|
2
2
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
|
+
import FeatureGates from '@atlaskit/feature-gate-js-client';
|
|
3
4
|
import { ADD_STEPS_TYPE, EVENT_ACTION, EVENT_STATUS } from '../helpers/const';
|
|
4
5
|
import { AcknowledgementResponseTypes } from '../types';
|
|
5
6
|
import { NCS_ERROR_CODE } from '../errors/ncs-errors';
|
|
@@ -21,7 +22,9 @@ export const commitStepQueue = ({
|
|
|
21
22
|
__livePage,
|
|
22
23
|
hasRecovered,
|
|
23
24
|
collabMode,
|
|
24
|
-
reason
|
|
25
|
+
reason,
|
|
26
|
+
numberOfStepCommitsSent,
|
|
27
|
+
setNumberOfCommitsSent
|
|
25
28
|
}) => {
|
|
26
29
|
// this timer is for waiting to send the next batch in between acks from the BE
|
|
27
30
|
let commitWaitTimer;
|
|
@@ -93,11 +96,17 @@ export const commitStepQueue = ({
|
|
|
93
96
|
version
|
|
94
97
|
});
|
|
95
98
|
try {
|
|
99
|
+
var _FeatureGates$getExpe;
|
|
100
|
+
const n = (_FeatureGates$getExpe = FeatureGates.getExperimentValue('validate-first-n-steps-experiment', 'steps', 0)) !== null && _FeatureGates$getExpe !== void 0 ? _FeatureGates$getExpe : 0;
|
|
101
|
+
const isExperimentEnabled = n > 0;
|
|
102
|
+
// skip validation if FG is on and we have already sent n steps, or if FG is off
|
|
103
|
+
const skipValidation = isExperimentEnabled ? numberOfStepCommitsSent >= n : true;
|
|
96
104
|
broadcast('steps:commit', {
|
|
97
105
|
collabMode,
|
|
98
106
|
steps: stepsWithClientAndUserId,
|
|
99
107
|
version,
|
|
100
|
-
userId
|
|
108
|
+
userId,
|
|
109
|
+
skipValidation
|
|
101
110
|
}, response => {
|
|
102
111
|
lastBroadcastRequestAcked = true;
|
|
103
112
|
const latency = new Date().getTime() - start;
|
|
@@ -142,6 +151,9 @@ export const commitStepQueue = ({
|
|
|
142
151
|
});
|
|
143
152
|
}
|
|
144
153
|
});
|
|
154
|
+
if (isExperimentEnabled && numberOfStepCommitsSent < n) {
|
|
155
|
+
setNumberOfCommitsSent(numberOfStepCommitsSent + 1);
|
|
156
|
+
}
|
|
145
157
|
} catch (error) {
|
|
146
158
|
// if the broadcast failed for any reason, we shouldn't keep the queue locked as the BE has not recieved any message
|
|
147
159
|
readyToCommit = true;
|
|
@@ -95,6 +95,7 @@ export class Provider extends Emitter {
|
|
|
95
95
|
initial: !initialized
|
|
96
96
|
});
|
|
97
97
|
const unconfirmedStepsLength = (_this$documentService = this.documentService.getUnconfirmedSteps()) === null || _this$documentService === void 0 ? void 0 : _this$documentService.length;
|
|
98
|
+
this.documentService.setNumberOfCommitsSent(0);
|
|
98
99
|
|
|
99
100
|
// if buffering is enabled and the provider is initialized before connection,
|
|
100
101
|
// send any unconfirmed steps
|
|
@@ -175,12 +176,14 @@ export class Provider extends Emitter {
|
|
|
175
176
|
* @param {InternalError} error The error to handle
|
|
176
177
|
*/
|
|
177
178
|
_defineProperty(this, "onErrorHandled", error => {
|
|
178
|
-
var _error$data, _error$data2;
|
|
179
|
+
var _error$data, _error$data2, _error$data3;
|
|
179
180
|
// User tried committing steps but they were rejected because:
|
|
180
181
|
// HEAD_VERSION_UPDATE_FAILED: the collab service's latest stored step tail version didn't correspond to the head version of the first step submitted
|
|
181
182
|
// VERSION_NUMBER_ALREADY_EXISTS: while storing the steps there was a conflict meaning someone else wrote steps into the database more quickly
|
|
182
183
|
if (((_error$data = error.data) === null || _error$data === void 0 ? void 0 : _error$data.code) === NCS_ERROR_CODE.HEAD_VERSION_UPDATE_FAILED || ((_error$data2 = error.data) === null || _error$data2 === void 0 ? void 0 : _error$data2.code) === NCS_ERROR_CODE.VERSION_NUMBER_ALREADY_EXISTS) {
|
|
183
184
|
this.documentService.onStepRejectedError();
|
|
185
|
+
} else if (((_error$data3 = error.data) === null || _error$data3 === void 0 ? void 0 : _error$data3.code) === NCS_ERROR_CODE.CORRUPT_STEP_FAILED_TO_SAVE) {
|
|
186
|
+
this.documentService.throttledCatchupv2(CatchupEventReason.CORRUPT_STEP);
|
|
184
187
|
} else {
|
|
185
188
|
var _this$analyticsHelper2;
|
|
186
189
|
(_this$analyticsHelper2 = this.analyticsHelper) === null || _this$analyticsHelper2 === void 0 ? void 0 : _this$analyticsHelper2.sendErrorEvent(error, 'Error handled');
|
|
@@ -59,6 +59,7 @@ export var DocumentService = /*#__PURE__*/function () {
|
|
|
59
59
|
_defineProperty(this, "aggressiveCatchup", false);
|
|
60
60
|
_defineProperty(this, "catchUpOutofSync", false);
|
|
61
61
|
_defineProperty(this, "hasRecovered", false);
|
|
62
|
+
_defineProperty(this, "numberOfStepCommitsSent", 0);
|
|
62
63
|
/**
|
|
63
64
|
* To prevent calling catchup to often, use lodash throttle to reduce the frequency
|
|
64
65
|
* @param reason - optional reason to attach.
|
|
@@ -70,6 +71,14 @@ export var DocumentService = /*#__PURE__*/function () {
|
|
|
70
71
|
// TODO: ED-26957 - why shouldn't this be leading?
|
|
71
72
|
trailing: true
|
|
72
73
|
}));
|
|
74
|
+
/**
|
|
75
|
+
* Updates the number of commits sent since connect/reconnect
|
|
76
|
+
* This is used to track the number of commits sent to the server.
|
|
77
|
+
* currently we are validating the first steps from a user after connect/reconnect - CEPS-710
|
|
78
|
+
*/
|
|
79
|
+
_defineProperty(this, "setNumberOfCommitsSent", function (steps) {
|
|
80
|
+
_this.numberOfStepCommitsSent = steps;
|
|
81
|
+
});
|
|
73
82
|
/**
|
|
74
83
|
* Called when:
|
|
75
84
|
* * session established(offline -> online)
|
|
@@ -107,7 +116,7 @@ export var DocumentService = /*#__PURE__*/function () {
|
|
|
107
116
|
analyticsHelper: _this.analyticsHelper,
|
|
108
117
|
clientId: _this.clientId,
|
|
109
118
|
onStepsAdded: _this.onStepsAdded,
|
|
110
|
-
catchUpOutofSync: _this.catchUpOutofSync,
|
|
119
|
+
catchUpOutofSync: reason === CatchupEventReason.CORRUPT_STEP ? true : _this.catchUpOutofSync,
|
|
111
120
|
reason: reason,
|
|
112
121
|
onCatchupComplete: function onCatchupComplete(steps) {
|
|
113
122
|
// We want to capture the number of steps made while offline vs. online
|
|
@@ -964,7 +973,9 @@ export var DocumentService = /*#__PURE__*/function () {
|
|
|
964
973
|
__livePage: this.options.__livePage,
|
|
965
974
|
hasRecovered: this.hasRecovered,
|
|
966
975
|
collabMode: this.participantsService.getCollabMode(),
|
|
967
|
-
reason: reason
|
|
976
|
+
reason: reason,
|
|
977
|
+
numberOfStepCommitsSent: this.numberOfStepCommitsSent,
|
|
978
|
+
setNumberOfCommitsSent: this.setNumberOfCommitsSent
|
|
968
979
|
});
|
|
969
980
|
}
|
|
970
981
|
}]);
|
|
@@ -10,6 +10,7 @@ export var NullDocumentService = /*#__PURE__*/function () {
|
|
|
10
10
|
return _this;
|
|
11
11
|
});
|
|
12
12
|
_defineProperty(this, "onErrorHandled", function () {});
|
|
13
|
+
_defineProperty(this, "setNumberOfCommitsSent", function () {});
|
|
13
14
|
}
|
|
14
15
|
return _createClass(NullDocumentService, [{
|
|
15
16
|
key: "updateDocument",
|
|
@@ -18,6 +18,7 @@ export var NCS_ERROR_CODE = /*#__PURE__*/function (NCS_ERROR_CODE) {
|
|
|
18
18
|
NCS_ERROR_CODE["INVALID_CLOUD_ID"] = "INVALID_CLOUD_ID";
|
|
19
19
|
NCS_ERROR_CODE["RATE_LIMIT_ERROR"] = "RATE_LIMIT_ERROR";
|
|
20
20
|
NCS_ERROR_CODE["PROSEMIRROR_SCHEMA_VALIDATION_ERROR"] = "PROSEMIRROR_SCHEMA_VALIDATION_ERROR";
|
|
21
|
+
NCS_ERROR_CODE["CORRUPT_STEP_FAILED_TO_SAVE"] = "CORRUPT_STEP_FAILED_TO_SAVE";
|
|
21
22
|
return NCS_ERROR_CODE;
|
|
22
23
|
}({});
|
|
23
24
|
|
|
@@ -45,5 +45,6 @@ export var CatchupEventReason = /*#__PURE__*/function (CatchupEventReason) {
|
|
|
45
45
|
CatchupEventReason["STEPS_REJECTED"] = "onStepsRejected";
|
|
46
46
|
CatchupEventReason["PROCESS_STEPS"] = "processSteps";
|
|
47
47
|
CatchupEventReason["RECONNECTED"] = "reconnected";
|
|
48
|
+
CatchupEventReason["CORRUPT_STEP"] = "corruptStep";
|
|
48
49
|
return CatchupEventReason;
|
|
49
50
|
}({});
|
|
@@ -3,6 +3,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
|
|
|
3
3
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
4
|
import countBy from 'lodash/countBy';
|
|
5
5
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
|
+
import FeatureGates from '@atlaskit/feature-gate-js-client';
|
|
6
7
|
import { ADD_STEPS_TYPE, EVENT_ACTION, EVENT_STATUS } from '../helpers/const';
|
|
7
8
|
import { AcknowledgementResponseTypes } from '../types';
|
|
8
9
|
import { NCS_ERROR_CODE } from '../errors/ncs-errors';
|
|
@@ -24,7 +25,9 @@ export var commitStepQueue = function commitStepQueue(_ref) {
|
|
|
24
25
|
__livePage = _ref.__livePage,
|
|
25
26
|
hasRecovered = _ref.hasRecovered,
|
|
26
27
|
collabMode = _ref.collabMode,
|
|
27
|
-
reason = _ref.reason
|
|
28
|
+
reason = _ref.reason,
|
|
29
|
+
numberOfStepCommitsSent = _ref.numberOfStepCommitsSent,
|
|
30
|
+
setNumberOfCommitsSent = _ref.setNumberOfCommitsSent;
|
|
28
31
|
// this timer is for waiting to send the next batch in between acks from the BE
|
|
29
32
|
var commitWaitTimer;
|
|
30
33
|
// if publishing and not waiting for an ACK, then clear the commit timer and proceed, skipping the timer
|
|
@@ -94,11 +97,17 @@ export var commitStepQueue = function commitStepQueue(_ref) {
|
|
|
94
97
|
version: version
|
|
95
98
|
});
|
|
96
99
|
try {
|
|
100
|
+
var _FeatureGates$getExpe;
|
|
101
|
+
var n = (_FeatureGates$getExpe = FeatureGates.getExperimentValue('validate-first-n-steps-experiment', 'steps', 0)) !== null && _FeatureGates$getExpe !== void 0 ? _FeatureGates$getExpe : 0;
|
|
102
|
+
var isExperimentEnabled = n > 0;
|
|
103
|
+
// skip validation if FG is on and we have already sent n steps, or if FG is off
|
|
104
|
+
var skipValidation = isExperimentEnabled ? numberOfStepCommitsSent >= n : true;
|
|
97
105
|
broadcast('steps:commit', {
|
|
98
106
|
collabMode: collabMode,
|
|
99
107
|
steps: stepsWithClientAndUserId,
|
|
100
108
|
version: version,
|
|
101
|
-
userId: userId
|
|
109
|
+
userId: userId,
|
|
110
|
+
skipValidation: skipValidation
|
|
102
111
|
}, function (response) {
|
|
103
112
|
lastBroadcastRequestAcked = true;
|
|
104
113
|
var latency = new Date().getTime() - start;
|
|
@@ -143,6 +152,9 @@ export var commitStepQueue = function commitStepQueue(_ref) {
|
|
|
143
152
|
});
|
|
144
153
|
}
|
|
145
154
|
});
|
|
155
|
+
if (isExperimentEnabled && numberOfStepCommitsSent < n) {
|
|
156
|
+
setNumberOfCommitsSent(numberOfStepCommitsSent + 1);
|
|
157
|
+
}
|
|
146
158
|
} catch (error) {
|
|
147
159
|
// if the broadcast failed for any reason, we shouldn't keep the queue locked as the BE has not recieved any message
|
|
148
160
|
readyToCommit = true;
|
|
@@ -110,6 +110,7 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
|
|
|
110
110
|
initial: !initialized
|
|
111
111
|
});
|
|
112
112
|
var unconfirmedStepsLength = (_this$documentService = _this.documentService.getUnconfirmedSteps()) === null || _this$documentService === void 0 ? void 0 : _this$documentService.length;
|
|
113
|
+
_this.documentService.setNumberOfCommitsSent(0);
|
|
113
114
|
|
|
114
115
|
// if buffering is enabled and the provider is initialized before connection,
|
|
115
116
|
// send any unconfirmed steps
|
|
@@ -206,12 +207,14 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
|
|
|
206
207
|
* @param {InternalError} error The error to handle
|
|
207
208
|
*/
|
|
208
209
|
_defineProperty(_this, "onErrorHandled", function (error) {
|
|
209
|
-
var _error$data, _error$data2;
|
|
210
|
+
var _error$data, _error$data2, _error$data3;
|
|
210
211
|
// User tried committing steps but they were rejected because:
|
|
211
212
|
// HEAD_VERSION_UPDATE_FAILED: the collab service's latest stored step tail version didn't correspond to the head version of the first step submitted
|
|
212
213
|
// VERSION_NUMBER_ALREADY_EXISTS: while storing the steps there was a conflict meaning someone else wrote steps into the database more quickly
|
|
213
214
|
if (((_error$data = error.data) === null || _error$data === void 0 ? void 0 : _error$data.code) === NCS_ERROR_CODE.HEAD_VERSION_UPDATE_FAILED || ((_error$data2 = error.data) === null || _error$data2 === void 0 ? void 0 : _error$data2.code) === NCS_ERROR_CODE.VERSION_NUMBER_ALREADY_EXISTS) {
|
|
214
215
|
_this.documentService.onStepRejectedError();
|
|
216
|
+
} else if (((_error$data3 = error.data) === null || _error$data3 === void 0 ? void 0 : _error$data3.code) === NCS_ERROR_CODE.CORRUPT_STEP_FAILED_TO_SAVE) {
|
|
217
|
+
_this.documentService.throttledCatchupv2(CatchupEventReason.CORRUPT_STEP);
|
|
215
218
|
} else {
|
|
216
219
|
var _this$analyticsHelper2;
|
|
217
220
|
(_this$analyticsHelper2 = _this.analyticsHelper) === null || _this$analyticsHelper2 === void 0 || _this$analyticsHelper2.sendErrorEvent(error, 'Error handled');
|
|
@@ -31,6 +31,7 @@ export declare class DocumentService implements DocumentServiceInterface {
|
|
|
31
31
|
private aggressiveCatchup;
|
|
32
32
|
private catchUpOutofSync;
|
|
33
33
|
private hasRecovered;
|
|
34
|
+
private numberOfStepCommitsSent;
|
|
34
35
|
private clientId?;
|
|
35
36
|
onErrorHandled: (error: InternalError) => void;
|
|
36
37
|
/**
|
|
@@ -56,6 +57,12 @@ export declare class DocumentService implements DocumentServiceInterface {
|
|
|
56
57
|
* @param reason - optional reason to attach.
|
|
57
58
|
*/
|
|
58
59
|
throttledCatchupv2: import("lodash").DebouncedFunc<(reason?: CatchupEventReason, reconnectionMetadata?: ReconnectionMetadata) => Promise<void>>;
|
|
60
|
+
/**
|
|
61
|
+
* Updates the number of commits sent since connect/reconnect
|
|
62
|
+
* This is used to track the number of commits sent to the server.
|
|
63
|
+
* currently we are validating the first steps from a user after connect/reconnect - CEPS-710
|
|
64
|
+
*/
|
|
65
|
+
setNumberOfCommitsSent: (steps: number) => void;
|
|
59
66
|
/**
|
|
60
67
|
* Called when:
|
|
61
68
|
* * session established(offline -> online)
|
|
@@ -16,7 +16,8 @@ export declare enum NCS_ERROR_CODE {
|
|
|
16
16
|
INVALID_DOCUMENT_ARI = "INVALID_DOCUMENT_ARI",
|
|
17
17
|
INVALID_CLOUD_ID = "INVALID_CLOUD_ID",
|
|
18
18
|
RATE_LIMIT_ERROR = "RATE_LIMIT_ERROR",
|
|
19
|
-
PROSEMIRROR_SCHEMA_VALIDATION_ERROR = "PROSEMIRROR_SCHEMA_VALIDATION_ERROR"
|
|
19
|
+
PROSEMIRROR_SCHEMA_VALIDATION_ERROR = "PROSEMIRROR_SCHEMA_VALIDATION_ERROR",
|
|
20
|
+
CORRUPT_STEP_FAILED_TO_SAVE = "CORRUPT_STEP_FAILED_TO_SAVE"
|
|
20
21
|
}
|
|
21
22
|
type HeadVersionUpdateFailedError = {
|
|
22
23
|
message: string;
|
|
@@ -163,6 +164,14 @@ type InvalidCloudIdError = {
|
|
|
163
164
|
status: number;
|
|
164
165
|
};
|
|
165
166
|
};
|
|
167
|
+
type CorruptStepFailedToApplyError = {
|
|
168
|
+
message: string;
|
|
169
|
+
data: {
|
|
170
|
+
code: NCS_ERROR_CODE.CORRUPT_STEP_FAILED_TO_SAVE;
|
|
171
|
+
meta: string;
|
|
172
|
+
status: number;
|
|
173
|
+
};
|
|
174
|
+
};
|
|
166
175
|
/**
|
|
167
176
|
* The client is trying to send too many messages or messages that are too large. This not expected to be a standard
|
|
168
177
|
* operating condition and should only ever indicate a frontend bug.
|
|
@@ -180,5 +189,5 @@ export type RateLimitError = {
|
|
|
180
189
|
status: 500;
|
|
181
190
|
};
|
|
182
191
|
};
|
|
183
|
-
export type NCSErrors = HeadVersionUpdateFailedError | VersionAlreadyPresentInDynamoError | InsufficientEditingPermissionError | ForbiddenUserTokenError | NCSDocumentNotFoundError | FailedToLoadInitDataError | ErrorMappingError | InvalidNamespaceDefinedError | SocketNamespaceNotFoundError | TenantInstanceMaintenanceError | NamespaceLockedError | EmptyBroadcastError | DynamoError | InvalidActivationIdError | InvalidDocumentAriError | InvalidCloudIdError | RateLimitError | ProsemirrorSchemaValidationError;
|
|
192
|
+
export type NCSErrors = HeadVersionUpdateFailedError | VersionAlreadyPresentInDynamoError | InsufficientEditingPermissionError | ForbiddenUserTokenError | NCSDocumentNotFoundError | FailedToLoadInitDataError | ErrorMappingError | InvalidNamespaceDefinedError | SocketNamespaceNotFoundError | TenantInstanceMaintenanceError | NamespaceLockedError | EmptyBroadcastError | DynamoError | InvalidActivationIdError | InvalidDocumentAriError | InvalidCloudIdError | RateLimitError | ProsemirrorSchemaValidationError | CorruptStepFailedToApplyError;
|
|
184
193
|
export {};
|
|
@@ -303,6 +303,7 @@ export declare enum CatchupEventReason {
|
|
|
303
303
|
STEPS_ADDED = "onStepsAdded",
|
|
304
304
|
STEPS_REJECTED = "onStepsRejected",
|
|
305
305
|
PROCESS_STEPS = "processSteps",
|
|
306
|
-
RECONNECTED = "reconnected"
|
|
306
|
+
RECONNECTED = "reconnected",
|
|
307
|
+
CORRUPT_STEP = "corruptStep"
|
|
307
308
|
}
|
|
308
309
|
export {};
|
|
@@ -7,7 +7,7 @@ import type { GetResolvedEditorStateReason } from '@atlaskit/editor-common/types
|
|
|
7
7
|
export declare let readyToCommit: boolean;
|
|
8
8
|
export declare let lastBroadcastRequestAcked: boolean;
|
|
9
9
|
export declare const RESET_READYTOCOMMIT_INTERVAL_MS = 5000;
|
|
10
|
-
export declare const commitStepQueue: ({ broadcast, steps, version, userId, clientId, onStepsAdded, onErrorHandled, analyticsHelper, emit, __livePage, hasRecovered, collabMode, reason, }: {
|
|
10
|
+
export declare const commitStepQueue: ({ broadcast, steps, version, userId, clientId, onStepsAdded, onErrorHandled, analyticsHelper, emit, __livePage, hasRecovered, collabMode, reason, numberOfStepCommitsSent, setNumberOfCommitsSent, }: {
|
|
11
11
|
broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void;
|
|
12
12
|
steps: readonly ProseMirrorStep[];
|
|
13
13
|
version: number;
|
|
@@ -21,4 +21,6 @@ export declare const commitStepQueue: ({ broadcast, steps, version, userId, clie
|
|
|
21
21
|
hasRecovered: boolean;
|
|
22
22
|
collabMode: string;
|
|
23
23
|
reason?: GetResolvedEditorStateReason | undefined;
|
|
24
|
+
numberOfStepCommitsSent: number;
|
|
25
|
+
setNumberOfCommitsSent: (steps: number) => void;
|
|
24
26
|
}) => void;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export declare class DocumentService implements DocumentServiceInterface {
|
|
|
31
31
|
private aggressiveCatchup;
|
|
32
32
|
private catchUpOutofSync;
|
|
33
33
|
private hasRecovered;
|
|
34
|
+
private numberOfStepCommitsSent;
|
|
34
35
|
private clientId?;
|
|
35
36
|
onErrorHandled: (error: InternalError) => void;
|
|
36
37
|
/**
|
|
@@ -56,6 +57,12 @@ export declare class DocumentService implements DocumentServiceInterface {
|
|
|
56
57
|
* @param reason - optional reason to attach.
|
|
57
58
|
*/
|
|
58
59
|
throttledCatchupv2: import("lodash").DebouncedFunc<(reason?: CatchupEventReason, reconnectionMetadata?: ReconnectionMetadata) => Promise<void>>;
|
|
60
|
+
/**
|
|
61
|
+
* Updates the number of commits sent since connect/reconnect
|
|
62
|
+
* This is used to track the number of commits sent to the server.
|
|
63
|
+
* currently we are validating the first steps from a user after connect/reconnect - CEPS-710
|
|
64
|
+
*/
|
|
65
|
+
setNumberOfCommitsSent: (steps: number) => void;
|
|
59
66
|
/**
|
|
60
67
|
* Called when:
|
|
61
68
|
* * session established(offline -> online)
|
|
@@ -16,7 +16,8 @@ export declare enum NCS_ERROR_CODE {
|
|
|
16
16
|
INVALID_DOCUMENT_ARI = "INVALID_DOCUMENT_ARI",
|
|
17
17
|
INVALID_CLOUD_ID = "INVALID_CLOUD_ID",
|
|
18
18
|
RATE_LIMIT_ERROR = "RATE_LIMIT_ERROR",
|
|
19
|
-
PROSEMIRROR_SCHEMA_VALIDATION_ERROR = "PROSEMIRROR_SCHEMA_VALIDATION_ERROR"
|
|
19
|
+
PROSEMIRROR_SCHEMA_VALIDATION_ERROR = "PROSEMIRROR_SCHEMA_VALIDATION_ERROR",
|
|
20
|
+
CORRUPT_STEP_FAILED_TO_SAVE = "CORRUPT_STEP_FAILED_TO_SAVE"
|
|
20
21
|
}
|
|
21
22
|
type HeadVersionUpdateFailedError = {
|
|
22
23
|
message: string;
|
|
@@ -163,6 +164,14 @@ type InvalidCloudIdError = {
|
|
|
163
164
|
status: number;
|
|
164
165
|
};
|
|
165
166
|
};
|
|
167
|
+
type CorruptStepFailedToApplyError = {
|
|
168
|
+
message: string;
|
|
169
|
+
data: {
|
|
170
|
+
code: NCS_ERROR_CODE.CORRUPT_STEP_FAILED_TO_SAVE;
|
|
171
|
+
meta: string;
|
|
172
|
+
status: number;
|
|
173
|
+
};
|
|
174
|
+
};
|
|
166
175
|
/**
|
|
167
176
|
* The client is trying to send too many messages or messages that are too large. This not expected to be a standard
|
|
168
177
|
* operating condition and should only ever indicate a frontend bug.
|
|
@@ -180,5 +189,5 @@ export type RateLimitError = {
|
|
|
180
189
|
status: 500;
|
|
181
190
|
};
|
|
182
191
|
};
|
|
183
|
-
export type NCSErrors = HeadVersionUpdateFailedError | VersionAlreadyPresentInDynamoError | InsufficientEditingPermissionError | ForbiddenUserTokenError | NCSDocumentNotFoundError | FailedToLoadInitDataError | ErrorMappingError | InvalidNamespaceDefinedError | SocketNamespaceNotFoundError | TenantInstanceMaintenanceError | NamespaceLockedError | EmptyBroadcastError | DynamoError | InvalidActivationIdError | InvalidDocumentAriError | InvalidCloudIdError | RateLimitError | ProsemirrorSchemaValidationError;
|
|
192
|
+
export type NCSErrors = HeadVersionUpdateFailedError | VersionAlreadyPresentInDynamoError | InsufficientEditingPermissionError | ForbiddenUserTokenError | NCSDocumentNotFoundError | FailedToLoadInitDataError | ErrorMappingError | InvalidNamespaceDefinedError | SocketNamespaceNotFoundError | TenantInstanceMaintenanceError | NamespaceLockedError | EmptyBroadcastError | DynamoError | InvalidActivationIdError | InvalidDocumentAriError | InvalidCloudIdError | RateLimitError | ProsemirrorSchemaValidationError | CorruptStepFailedToApplyError;
|
|
184
193
|
export {};
|
|
@@ -303,6 +303,7 @@ export declare enum CatchupEventReason {
|
|
|
303
303
|
STEPS_ADDED = "onStepsAdded",
|
|
304
304
|
STEPS_REJECTED = "onStepsRejected",
|
|
305
305
|
PROCESS_STEPS = "processSteps",
|
|
306
|
-
RECONNECTED = "reconnected"
|
|
306
|
+
RECONNECTED = "reconnected",
|
|
307
|
+
CORRUPT_STEP = "corruptStep"
|
|
307
308
|
}
|
|
308
309
|
export {};
|
|
@@ -7,7 +7,7 @@ import type { GetResolvedEditorStateReason } from '@atlaskit/editor-common/types
|
|
|
7
7
|
export declare let readyToCommit: boolean;
|
|
8
8
|
export declare let lastBroadcastRequestAcked: boolean;
|
|
9
9
|
export declare const RESET_READYTOCOMMIT_INTERVAL_MS = 5000;
|
|
10
|
-
export declare const commitStepQueue: ({ broadcast, steps, version, userId, clientId, onStepsAdded, onErrorHandled, analyticsHelper, emit, __livePage, hasRecovered, collabMode, reason, }: {
|
|
10
|
+
export declare const commitStepQueue: ({ broadcast, steps, version, userId, clientId, onStepsAdded, onErrorHandled, analyticsHelper, emit, __livePage, hasRecovered, collabMode, reason, numberOfStepCommitsSent, setNumberOfCommitsSent, }: {
|
|
11
11
|
broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void;
|
|
12
12
|
steps: readonly ProseMirrorStep[];
|
|
13
13
|
version: number;
|
|
@@ -21,4 +21,6 @@ export declare const commitStepQueue: ({ broadcast, steps, version, userId, clie
|
|
|
21
21
|
hasRecovered: boolean;
|
|
22
22
|
collabMode: string;
|
|
23
23
|
reason?: GetResolvedEditorStateReason | undefined;
|
|
24
|
+
numberOfStepCommitsSent: number;
|
|
25
|
+
setNumberOfCommitsSent: (steps: number) => void;
|
|
24
26
|
}) => void;
|