sharedb 5.1.1 → 5.2.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/lib/client/doc.js CHANGED
@@ -61,6 +61,7 @@ function Doc(connection, collection, id) {
61
61
  this.id = id;
62
62
 
63
63
  this.version = null;
64
+ // The OT type of this document. An uncreated document has type `null`
64
65
  this.type = null;
65
66
  this.data = undefined;
66
67
 
@@ -70,6 +71,8 @@ function Doc(connection, collection, id) {
70
71
  this.pendingFetch = [];
71
72
  this.pendingSubscribe = [];
72
73
 
74
+ this._isInHardRollback = false;
75
+
73
76
  // Whether we think we are subscribed on the server. Synchronously set to
74
77
  // false on calls to unsubscribe and disconnect. Should never be true when
75
78
  // this.wantSubscribe is false
@@ -93,9 +96,6 @@ function Doc(connection, collection, id) {
93
96
  // This is a list of {[create:{...}], [del:true], [op:...], callbacks:[...]}
94
97
  this.pendingOps = [];
95
98
 
96
- // The OT type of this document. An uncreated document has type `null`
97
- this.type = null;
98
-
99
99
  // The applyStack enables us to track any ops submitted while we are
100
100
  // applying an op incrementally. This value is an array when we are
101
101
  // performing an incremental apply and null otherwise. When it is an array,
@@ -748,10 +748,18 @@ Doc.prototype._submit = function(op, source, callback) {
748
748
  // The op contains either op, create, delete, or none of the above (a no-op).
749
749
  if ('op' in op) {
750
750
  if (!this.type) {
751
- var err = new ShareDBError(
752
- ERROR_CODE.ERR_DOC_DOES_NOT_EXIST,
753
- 'Cannot submit op. Document has not been created. ' + this.collection + '.' + this.id
754
- );
751
+ if (this._isInHardRollback) {
752
+ var err = new ShareDBError(
753
+ ERROR_CODE.ERR_DOC_IN_HARD_ROLLBACK,
754
+ 'Cannot submit op. Document is performing hard rollback. ' + this.collection + '.' + this.id
755
+ );
756
+ } else {
757
+ var err = new ShareDBError(
758
+ ERROR_CODE.ERR_DOC_DOES_NOT_EXIST,
759
+ 'Cannot submit op. Document has not been created. ' + this.collection + '.' + this.id
760
+ );
761
+ }
762
+
755
763
  if (callback) return callback(err);
756
764
  return this.emit('error', err);
757
765
  }
@@ -1030,6 +1038,7 @@ Doc.prototype._rollback = function(err) {
1030
1038
  };
1031
1039
 
1032
1040
  Doc.prototype._hardRollback = function(err) {
1041
+ this._isInHardRollback = true;
1033
1042
  // Store pending ops so that we can notify their callbacks of the error.
1034
1043
  // We combine the inflight op and the pending ops, because it's possible
1035
1044
  // to hit a condition where we have no inflight op, but we do have pending
@@ -1047,6 +1056,8 @@ Doc.prototype._hardRollback = function(err) {
1047
1056
  // Fetch the latest version from the server to get us back into a working state
1048
1057
  var doc = this;
1049
1058
  this._fetch({force: true}, function(fetchError) {
1059
+ doc._isInHardRollback = false;
1060
+
1050
1061
  // We want to check that no errors are swallowed, so we check that:
1051
1062
  // - there are callbacks to call, and
1052
1063
  // - that every single pending op called a callback
package/lib/error.js CHANGED
@@ -30,6 +30,7 @@ ShareDBError.CODES = {
30
30
  ERR_DOC_DOES_NOT_EXIST: 'ERR_DOC_DOES_NOT_EXIST',
31
31
  ERR_DOC_TYPE_NOT_RECOGNIZED: 'ERR_DOC_TYPE_NOT_RECOGNIZED',
32
32
  ERR_DOC_WAS_DELETED: 'ERR_DOC_WAS_DELETED',
33
+ ERR_DOC_IN_HARD_ROLLBACK: 'ERR_DOC_IN_HARD_ROLLBACK',
33
34
  ERR_INFLIGHT_OP_MISSING: 'ERR_INFLIGHT_OP_MISSING',
34
35
  ERR_INGESTED_SNAPSHOT_HAS_NO_VERSION: 'ERR_INGESTED_SNAPSHOT_HAS_NO_VERSION',
35
36
  ERR_MAX_SUBMIT_RETRIES_EXCEEDED: 'ERR_MAX_SUBMIT_RETRIES_EXCEEDED',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sharedb",
3
- "version": "5.1.1",
3
+ "version": "5.2.0",
4
4
  "description": "JSON OT database backend",
5
5
  "main": "lib/index.js",
6
6
  "dependencies": {
@@ -636,6 +636,25 @@ describe('Doc', function() {
636
636
  }
637
637
  ], done);
638
638
  });
639
+
640
+ it('rejects ops with ERR_DOC_IN_HARD_ROLLBACK error when in hard rollback', function(done) {
641
+ var backend = this.backend;
642
+ var doc = backend.connect().get('dogs', 'snoopy');
643
+
644
+ async.series([
645
+ doc.create.bind(doc, {color: 'red'}),
646
+ function(next) {
647
+ doc.on('error', function(error) {
648
+ expect(error.code).to.be.equal('TEST_ERROR');
649
+ });
650
+ doc._hardRollback(new ShareDBError('TEST_ERROR'));
651
+ doc.submitOp({p: ['color'], oi: 'blue', od: 'red'}, function(error) {
652
+ expect(error.code).to.be.equal('ERR_DOC_IN_HARD_ROLLBACK');
653
+ next();
654
+ });
655
+ }
656
+ ], done);
657
+ });
639
658
  });
640
659
 
641
660
  describe('errors on ops that could cause prototype corruption', function() {