Can revert updates, simple or batch

pull/2/head
Louis Chatriot 12 years ago
parent 9feeb26c4f
commit 39050a45d4
  1. 34
      lib/datastore.js
  2. 17
      lib/indexes.js
  3. 57
      test/indexes.test.js

@ -84,8 +84,7 @@ Datastore.prototype.ensureIndex = function (options, cb) {
* Add one or several document(s) to all indexes
*/
Datastore.prototype.addToIndexes = function (doc) {
var self = this
, i, failingIndex, error
var i, failingIndex, error
, keys = Object.keys(this.indexes)
;
@ -123,15 +122,32 @@ Datastore.prototype.removeFromIndexes = function (doc) {
/**
* Update a document in all indexes
* TODO: enable rollback if an update fails
* Update one or several documents in all indexes
* If one update violates a constraint, all changes are rolled back
*/
Datastore.prototype.updateIndexes = function (doc, newDoc) {
var self = this;
Datastore.prototype.updateIndexes = function (oldDoc, newDoc) {
var i, failingIndex, error
, keys = Object.keys(this.indexes)
;
Object.keys(this.indexes).forEach(function (i) {
self.indexes[i].update(doc, newDoc);
});
for (i = 0; i < keys.length; i += 1) {
try {
this.indexes[keys[i]].update(oldDoc, newDoc);
} catch (e) {
failingIndex = i;
error = e;
break;
}
}
// If an error happened, we need to rollback the insert on all other indexes
if (error) {
for (i = 0; i < failingIndex; i += 1) {
this.indexes[keys[i]].remove(doc);
}
throw error;
}
};

@ -131,6 +131,23 @@ Index.prototype.update = function (oldDoc, newDoc) {
};
/**
* Revert an update
*/
Index.prototype.revertUpdate = function (oldDoc, newDoc) {
var revert = [];
if (!util.isArray(oldDoc)) {
this.update(newDoc, oldDoc);
} else {
oldDoc.forEach(function (pair) {
revert.push({ oldDoc: pair.newDoc, newDoc: pair.oldDoc });
});
this.update(revert);
}
};
/**
* Update multiple documents in the index
* If a constraint is violated, the changes need to be rolled back

@ -330,6 +330,63 @@ describe('Indexes', function () {
assert.deepEqual(idx.tree.search('world'), [noChange]);
});
it('Can revert normal and batch updates', function () {
var idx = new Index({ fieldName: 'tf' })
, doc1 = { a: 5, tf: 'hello' }
, doc2 = { a: 8, tf: 'world' }
, doc3 = { a: 2, tf: 'bloup' }
, doc1b = { a: 23, tf: 'world' }
, doc2b = { a: 1, tf: 'changed' }
, doc3b = { a: 44, tf: 'bloup' }
, batchUpdate = [{ oldDoc: doc1, newDoc: doc1b }, { oldDoc: doc2, newDoc: doc2b }, { oldDoc: doc3, newDoc: doc3b }]
;
idx.insert(doc1);
idx.insert(doc2);
idx.insert(doc3);
idx.tree.getNumberOfKeys().should.equal(3);
idx.update(batchUpdate);
idx.tree.getNumberOfKeys().should.equal(3);
idx.getMatching('world').length.should.equal(1);
idx.getMatching('world')[0].should.equal(doc1b);
idx.getMatching('changed').length.should.equal(1);
idx.getMatching('changed')[0].should.equal(doc2b);
idx.getMatching('bloup').length.should.equal(1);
idx.getMatching('bloup')[0].should.equal(doc3b);
idx.revertUpdate(batchUpdate);
idx.tree.getNumberOfKeys().should.equal(3);
idx.getMatching('hello').length.should.equal(1);
idx.getMatching('hello')[0].should.equal(doc1);
idx.getMatching('world').length.should.equal(1);
idx.getMatching('world')[0].should.equal(doc2);
idx.getMatching('bloup').length.should.equal(1);
idx.getMatching('bloup')[0].should.equal(doc3);
// Now a simple update
idx.update(doc2, doc2b);
idx.tree.getNumberOfKeys().should.equal(3);
idx.getMatching('hello').length.should.equal(1);
idx.getMatching('hello')[0].should.equal(doc1);
idx.getMatching('changed').length.should.equal(1);
idx.getMatching('changed')[0].should.equal(doc2b);
idx.getMatching('bloup').length.should.equal(1);
idx.getMatching('bloup')[0].should.equal(doc3);
idx.revertUpdate(doc2, doc2b);
idx.tree.getNumberOfKeys().should.equal(3);
idx.getMatching('hello').length.should.equal(1);
idx.getMatching('hello')[0].should.equal(doc1);
idx.getMatching('world').length.should.equal(1);
idx.getMatching('world')[0].should.equal(doc2);
idx.getMatching('bloup').length.should.equal(1);
idx.getMatching('bloup')[0].should.equal(doc3);
});
}); // ==== End of 'Update' ==== //

Loading…
Cancel
Save