Skip to content

Commit

Permalink
get, all, and length will now exclude expired sessions; see #89
Browse files Browse the repository at this point in the history
  • Loading branch information
chill117 committed Dec 22, 2018
1 parent 2d369f1 commit 400ac0f
Show file tree
Hide file tree
Showing 14 changed files with 240 additions and 421 deletions.
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

* TBD:
* `get`, `all`, and `length` will now exclude expired sessions. See [#89](https://github.com/chill117/express-mysql-session/issues/89) for more details.
* Removed grunt; now using npm run tasks.
* Updated dependencies
* v2.0.1:
* Updated dependencies
* v2.0.0:
Expand Down
29 changes: 23 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,11 @@ module.exports = function(session) {
debug.log('Getting session:', session_id);

// LIMIT not needed here because the WHERE clause is searching by the table's primary key.
var sql = 'SELECT ?? AS data FROM ?? WHERE ?? = ?';
var sql = 'SELECT ?? AS data, ?? as expires FROM ?? WHERE ?? = ?';

var params = [
this.options.schema.columnNames.data,
this.options.schema.columnNames.expires,
this.options.schema.tableName,
this.options.schema.columnNames.session_id,
session_id
Expand All @@ -166,8 +167,20 @@ module.exports = function(session) {
return cb(error, null);
}

var row = rows[0] || null;
if (!row) {
return cb(null, null);
}

// Check the expires time.
var now = Math.round(Date.now() / 1000);
if (row.expires < now) {
// Session has expired.
return cb(null, null);
}

try {
var session = rows[0] ? JSON.parse(rows[0].data) : null;
var session = JSON.parse(row.data);
} catch (error) {
debug.error('Failed to parse data for session (' + session_id + ')');
debug.error(error);
Expand Down Expand Up @@ -310,10 +323,12 @@ module.exports = function(session) {

debug.log('Getting number of sessions');

var sql = 'SELECT COUNT(*) FROM ??';
var sql = 'SELECT COUNT(*) FROM ?? WHERE ?? >= ?';

var params = [
this.options.schema.tableName
this.options.schema.tableName,
this.options.schema.columnNames.expires,
Math.round(Date.now() / 1000)
];

this.query(sql, params, function(error, rows) {
Expand All @@ -334,10 +349,12 @@ module.exports = function(session) {

debug.log('Getting all sessions');

var sql = 'SELECT * FROM ??';
var sql = 'SELECT * FROM ?? WHERE ?? >= ?';

var params = [
this.options.schema.tableName
this.options.schema.tableName,
this.options.schema.columnNames.expires,
Math.round(Date.now() / 1000)
];

this.query(sql, params, function(error, rows) {
Expand Down
23 changes: 4 additions & 19 deletions test/benchmarks/touch.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,11 @@ var manager = require('../manager');

describe('benchmark: touch', function() {

var sessionStore;
before(manager.setUp);

before(function(done) {

manager.setUp(function(error, store) {

if (error) {
return done(error);
}

sessionStore = store;
done();
});
});

var numSessions = 1000000;
var numSessions = 50000;
var sessionIdPrefix = 'benchmarking-session-id-';

before(function(done) {

this.timeout(60000);
manager.populateManySessions(numSessions, sessionIdPrefix, done);
});
Expand All @@ -34,10 +19,10 @@ describe('benchmark: touch', function() {

it('touch()', function(done) {

this.timeout(15000);
this.timeout(30000);

var bench = new Benchmark(function(deferred) {
sessionStore.touch(sessionIdPrefix + _.random(numSessions), {}/* session object */, function() {
manager.sessionStore.touch(sessionIdPrefix + _.random(numSessions), {}/* session object */, function() {
deferred.resolve();
});
}, { defer: true });
Expand Down
130 changes: 62 additions & 68 deletions test/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,73 +8,89 @@ var mysql = require('mysql');
var config = require('./config');
var fixtures = require('./fixtures');

var connection = mysql.createConnection(config);

var manager = module.exports = {

config: config,
connection: connection,
fixtures: fixtures,
stores: [],

setUp: function(cb) {

async.series({
tearDown: manager.tearDown,
store: manager.createInstance
}, function(error, results) {

if (error) {
return cb(error);
}

var store = results.store;
manager.stores.push(store);
cb(null, store);
});
async.seq(manager.tearDown, manager.createInstance)(cb);
},

tearDown: function(cb) {

async.series([
manager.dropDatabaseTables
], cb);
async.seq(manager.dropDatabaseTables)(cb);
},

dropDatabaseTables: function(cb) {

connection.query('SHOW TABLES', function(error, rows) {
manager.sessionStore.connection.query('SHOW TABLES', function(error, rows) {

async.each(rows, function(row, next) {

var tableName = row['Tables_in_' + config.database];
var sql = 'DROP TABLE IF EXISTS ??';
var params = [tableName];

connection.query(sql, params, next);
manager.sessionStore.connection.query(sql, params, next);

}, cb);
});
},

populateSessions: function(cb) {
expireSession: function(sessionId, cb) {

var expiration = sessionStore.options.expiration;
var sql = 'UPDATE ?? SET ?? = ? WHERE ?? = ?';
var expires = ( new Date( Date.now() - (expiration + 60000) ) ) / 1000;
var params = [
sessionStore.options.schema.tableName,
sessionStore.options.schema.columnNames.expires,
expires,
sessionStore.options.schema.columnNames.session_id,
sessionId
];
sessionStore.connection.query(sql, params, cb);
},

expireSomeSessions: function(numToExpire, cb) {

var expiration = sessionStore.options.expiration;
var sql = 'UPDATE ?? SET ?? = ? LIMIT ?';
var expires = ( new Date( Date.now() - (expiration + 60000) ) ) / 1000;
var params = [
sessionStore.options.schema.tableName,
sessionStore.options.schema.columnNames.expires,
expires,
numToExpire
];
sessionStore.connection.query(sql, params, cb);
},

async.each(fixtures.sessions, function(session, next) {
populateSessions: function(cb) {

var session_id = session.session_id;
var data = session.data;
async.each(fixtures.sessions, manager.populateSession, cb);
},

sessionStore.set(session_id, data, next);
populateSession: function(session, cb) {

}, cb);
var sessionId = session.session_id;
var data = session.data;
sessionStore.set(sessionId, data, cb);
},

populateManySessions: function(targetNumSessions, prefix, cb) {

var numSessions = 0;
var batchSize = Math.min(50000, targetNumSessions);
if (typeof prefix === 'function') {
cb = prefix;
prefix = null;
}

var expires = Math.round((new Date).getTime() / 1000);
prefix = prefix || '';
var numSessions = 0;
var expires = Math.round(Date.now() / 1000);
var dataStr = JSON.stringify({
someText: 'some sample text',
someInt: 1001,
Expand All @@ -83,26 +99,26 @@ var manager = module.exports = {

async.whilst(function() { return numSessions < targetNumSessions; }, function(next) {

var sql = 'INSERT INTO ?? (??, ??, ??) VALUES (?, ?, ?)';
var batchSize = Math.min(2000, targetNumSessions - numSessions);
var sql = 'INSERT INTO ?? (??, ??, ??) VALUES ';
var params = [
sessionStore.options.schema.tableName,
sessionStore.options.schema.columnNames.session_id,
sessionStore.options.schema.columnNames.expires,
sessionStore.options.schema.columnNames.data,
prefix + '-' + (numSessions),
expires,
dataStr
];

_.times(batchSize - 1, function(index) {
sql += ', (?, ?, ?)';
params.push(prefix + '-' + (numSessions + index + 1));
params.push(expires);
params.push(dataStr);
sql += _.chain(new Array(batchSize)).map(function() {
return '(?, ?, ?)';
}).value().join(', ');

_.times(batchSize, function(index) {
var sessionId = prefix + '-' + (numSessions + index);
params = params.concat([sessionId, expires, dataStr]);
});

numSessions += batchSize;
connection.query(sql, params, next);
manager.sessionStore.connection.query(sql, params, next);

}, cb);
},
Expand Down Expand Up @@ -131,38 +147,16 @@ var manager = module.exports = {
}

options = _.defaults(options || {}, config);
cb = cb || _.noop;
var store = new MySQLStore(options, cb);
manager.stores.push(store);
return store;
},

return sessionStore = new MySQLStore(options, function(error) {

if (error) {
return cb(error);
}

cb(null, sessionStore);
});
}
};

var MySQLStore = manager.MySQLStore = manager.loadConstructor();
var sessionStore;

after(function(done) {
if (!connection) return done();
connection.end(function(error) {
if (error) return done(error);
connection = null;
done();
});
});

after(function(done) {
if (!sessionStore) return done();
sessionStore.close(function(error) {
if (error) return done(error);
sessionStore = null;
done();
});
});
var sessionStore = manager.sessionStore = manager.createInstance();

after(function(done) {
async.each(manager.stores, function(store, next) {
Expand Down
Loading

0 comments on commit 400ac0f

Please sign in to comment.