Skip to content

Commit fea81ba

Browse files
author
Alec Gibson
committed
Review markups
- Add documentation for common errors - Americanize spelling - Add a special error for invalid Milestone DB arguments
1 parent 5fa1be3 commit fea81ba

File tree

5 files changed

+94
-14
lines changed

5 files changed

+94
-14
lines changed

README.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,3 +662,82 @@ ShareDB returns errors as plain JavaScript objects with the format:
662662
```
663663

664664
Additional fields may be added to the error object for debugging context depending on the error. Common additional fields include `collection`, `id`, and `op`.
665+
666+
### Common error codes
667+
668+
#### `ERR_OP_SUBMIT_REJECTED`
669+
670+
The op submitted by the client has been rejected by the server for a non-critical reason.
671+
672+
When the client receives this code, it will attempt to roll back the rejected op, leaving the client in a usable state.
673+
674+
This error might be used as part of standard control flow. For example, consumers may define a middleware that validates document structure, and rejects operations that do not conform to this schema using this error code to reset the client to a valid state.
675+
676+
#### `ERR_OP_ALREADY_SUBMITTED`
677+
678+
The same op has been received by the server twice.
679+
680+
This is non-critical, and part of normal control flow, and is sent as an error in order to short-circuit the op processing. It is eventually swallowed by the server, and shouldn't need further handling.
681+
682+
#### `ERR_SUBMIT_TRANSFORM_OPS_NOT_FOUND`
683+
684+
The ops needed to transform the submitted op up to the current version of the snapshot could not be found.
685+
686+
If a client on an old version of a document submits an op, that op needs to be transformed by all the ops that have been applied to the document in the meantime. If the server cannot fetch these ops from the database, then this error is returned.
687+
688+
The most common case of this would be ops being deleted from the database. For example, let's assume we have a TTL set up on the ops in our database. Let's also say we have a client that is so old that the op corresponding to its version has been deleted by the TTL policy. If this client then attempts to submit an op, the server will not be able to find the ops required to transform the op to apply to the current version of the snapshot.
689+
690+
Other causes of this error may be dropping the ops collection all together, or having the database corrupted in some other way.
691+
692+
#### `ERR_MAX_SUBMIT_RETRIES_EXCEEDED`
693+
694+
The number of retries defined by the `maxSubmitRetries` option has been exceeded by a submission.
695+
696+
#### `ERR_DOC_ALREADY_CREATED`
697+
698+
The creation request has failed, because the document was already created by another client.
699+
700+
This can happen when two clients happen to simultaneously try to create the same document, and is potentially recoverable by simply fetching the already-created document.
701+
702+
#### `ERR_DOC_ALREADY_DELETED`
703+
704+
The deletion request has failed, because the document was already deleted by another client.
705+
706+
This can happen when two clients happen to simultaneously try to delete the same document. Given that the end result is the same, this error can potentially just be ignored.
707+
708+
#### `ERR_DOC_TYPE_NOT_RECOGNIZED`
709+
710+
The specified document type has not been registered with ShareDB.
711+
712+
This error can usually be remedied by remembering to register any types you need:
713+
714+
```javascript
715+
var ShareDB = require('sharedb');
716+
var richText = require('rich-text');
717+
718+
ShareDB.types.register(richText.type);
719+
```
720+
721+
#### `ERR_DEFAULT_TYPE_MISMATCH`
722+
723+
The default type being used by the client does not match the default type expected by the server.
724+
725+
This will typically only happen when using a different default type to the built-in `json0` used by ShareDB by default (eg if using a fork). The exact same type must be used by both the client and the server, and should be registered as the default type:
726+
727+
```javascript
728+
var ShareDB = require('sharedb');
729+
var forkedJson0 = require('forked-json0');
730+
731+
// Make sure to also do this on your client
732+
ShareDB.types.defaultType = forkedJson0.type;
733+
```
734+
735+
#### `ERR_OP_NOT_ALLOWED_IN_PROJECTION`
736+
737+
The submitted op is not valid when applied to the projection.
738+
739+
This may happen if the op targets some property that is not included in the projection.
740+
741+
#### `ERR_TYPE_CANNOT_BE_PROJECTED`
742+
743+
The document's type cannot be projected. `json0` is currently the only type that supports projections.

lib/client/doc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ Doc.prototype._setType = function(newType) {
143143
// If we removed the type from the object, also remove its data
144144
this.data = undefined;
145145
} else {
146-
var err = new ShareDBError(ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNISED, 'Missing type ' + newType);
146+
var err = new ShareDBError(ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNIZED, 'Missing type ' + newType);
147147
return this.emit('error', err);
148148
}
149149
};

lib/error.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ ShareDBError.CODES = {
1919
ERR_DOC_MISSING_VERSION: 'ERR_DOC_MISSING_VERSION',
2020
ERR_DOC_ALREADY_CREATED: 'ERR_DOC_ALREADY_CREATED',
2121
ERR_DOC_DOES_NOT_EXIST: 'ERR_DOC_DOES_NOT_EXIST',
22-
ERR_DOC_TYPE_NOT_RECOGNISED: 'ERR_DOC_TYPE_NOT_RECOGNISED',
22+
ERR_DOC_TYPE_NOT_RECOGNIZED: 'ERR_DOC_TYPE_NOT_RECOGNIZED',
2323
ERR_DOC_WAS_DELETED: 'ERR_DOC_WAS_DELETED',
2424
ERR_INFLIGHT_OP_MISSING: 'ERR_INFLIGHT_OP_MISSING',
2525
ERR_INGESTED_SNAPSHOT_HAS_NO_VERSION: 'ERR_INGESTED_SNAPSHOT_HAS_NO_VERSION',
2626
ERR_MAX_SUBMIT_RETRIES_EXCEEDED: 'ERR_MAX_SUBMIT_RETRIES_EXCEEDED',
2727
ERR_MESSAGE_BADLY_FORMED: 'ERR_MESSAGE_BADLY_FORMED',
28+
ERR_MILESTONE_ARGUMENT_INVALID: 'ERR_MILESTONE_ARGUMENT_INVALID',
2829
ERR_OP_ALREADY_SUBMITTED: 'ERR_OP_ALREADY_SUBMITTED',
2930
ERR_OP_NOT_ALLOWED_IN_PROJECTION: 'ERR_OP_NOT_ALLOWED_IN_PROJECTION',
3031
ERR_OP_SUBMIT_REJECTED: 'ERR_OP_SUBMIT_REJECTED',

lib/milestone-db/memory.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ MemoryMilestoneDB.prototype = Object.create(MilestoneDB.prototype);
2626

2727
MemoryMilestoneDB.prototype.getMilestoneSnapshot = function(collection, id, version, callback) {
2828
if (!this._isValidVersion(version)) {
29-
return process.nextTick(callback, new ShareDBError(ERROR_CODE.ERR_UNKNOWN_ERROR, 'Invalid version'));
29+
return process.nextTick(callback, new ShareDBError(ERROR_CODE.ERR_MILESTONE_ARGUMENT_INVALID, 'Invalid version'));
3030
}
3131

3232
var predicate = versionLessThanOrEqualTo(version);
@@ -39,8 +39,8 @@ MemoryMilestoneDB.prototype.saveMilestoneSnapshot = function(collection, snapsho
3939
this.emit('save', collection, snapshot);
4040
}.bind(this);
4141

42-
if (!collection) return callback(new ShareDBError(ERROR_CODE.ERR_UNKNOWN_ERROR, 'Missing collection'));
43-
if (!snapshot) return callback(new ShareDBError(ERROR_CODE.ERR_UNKNOWN_ERROR, 'Missing snapshot'));
42+
if (!collection) return callback(new ShareDBError(ERROR_CODE.ERR_MILESTONE_ARGUMENT_INVALID, 'Missing collection'));
43+
if (!snapshot) return callback(new ShareDBError(ERROR_CODE.ERR_MILESTONE_ARGUMENT_INVALID, 'Missing snapshot'));
4444

4545
var milestoneSnapshots = this._getMilestoneSnapshotsSync(collection, snapshot.id);
4646
milestoneSnapshots.push(snapshot);
@@ -53,7 +53,7 @@ MemoryMilestoneDB.prototype.saveMilestoneSnapshot = function(collection, snapsho
5353

5454
MemoryMilestoneDB.prototype.getMilestoneSnapshotAtOrBeforeTime = function(collection, id, timestamp, callback) {
5555
if (!this._isValidTimestamp(timestamp)) {
56-
return process.nextTick(callback, new ShareDBError(ERROR_CODE.ERR_UNKNOWN_ERROR, 'Invalid timestamp'));
56+
return process.nextTick(callback, new ShareDBError(ERROR_CODE.ERR_MILESTONE_ARGUMENT_INVALID, 'Invalid timestamp'));
5757
}
5858

5959
var filter = timestampLessThanOrEqualTo(timestamp);
@@ -62,7 +62,7 @@ MemoryMilestoneDB.prototype.getMilestoneSnapshotAtOrBeforeTime = function(collec
6262

6363
MemoryMilestoneDB.prototype.getMilestoneSnapshotAtOrAfterTime = function(collection, id, timestamp, callback) {
6464
if (!this._isValidTimestamp(timestamp)) {
65-
return process.nextTick(callback, new ShareDBError(ERROR_CODE.ERR_UNKNOWN_ERROR, 'Invalid timestamp'));
65+
return process.nextTick(callback, new ShareDBError(ERROR_CODE.ERR_MILESTONE_ARGUMENT_INVALID, 'Invalid timestamp'));
6666
}
6767

6868
var filter = timestampGreaterThanOrEqualTo(timestamp);
@@ -84,7 +84,7 @@ MemoryMilestoneDB.prototype._findMilestoneSnapshot = function(collection, id, br
8484
callback, new ShareDBError(ERROR_CODE.ERR_UNKNOWN_ERROR, 'Missing collection')
8585
);
8686
}
87-
if (!id) return process.nextTick(callback, new ShareDBError(ERROR_CODE.ERR_UNKNOWN_ERROR, 'Missing ID'));
87+
if (!id) return process.nextTick(callback, new ShareDBError(ERROR_CODE.ERR_MILESTONE_ARGUMENT_INVALID, 'Missing ID'));
8888

8989
var milestoneSnapshots = this._getMilestoneSnapshotsSync(collection, id);
9090

lib/ot.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ exports.checkOp = function(op) {
2424
}
2525
var type = types[typeName];
2626
if (type == null || typeof type !== 'object') {
27-
return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNISED, message: 'Unknown type'};
27+
return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNIZED, message: 'Unknown type'};
2828
}
2929
} else if (op.del != null) {
3030
if (op.del !== true) return {code: ERROR_CODE.ERR_OT_OP_BADLY_FORMED, message: 'del value must be true'};
@@ -72,7 +72,7 @@ exports.apply = function(snapshot, op) {
7272
// The document doesn't exist, although it might have once existed
7373
var create = op.create;
7474
var type = types[create.type];
75-
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNISED, message: 'Unknown type'};
75+
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNIZED, message: 'Unknown type'};
7676

7777
try {
7878
snapshot.data = type.create(create.data);
@@ -105,7 +105,7 @@ function applyOpEdit(snapshot, edit) {
105105

106106
if (edit == null) return {code: ERROR_CODE.ERR_OT_OP_NOT_PROVIDED, message: 'Missing op'};
107107
var type = types[snapshot.type];
108-
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNISED, message: 'Unknown type'};
108+
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNIZED, message: 'Unknown type'};
109109

110110
try {
111111
snapshot.data = type.apply(snapshot.data, edit);
@@ -138,7 +138,7 @@ exports.transform = function(type, op, appliedOp) {
138138

139139
if (typeof type === 'string') {
140140
type = types[type];
141-
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNISED, message: 'Unknown type'};
141+
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNIZED, message: 'Unknown type'};
142142
}
143143

144144
try {
@@ -163,7 +163,7 @@ exports.applyOps = function(snapshot, ops) {
163163

164164
if (snapshot.type) {
165165
type = types[snapshot.type];
166-
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNISED, message: 'Unknown type'};
166+
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNIZED, message: 'Unknown type'};
167167
}
168168

169169
for (var index = 0; index < ops.length; index++) {
@@ -173,7 +173,7 @@ exports.applyOps = function(snapshot, ops) {
173173

174174
if (op.create) {
175175
type = types[op.create.type];
176-
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNISED, message: 'Unknown type'};
176+
if (!type) return {code: ERROR_CODE.ERR_DOC_TYPE_NOT_RECOGNIZED, message: 'Unknown type'};
177177
snapshot.data = type.create(op.create.data);
178178
snapshot.type = type.uri;
179179
} else if (op.del) {

0 commit comments

Comments
 (0)