ohm
Version:
Node.js Session Manager
112 lines (96 loc) • 3.6 kB
JavaScript
;
(function () {
'use strict';
var _ = require('lodash');
var SESSION_DATA_FIELDS = ['cookie', 'sessionID', 'viewerContextID'];
var session = require('express-session');
var MemoryStore = session.MemoryStore;
var RedisStore = require('connect-redis')(session);
var emptyFunction = include('models/emptyFunction.js');
var production = process.env.NODE_ENV === 'production';
var redis = require('redis');
/**
* Implementation of session data memory store.
*
* The npm package connect (and hence express.js) relies on the concept of
* a MomeryStore in order to make sessionData a persistent object
* stored on the server. However, because this is in RAM, any reboot of the server
* causes all this information to be lost. Hence we instead will implement
* a DB backed store to fetch and store session data.
*
* See https://github.com/senchalabs/connect/blob/master/lib/middleware/session/memory.js
* for an example implementation of what connect expected from the session API.
*
* You MUST implement:
* - get: function (sessionID, callback)
* - set: function (sessionID, sessionData, callback)
* - destroy: function (sessionID, callback)
* @module SessionDataStore
*/
function SessionDataStore(config) {
this.config = config;
if (!production) {
this.cache = new MemoryStore({
reapInterval: 60000 * 10
});
} else {
this.cache = new RedisStore({
client: redis.createClient(config.REDIS_PORT, config.REDIS_HOST)
});
}
}
_.extend(SessionDataStore.prototype, RedisStore.prototype, {
renameIDToSessionID: function renameIDToSessionID(sessionDataJSON) {
var copy = _.omit(sessionDataJSON, 'id');
if (sessionDataJSON.id) {
copy.sessionID = sessionDataJSON.id;
}
return copy;
},
areEqual: function areEqual(sessionDataJSON1, sessionDataJSON2) {
return _.isEqual(_.pick(this.renameIDToSessionID(sessionDataJSON1), SESSION_DATA_FIELDS), _.pick(this.renameIDToSessionID(sessionDataJSON2), SESSION_DATA_FIELDS));
},
_getFromCache: function _getFromCache(sessionID, callback) {
this.cache.get(sessionID, callback);
},
dirtyCache: function dirtyCache(sessionID, callback) {
this.cache.destroy(sessionID, callback);
},
_updateCache: function _updateCache(err, sessionID, sessionDataJSON, callback) {
if (sessionDataJSON && !err) {
this.cache.set(sessionID, sessionDataJSON);
callback(null, sessionDataJSON);
} else {
callback(err);
}
},
get: function get(sessionID, callback) {
var _this = this;
process.nextTick(function () {
_this._getFromCache(sessionID, callback);
});
},
set: function set(sessionID, sessionDataJSON, callback) {
var _this2 = this;
callback = callback || emptyFunction;
process.nextTick(function () {
_this2._getFromCache(sessionID, function (err, cacheSessionDataJSON) {
cacheSessionDataJSON = cacheSessionDataJSON || {};
if (_this2.areEqual(cacheSessionDataJSON, sessionDataJSON)) {
return callback();
} else {
_this2._updateCache(err, sessionID, sessionDataJSON, callback);
}
});
});
},
destroy: function destroy(sessionID, callback) {
var _this3 = this;
callback = callback || emptyFunction;
process.nextTick(function () {
_this3.dirtyCache(sessionID, callback);
});
}
});
module.exports = SessionDataStore;
})();