mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Return counts for collection update and remove commands
In order to support optimistic locking the counts from the MongoDB update and remove commands need to be returned to the application code so that the update/remove can be verified they took place and action taken if they did not (like throwing a 409 Error). For consistency make LocalCollection return counts also.
This commit is contained in:
@@ -498,6 +498,7 @@ LocalCollection.prototype.remove = function (selector) {
|
||||
LocalCollection._recomputeResults(query);
|
||||
});
|
||||
self._observeQueue.drain();
|
||||
return remove.length;
|
||||
};
|
||||
|
||||
// XXX atomicity: if multi is true, and one modification fails, do
|
||||
@@ -523,12 +524,15 @@ LocalCollection.prototype.update = function (selector, mod, options) {
|
||||
});
|
||||
var recomputeQids = {};
|
||||
|
||||
var updateCount = 0;
|
||||
|
||||
for (var id in self.docs) {
|
||||
var doc = self.docs[id];
|
||||
if (selector_f(doc)) {
|
||||
// XXX Should we save the original even if mod ends up being a no-op?
|
||||
self._saveOriginal(id, doc);
|
||||
self._modifyAndNotify(doc, mod, recomputeQids);
|
||||
++updateCount;
|
||||
if (!options.multi)
|
||||
break;
|
||||
}
|
||||
@@ -541,6 +545,7 @@ LocalCollection.prototype.update = function (selector, mod, options) {
|
||||
qidToOriginalResults[qid]);
|
||||
});
|
||||
self._observeQueue.drain();
|
||||
return updateCount;
|
||||
};
|
||||
|
||||
LocalCollection.prototype._modifyAndNotify = function (
|
||||
|
||||
@@ -66,7 +66,8 @@ var log_callbacks = function (operations) {
|
||||
// XXX test shared structure in all MM entrypoints
|
||||
Tinytest.add("minimongo - basics", function (test) {
|
||||
var c = new LocalCollection(),
|
||||
fluffyKitten_id;
|
||||
fluffyKitten_id,
|
||||
count;
|
||||
|
||||
fluffyKitten_id = c.insert({type: "kitten", name: "fluffy"});
|
||||
c.insert({type: "kitten", name: "snookums"});
|
||||
@@ -87,7 +88,8 @@ Tinytest.add("minimongo - basics", function (test) {
|
||||
test.length(c.find({type: "kitten"}).fetch(), 2);
|
||||
test.length(c.find({type: "cryptographer"}).fetch(), 2);
|
||||
|
||||
c.update({name: "snookums"}, {$set: {type: "cryptographer"}});
|
||||
count = c.update({name: "snookums"}, {$set: {type: "cryptographer"}});
|
||||
test.equal(count, 1);
|
||||
test.equal(c.find().count(), 4);
|
||||
test.equal(c.find({type: "kitten"}).count(), 1);
|
||||
test.equal(c.find({type: "cryptographer"}).count(), 3);
|
||||
@@ -102,10 +104,12 @@ Tinytest.add("minimongo - basics", function (test) {
|
||||
c.remove({_id: null});
|
||||
c.remove({_id: false});
|
||||
c.remove({_id: undefined});
|
||||
c.remove();
|
||||
count = c.remove();
|
||||
test.equal(count, 0);
|
||||
test.equal(c.find().count(), 4);
|
||||
|
||||
c.remove({});
|
||||
count = c.remove({});
|
||||
test.equal(count, 4);
|
||||
test.equal(c.find().count(), 0);
|
||||
|
||||
c.insert({_id: 1, name: "strawberry", tags: ["fruit", "red", "squishy"]});
|
||||
@@ -1647,7 +1651,8 @@ Tinytest.add("minimongo - diff", function (test) {
|
||||
|
||||
Tinytest.add("minimongo - saveOriginals", function (test) {
|
||||
// set up some data
|
||||
var c = new LocalCollection();
|
||||
var c = new LocalCollection(),
|
||||
count;
|
||||
c.insert({_id: 'foo', x: 'untouched'});
|
||||
c.insert({_id: 'bar', x: 'updateme'});
|
||||
c.insert({_id: 'baz', x: 'updateme'});
|
||||
@@ -1658,9 +1663,12 @@ Tinytest.add("minimongo - saveOriginals", function (test) {
|
||||
c.saveOriginals();
|
||||
c.insert({_id: "hooray", z: 'insertme'});
|
||||
c.remove({y: 'removeme'});
|
||||
c.update({x: 'updateme'}, {$set: {z: 5}}, {multi: true});
|
||||
count = c.update({x: 'updateme'}, {$set: {z: 5}}, {multi: true});
|
||||
c.update('bar', {$set: {k: 7}}); // update same doc twice
|
||||
|
||||
// Verify returned count is correct
|
||||
test.equal(count, 2);
|
||||
|
||||
// Verify the originals.
|
||||
var originals = c.retrieveOriginals();
|
||||
var affected = ['bar', 'baz', 'quux', 'whoa', 'hooray'];
|
||||
|
||||
@@ -357,7 +357,9 @@ _.each(["insert", "update", "remove"], function (name) {
|
||||
// it's my collection. descend into the collection object
|
||||
// and propagate any exception.
|
||||
try {
|
||||
self._collection[name].apply(self._collection, args);
|
||||
var result = self._collection[name].apply(self._collection, args);
|
||||
if (ret === undefined)
|
||||
ret = result;
|
||||
} catch (e) {
|
||||
if (callback) {
|
||||
callback(e);
|
||||
|
||||
@@ -228,9 +228,10 @@ _Mongo.prototype.remove = function (collection_name, selector) {
|
||||
var future = new Future;
|
||||
collection.remove(replaceTypes(selector, replaceMeteorAtomWithMongo),
|
||||
{safe: true}, future.resolver());
|
||||
future.wait();
|
||||
var result = future.wait();
|
||||
// XXX We don't have to run this on error, right?
|
||||
self._refresh(collection_name, selector);
|
||||
return result;
|
||||
} finally {
|
||||
write.committed();
|
||||
}
|
||||
@@ -266,8 +267,9 @@ _Mongo.prototype.update = function (collection_name, selector, mod, options) {
|
||||
collection.update(replaceTypes(selector, replaceMeteorAtomWithMongo),
|
||||
replaceTypes(mod, replaceMeteorAtomWithMongo),
|
||||
mongoOpts, future.resolver());
|
||||
future.wait();
|
||||
var result = future.wait();
|
||||
self._refresh(collection_name, selector);
|
||||
return result;
|
||||
} finally {
|
||||
write.committed();
|
||||
}
|
||||
|
||||
@@ -191,8 +191,14 @@ Tinytest.addAsync("mongo-livedata - basics, " + idGeneration, function (test, on
|
||||
test.equal(_.pluck(coll.find({run: run}, {sort: {x: -1}}).fetch(), "x"),
|
||||
[4, 1]);
|
||||
|
||||
expectObserve('', function () {
|
||||
var count = coll.update({run: run, x: -1}, {$inc: {x: 2}}, {multi: true});
|
||||
test.equal(count, 0);
|
||||
});
|
||||
|
||||
expectObserve('c(3,0,1)c(6,1,4)', function () {
|
||||
coll.update({run: run}, {$inc: {x: 2}}, {multi: true});
|
||||
var count = coll.update({run: run}, {$inc: {x: 2}}, {multi: true});
|
||||
test.equal(count, 2);
|
||||
test.equal(_.pluck(coll.find({run: run}, {sort: {x: -1}}).fetch(), "x"),
|
||||
[6, 3]);
|
||||
});
|
||||
@@ -205,7 +211,8 @@ Tinytest.addAsync("mongo-livedata - basics, " + idGeneration, function (test, on
|
||||
});
|
||||
|
||||
expectObserve('r(13,1)', function () {
|
||||
coll.remove({run: run, x: {$gt: 10}});
|
||||
var count = coll.remove({run: run, x: {$gt: 10}});
|
||||
test.equal(count, 1);
|
||||
test.equal(coll.find({run: run}).count(), 1);
|
||||
});
|
||||
|
||||
@@ -214,6 +221,12 @@ Tinytest.addAsync("mongo-livedata - basics, " + idGeneration, function (test, on
|
||||
test.equal(coll.find({run: run}).count(), 0);
|
||||
});
|
||||
|
||||
expectObserve('', function () {
|
||||
var count = coll.remove({run: run});
|
||||
test.equal(count, 0);
|
||||
test.equal(coll.find({run: run}).count(), 0);
|
||||
});
|
||||
|
||||
obs.stop();
|
||||
onComplete();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user