finish optimistic retry code detect collision

This commit is contained in:
David Greenspan
2013-09-27 17:53:06 -07:00
parent 6494ec563f
commit 3e87c8f9d5
2 changed files with 39 additions and 3 deletions

View File

@@ -373,6 +373,13 @@ var numberAffectedCallback = function (callback) {
var NUM_OPTIMISTIC_TRIES = 3;
// exposed for testing
MongoConnection._isCannotChangeIdError = function (err) {
// either of these checks should work, but just to be safe...
return (err.code === 13596 ||
err.err.indexOf("cannot change _id of a document") === 0);
};
var simulateUpsertWithInsertedId = function (collection, selector, mod,
isModify, options, callback) {
var insertedId = options.insertedId; // must exist
@@ -445,11 +452,14 @@ var simulateUpsertWithInsertedId = function (collection, selector, mod,
collection.update(selector, replacementWithId, mongoOptsForInsert,
numberAffectedCallback(function (err, result) {
if (err) {
// XXX figure out if this is a
// figure out if this is a
// "cannot change _id of document" error, and
// if so, try doUpdate() again, up to 3 times.
Meteor._debug(err);
callback(err);
if (MongoConnection._isCannotChangeIdError(err)) {
doUpdate();
} else {
callback(err);
}
} else {
callback(null, _.extend(result, { insertedId: insertedId }));
}

View File

@@ -913,6 +913,32 @@ if (Meteor.isServer) {
onComplete();
});
Tinytest.addAsync("mongo-livedata - upsert error parse, " + idGeneration, function (test, onComplete) {
var run = test.runId();
var coll = new Meteor.Collection("livedata_upsert_errorparse_collection_"+run, collectionOptions);
coll.insert({_id: 'foobar'});
var err;
try {
coll.update({_id: 'foobar'}, {_id: 'cowbar'});
} catch (e) {
err = e;
}
test.isTrue(err);
test.isTrue(MongoInternals.Connection._isCannotChangeIdError(err));
try {
coll.insert({_id: 'foobar'});
} catch (e) {
err = e;
}
test.isTrue(err);
// duplicate id error is not same as change id error
test.isFalse(MongoInternals.Connection._isCannotChangeIdError(err));
onComplete();
});
} // end Meteor.isServer
_.each(Meteor.isServer ? [true, false] : [true], function (minimongo) {