diff --git a/lib/db.js b/lib/db.js index 36462e1..1b5c4e8 100644 --- a/lib/db.js +++ b/lib/db.js @@ -76,11 +76,16 @@ Db.prototype.open = function (fn) { self.connecting = true; self._mdb = mdb; + debug('opening %s:%s', this.options.host, this.options.port); mdb.open(function (err) { self.connecting = false; - if(err) return fn && fn(err); + if(err) { + debug('open error:', err); + return fn && fn(err); + } + debug('opened connection'); self.emit('connected'); - }) + }); } /** @@ -141,6 +146,7 @@ function collection(store, fn) { } if(db.connecting) { + debug('waiting for db connection'); db.once('connected', execute); } else { execute(); diff --git a/lib/session.js b/lib/session.js index 8aa4743..4481fe9 100644 --- a/lib/session.js +++ b/lib/session.js @@ -1,255 +1,255 @@ var Store = require('./db').Store - , util = require('util') - , uuid = require('./util/uuid') - , Cookies = require('cookies') - , EventEmitter = require('events').EventEmitter - , debug = require('debug')('session'); +, util = require('util') +, uuid = require('./util/uuid') +, Cookies = require('cookies') +, EventEmitter = require('events').EventEmitter +, debug = require('debug')('session'); /*! - * A simple index for storing sesssions in memory. - */ +* A simple index for storing sesssions in memory. +*/ var sessionIndex = {} - , userSessionIndex = {}; + , userSessionIndex = {}; /** - * A store for persisting sessions inbetween connection / disconnection. - * Automatically creates session IDs on inserted objects. - */ +* A store for persisting sessions inbetween connection / disconnection. +* Automatically creates session IDs on inserted objects. +*/ function SessionStore(namespace, db, sockets) { - this.sockets = sockets; + this.sockets = sockets; - // socket queue - var socketQueue = this.socketQueue = new EventEmitter() - , socketIndex = this.socketIndex = {}; + // socket queue + var socketQueue = this.socketQueue = new EventEmitter() + , socketIndex = this.socketIndex = {}; - // TODO - sockets.on('connection', ...) - map to a session id based on socket.handshake.headers - sockets && sockets.on('connection', function (socket) { - // NOTE: do not use set here ever, the `Cookies` api is meant to get a req, res - // but we are just using it for a cookie parser - var cookies = new Cookies(socket.handshake) - , sid = cookies.get('sid'); + // TODO - sockets.on('connection', ...) - map to a session id based on socket.handshake.headers + sockets && sockets.on('connection', function (socket) { + // NOTE: do not use set here ever, the `Cookies` api is meant to get a req, res + // but we are just using it for a cookie parser + var cookies = new Cookies(socket.handshake) + , sid = cookies.get('sid'); - if(sid) { - // index sockets against their session id - socketIndex[sid] = socket; - socketQueue.emit(sid, socket); - } - }) + if(sid) { + // index sockets against their session id + socketIndex[sid] = socket; + socketQueue.emit(sid, socket); + } + }) - Store.apply(this, arguments); + Store.apply(this, arguments); } util.inherits(SessionStore, Store); exports.SessionStore = SessionStore; SessionStore.prototype.createUniqueIdentifier = function() { - return uuid.create(128); + return uuid.create(128); }; /** - * Create a new `Session` based on an optional `sid` (session id). - * - * @param {String} sid - * @param {Function} callback(err, session) - */ +* Create a new `Session` based on an optional `sid` (session id). +* +* @param {String} sid +* @param {Function} callback(err, session) +*/ SessionStore.prototype.createSession = function(sid, fn) { - var socketIndex = this.socketIndex - , store = this; + var socketIndex = this.socketIndex + , store = this; - if(typeof sid == 'function') { - fn = sid; - sid = undefined; - } - if(sid) { - this.find({id: sid}, function(err, s) { - if(err) return fn(err); - if(!s) { - store.insert({id: sid}, function(err, s) { - if(err) console.error(err); - }); - } - var sess = sessionIndex[sid] || new Session(s, store, socketIndex, store.sockets); - sessionIndex[sid] = sess; - // index sessions by user - if(s && s.uid) { - userSessionIndex[s.uid] = sess; - } - fn(err, sess); - }); - } else { - sid = this.createUniqueIdentifier(); - var sess = sessionIndex[sid] = new Session({id: sid}, this, socketIndex, store.sockets); - fn(null, sess); - this.insert({id: sid}, function(err, s) { - if(err) console.error(err); - }); - } + if(typeof sid == 'function') { + fn = sid; + sid = undefined; + } + if(sid) { + this.find({id: sid}, function(err, s) { + if(err) return fn(err); + if(!s) { + store.insert({id: sid}, function(err, s) { + if(err) console.error(err); + }); + } + var sess = sessionIndex[sid] || new Session(s, store, socketIndex, store.sockets); + sessionIndex[sid] = sess; + // index sessions by user + if(s && s.uid) { + userSessionIndex[s.uid] = sess; + } + fn(err, sess); + }); + } else { + sid = this.createUniqueIdentifier(); + var sess = sessionIndex[sid] = new Session({id: sid}, this, socketIndex, store.sockets); + fn(null, sess); + this.insert({id: sid}, function(err, s) { + if(err) console.error(err); + }); + } }; /** - * An in memory representation of a client or user connection that can be saved to disk. - * Data will be passed around via a `Context` to resources. - * - * Example: - * - * var session = new Session({id: 'my-sid', new SessionStore('sessions', db)}); - * - * session.set({uid: 'my-uid'}).save(); - * - * @param {Object} data - * @param {Store} store - * @param {Socket} socket - */ +* An in memory representation of a client or user connection that can be saved to disk. +* Data will be passed around via a `Context` to resources. +* +* Example: +* +* var session = new Session({id: 'my-sid', new SessionStore('sessions', db)}); +* +* session.set({uid: 'my-uid'}).save(); +* +* @param {Object} data +* @param {Store} store +* @param {Socket} socket +*/ function Session(data, store, sockets, rawSockets) { - this.data = data; - if(data && data.id) this.sid = data.id; - this.store = store; + this.data = data; + if(data && data.id) this.sid = data.id; + this.store = store; - // create faux socket, to queue any events until - // a real socket is available - var socketWrapper = this.socket = { - on: function () { - // if we have a real socket, use it - if(this._socket) { - this._socket.apply(this._socket, arguments); - } else { - // otherwise add to bind queue - var queue = this._bindQueue = this._bindQueue || []; - queue.push(arguments); - } - }, - emit: function () { - // if we have a real socket, use it - if(this._socket) { - this._socket.emit.apply(this._socket, arguments); - } else { - // otherwise add to bind queue - var queue = this._emitQueue = this._bindQueue || []; - queue.push(arguments); - } - }, - _socket: sockets[this.sid] - } + // create faux socket, to queue any events until + // a real socket is available + var socketWrapper = this.socket = { + on: function () { + // if we have a real socket, use it + if(this._socket) { + this._socket.apply(this._socket, arguments); + } else { + // otherwise add to bind queue + var queue = this._bindQueue = this._bindQueue || []; + queue.push(arguments); + } + }, + emit: function () { + // if we have a real socket, use it + if(this._socket) { + this._socket.emit.apply(this._socket, arguments); + } else { + // otherwise add to bind queue + var queue = this._emitQueue = this._bindQueue || []; + queue.push(arguments); + } + }, + _socket: sockets[this.sid] + } - this.emitToUsers = function(collection, query, event, data) { - collection.get(query, function(users) { - var userSession; - // TODO: arguments in weird order - if(users && users.id) { - userSession = userSessionIndex[err.id]; - console.info(userSession); - if(userSession && userSession.socket) { - userSession.socket.emit(event, data); - } - return; - } - users.forEach(function(u) { - userSession = userSessionIndex[u.id]; + this.emitToUsers = function(collection, query, event, data) { + collection.get(query, function(users) { + var userSession; + // TODO: arguments in weird order + if(users && users.id) { + userSession = userSessionIndex[err.id]; + console.info(userSession); + if(userSession && userSession.socket) { + userSession.socket.emit(event, data); + } + return; + } + users.forEach(function(u) { + userSession = userSessionIndex[u.id]; - // emit to sessions online - if(userSession && userSession.socket) { - userSession.socket.emit(event, data); - } - }); - }) - } + // emit to sessions online + if(userSession && userSession.socket) { + userSession.socket.emit(event, data); + } + }); + }) + } - this.emitToAll = function() { - rawSockets.emit.apply(rawSockets, arguments); - } + this.emitToAll = function() { + rawSockets.emit.apply(rawSockets, arguments); + } - // resolve queue once a socket is ready - store.socketQueue.once(this.sid, function (socket) { - socketWrapper._socket = socket; - // drain bind queue - if(socketWrapper._bindQueue && socketWrapper._bindQueue.length) { - socketWrapper._bindQueue.forEach(function (args) { - socket.on.apply(socket, args); - }) - } - // drain emit queue - if(socketWrapper._emitQueue && socketWrapper._emitQueue.length) { - socketWrapper._emitQueue.forEach(function (args) { - socket.emit.apply(socket, args); - }) - } - }) + // resolve queue once a socket is ready + store.socketQueue.once(this.sid, function (socket) { + socketWrapper._socket = socket; + // drain bind queue + if(socketWrapper._bindQueue && socketWrapper._bindQueue.length) { + socketWrapper._bindQueue.forEach(function (args) { + socket.on.apply(socket, args); + }) + } + // drain emit queue + if(socketWrapper._emitQueue && socketWrapper._emitQueue.length) { + socketWrapper._emitQueue.forEach(function (args) { + socket.emit.apply(socket, args); + }) + } + }) } /** - * Set properties on the in memory representation of a session. - * - * @param {Object} changes - * @return {Session} this for chaining - */ +* Set properties on the in memory representation of a session. +* +* @param {Object} changes +* @return {Session} this for chaining +*/ Session.prototype.set = function(object) { - var session = this - , data = session.data || (session.data = {}); + var session = this + , data = session.data || (session.data = {}); - Object.keys(object).forEach(function(key) { - data[key] = object[key]; - }); - return this; + Object.keys(object).forEach(function(key) { + data[key] = object[key]; + }); + return this; }; /** - * Save the in memory representation of a session to its store. - * - * @param {Function} callback(err, data) - * @return {Session} this for chaining - */ +* Save the in memory representation of a session to its store. +* +* @param {Function} callback(err, data) +* @return {Session} this for chaining +*/ Session.prototype.save = function(fn) { - var session = this - , data = this.data - , query = {id: data.id}; + var session = this + , data = this.data + , query = {id: data.id}; - session.remove(function (err) { - if(err) return fn(err); - session.store.insert(data, function (err, res) { - fn(err, res); - }); - }); - return this; + session.remove(function (err) { + if(err) return fn(err); + session.store.insert(data, function (err, res) { + fn(err, res); + }); + }); + return this; }; /** - * Reset the session using the data in its store. - * - * @param {Function} callback(err, data) - * @return {Session} this for chaining - */ +* Reset the session using the data in its store. +* +* @param {Function} callback(err, data) +* @return {Session} this for chaining +*/ Session.prototype.fetch = function(fn) { - var session = this; - this.store.first({id: this.data.id}, function (err, data) { - session.set(data); - fn(err, data); - }); - return this; + var session = this; + this.store.first({id: this.data.id}, function (err, data) { + session.set(data); + fn(err, data); + }); + return this; }; /** - * Remove the session. - * - * @param {Function} callback(err, data) - * @return {Session} this for chaining - */ +* Remove the session. +* +* @param {Function} callback(err, data) +* @return {Session} this for chaining +*/ Session.prototype.remove = function(fn) { - var session = this; - debug('Removing %s', this.data.id); + var session = this; + debug('Removing %s', this.data.id); - delete sessionIndex[this.data.id]; - delete userSessionIndex[this.data.uid]; // TODO: Don't delete all of a user's sessions - delete session.store.socketIndex[this.data.id]; + delete sessionIndex[this.data.id]; + delete userSessionIndex[this.data.uid]; // TODO: Don't delete all of a user's sessions + delete session.store.socketIndex[this.data.id]; - this.store.remove({id: this.data.id}, fn); + this.store.remove({id: this.data.id}, fn); - return this; + return this; }; \ No newline at end of file