I'm having weird issue with IE9 when reloading an existing tab pointing to my nodeJS server http://localhost:8080/ :
mydb.usermodels.$userId_1 dup key: { : "d268745fbe9" }
Opening a new tab in IE9 and loading the same URL does not generates such error, and Firefox lets me reload the same tab with no error at all.
Basically, when the tab is load (or reload) the client generate a random user ID and send it to the server over a socket.io socket. The server then checks if userId is present in database and in case it is not, it creates a new entry.
It is not clear what can cause IE9 related error but I suspect :
Without hope I have tryed to set my documents with unique: false and set options {id: false} and {_id: false} to disable id getter added to the schema but as I expected it fails to resolve the problem.
What is your opinion on this ?
Please take a looks at the code :
var express = require('express')
, app = express()
, http = require('http')
, static = require('node-static')
, server = http.createServer(app)
, port = 8080;
app.use('/',express.static(__dirname+'/public'));
var mongoose = require('mongoose')
, Schema = mongoose.Schema
, ObjectId = Schema.ObjectId;
mongoose.connect('mongodb://localhost/mydb');
var userSchema = new Schema({
userId: {type: String, unique: true},
loc: {type: [Number], index: '2d'}
});
userModel = mongoose.model('userModel', userSchema);
/**
* configure session store & session.socket.io
**/
var connect = require('connect')
, cookieParser = express.cookieParser('your secret sauce')
, sessionStore = new connect.middleware.session.MemoryStore();
var io = require('socket.io').listen(server, { log: false });
var SessionSockets = require('session.socket.io')
, sessionSockets = new SessionSockets(io, sessionStore, cookieParser, 'vfre54v5rfv54v5s94v');
sessionSockets.on('connection', function (err, socket, session) {
/**
* get data from the user
**/
socket.on('send2db', function(data) {
userModel.findOne({ userId : data.id }, function (err, user) { //search the user in database
if (err){ throw err;
} else if ( user == null ){
var instance = new userModel( { userId: data.id, loc: [data.lat, data.lng] } );
instance.save(function (err) {
if (err) { throw err; }
userModel.findOne( { userId: data.id }, function (err, user) {
if (err) { throw err; }
else console.log('');
console.log('user',user.userId,'create with location ', user.loc);
});
});
}
/***
* update user position when it changes
***/
else if (user.loc[0] != data.lat && user.loc[1] != data.lng ){
userModel.update( { userId: data.id}, { loc : [data.lat,data.lng] }, function (err) {
if (err) { console.log('There is an error', err); }
userModel.findOne( { userId: data.id }, function (err, userfind) {
if (err) { throw err; }
console.log('user', user.userId,'has update his position',userfind.loc);
});
});
} else if (user.loc == [data.lat,data.lng]){ // check if position is same
console.log('user', data.id, 'has the same position ! WTF Im doing here ???');
}
});
/***
* find users around
***/
//findUser();
function findUser () {
userModel.find( { loc : { $near : [data.lat,data.lng], $maxDistance: 100/111.12 } } , function(err, users){
if (err) {
console.log("error in finding near", err);
throw err;
}
console.log('users.length : ' , users.length);
for (var i = 0, l = users.length; i < l; i++) {
user = users[i];
console.log('Pseudo ' + user.userId, 'has position ' + user.loc);
}
console.log('');
});
};
});
As I can see with the console.log(); I have in my code is that failure does not occurs always at the same moment, and piece of code that are executed during one test is not the test after. The failure happens after or while execution of instance.save(function (err) {.
Most of the time userModel.findOne that follow is executed and console.log('user',user.userId,'create with location', user.loc, 'and namespace', user.namespace); retruns the correct value.
It can happens that console.log('user',user.userId,'create with location', user.loc, 'and namespace', user.namespace); is not executed at all, neither function(err, users){.
It can happens too that function findUser () { that is after the IF ELSE IF is executed BEFORE the end of it. What I mean here is that first I see findUser function that returns some correct value then I see the console.log(...); output, and it crashs.
Console output also indicates that error occurs with the following system files at these lines.
utils.js, line 437 : trow err;
/**
* process.nextTick helper.
*
* Wraps `callback` in a try/catch + nextTick.
*
* node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.
*
* @param {Function} callback
* @api private
*/
exports.tick = function tick (callback) {
if ('function' !== typeof callback) return;
return function () {
try {
callback.apply(this, arguments);
} catch (err) {
// only nextTick on err to get out of
// the event loop and avoid state corruption.
process.nextTick(function () {
throw err;
});
}
}
}
db.js, line 1931 : var e = new Error(msg);
/**
* Wrap a Mongo error document into an Error instance
* @ignore
* @api private
*/
Db.prototype.wrap = function(error) {
var msg = error.err || error.errmsg || error;
var e = new Error(msg);
e.name = 'MongoError';
// Get all object keys
var keys = typeof error == 'object' ? Object.keys(error) : [];
// Populate error object with properties
for(var i = 0; i < keys.length; i++) {
e[keys[i]] = error[keys[i]];
}
return e;
}
collection.js, line 323 : callback(self.db.wrap(error[0]));
// Execute command with safe options (rolls up both command and safe command into one and executes them on the same connection)
self.db._executeInsertCommand(insertCommand, commandOptions, function (err, error) {
error = error && error.documents;
if(!callback) return;
if (err) {
callback(err);
} else if(error[0].err || error[0].errmsg) {
callback(self.db.wrap(error[0]));
} else {
callback(null, docs);
}