Created
April 14, 2012 19:52
-
-
Save boutell/2387479 to your computer and use it in GitHub Desktop.
New Mongoose retry-when-save-fails test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Create a situation where a unique index error will occur. Try to save the | |
* object again after making the relevant field unique. Then do an update on one of the objects. | |
* | |
* Expected behavior: each object after the first saves successfully the second (or third...) time and we wind | |
* up with ten objects. Actual behavior with current Mongoose: we wind up with one object because the | |
* isNew flag is never reset to true when an insert fails. Behavior with my pull request: the isNew flag | |
* is reset if an insert (not an update) fails, allowing save handlers to try again on error after doing things | |
* like making slugs more unique. | |
* | |
* [email protected] 2012-04-14 | |
*/ | |
var mongoose = require('mongoose'); | |
var db = mongoose.connect('mongodb://localhost/mongooseRetrySaveTest'); | |
var Schema = mongoose.Schema; | |
var mediaItemSchema = new Schema({ | |
slug: { type: String, unique: true } | |
}); | |
// Don't do anything until the ensureIndex() calls on the model are really complete. | |
// Otherwise we get unique index errors *after* all the inserts succeed | |
// According to the node docs and irc discussion node is truly single-threaded and there is | |
// no risk those ensureIndex calls will complete before my on() handler gets attached. I did | |
// some digging in the drivers and looks like that is... probably... true (: but I would be happier | |
// if the model function had an on-complete callback | |
var MediaItem = mongoose.model('MediaItem', mediaItemSchema); | |
MediaItem.on('index', function() | |
{ | |
console.log('got the index event from MediaItem'); | |
cleanup(); | |
}); | |
function cleanup() | |
{ | |
MediaItem.remove({}, function (err) { | |
if (err) | |
{ | |
throw err; | |
} | |
console.log("Successfully cleaned up any previous test"); | |
insert(); | |
}); | |
} | |
function insert() | |
{ | |
for (i = 0; (i < 10); i++) | |
{ | |
insertOne(); | |
} | |
} | |
function insertOne() | |
{ | |
var mediaItem = new MediaItem(); | |
mediaItem.slug = "common-slug"; | |
attemptSave(mediaItem); | |
} | |
function attemptSave(mediaItem) | |
{ | |
mediaItem.save(afterSaveAttempt); | |
function afterSaveAttempt(err, savedItem) | |
{ | |
console.log("in afterSaveAttempt"); | |
if (err) | |
{ | |
console.log("there is an error"); | |
if ((err.code === 11000) && (err.err.indexOf('slug') !== -1)) | |
{ | |
console.log("Retrying with a more unique slug"); | |
mediaItem.slug += (Math.floor(Math.random() * 10)).toString(); | |
setTimeout(function() { | |
console.log('calling save from a timeout function'); | |
mediaItem.save(afterSaveAttempt); | |
}, 0); | |
return; | |
} | |
else | |
{ | |
console.log("Throwing error"); | |
throw err; | |
} | |
} | |
console.log(savedItem); | |
// No error - count it as a success | |
afterSaveSuccess(); | |
} | |
} | |
var saved = 0; | |
function afterSaveSuccess() | |
{ | |
console.log("Counting success"); | |
saved++; | |
if (saved === 10) | |
{ | |
find(); | |
} | |
} | |
// We should have 100 items now, how many do we really have? | |
function find() | |
{ | |
MediaItem.find({}, function(err, docs) { | |
console.log("We have " + docs.length + " objects, we expected 10"); | |
}); | |
update(); | |
} | |
// Find the first object and demonstrate that my changes | |
// didn't break update() in mongoose | |
function update() | |
{ | |
MediaItem.findOne({slug: 'common-slug'}, function(err, original) | |
{ | |
if (err) | |
{ | |
throw err; | |
} | |
original.slug = 'totally-different-slug'; | |
original.save(verifyUpdate); | |
}); | |
} | |
function verifyUpdate(err, original) | |
{ | |
if (err) | |
{ | |
throw err; | |
} | |
console.log('update allegedly worked'); | |
MediaItem.findOne({slug: 'totally-different-slug'}, function(err, original) | |
{ | |
if (err) | |
{ | |
throw err; | |
} | |
console.log('Update REALLY worked'); | |
console.log('Flawless victory!'); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment