Permalink
Browse files

Merge pull request #209 from STRML/ttl-fn

Add support for store.ttl fn.
  • Loading branch information...
2 parents e8130a5 + 96d444c commit b41037e910bb1238dbf88496bd2f2e002f05e59b @wavded wavded committed on GitHub Jun 14, 2017
Showing with 82 additions and 3 deletions.
  1. +1 −0 Readme.md
  2. +7 −3 lib/connect-redis.js
  3. +1 −0 package.json
  4. +73 −0 test/connect-redis-test.js
View
@@ -35,6 +35,7 @@ A Redis client is required. An existing client can be passed directly using the
The following additional params may be included:
- `ttl` Redis session TTL (expiration) in seconds. Defaults to session.maxAge (if set), or one day.
+ - This may also be set to a function of the form `(store, sess, sessionID) => number`.
- `disableTTL` Disables setting TTL, keys will stay in redis until evicted by other means (overides `ttl`\)
- `db` Database index to use. Defaults to Redis's default (0).
- `pass` Password for Redis authentication
View
@@ -15,9 +15,13 @@ var noop = function(){};
var oneDay = 86400;
-function getTTL(store, sess) {
+function getTTL(store, sess, sid) {
+ if (typeof store.ttl === 'number') return store.ttl;
+ if (typeof store.ttl === 'function') return store.ttl(store, sess, sid);
+ if (store.ttl) throw new TypeError('`store.ttl` must be a number or function.');
+
var maxAge = sess.cookie.maxAge;
- return store.ttl || (typeof maxAge === 'number'
+ return (typeof maxAge === 'number'
? Math.floor(maxAge / 1000)
: oneDay);
}
@@ -188,7 +192,7 @@ module.exports = function (session) {
args.push(jsess);
if (!store.disableTTL) {
- var ttl = getTTL(store, sess);
+ var ttl = getTTL(store, sess, sid);
args.push('EX', ttl);
debug('SET "%s" %s ttl:%s', sid, jsess, ttl);
} else {
View
@@ -23,6 +23,7 @@
"express-session": "^1.9.1",
"ioredis": "^2.5.0",
"istanbul": "^0.4.5",
+ "sinon": "^2.3.4",
"tape": "^4.2.1"
},
"engines": {
View
@@ -5,6 +5,7 @@ var session = require('express-session');
var RedisStore = require('../')(session);
var redis = require('redis');
var ioRedis = require('ioredis');
+var sinon = require('sinon');
var P = require('bluebird');
var lifecycleTest = P.coroutine(function *(store, t) {
@@ -97,6 +98,78 @@ test('options', function (t) {
return lifecycleTest(store, t);
});
+test('ttl options', P.coroutine(function *(t) {
+ var store = new RedisStore({ port: redisSrv.port });
+
+ var sid = '123';
+ var data, ok;
+ sinon.stub(store.client, 'set').callsArgWith(1, null, 'OK');
+ P.promisifyAll(store);
+
+ // Basic (one day)
+ data = { cookie: {}, name: 'tj' };
+ ok = yield store.setAsync(sid, data);
+ t.equal(ok, 'OK', '#set() ok');
+ assertSetCalledWith(t, store, sid, data, ['EX', 86400]);
+
+ // maxAge in cookie
+ data = { cookie: { maxAge: 2000 }, name: 'tj' };
+ ok = yield store.setAsync(sid, data);
+ t.equal(ok, 'OK', '#set() ok');
+ assertSetCalledWith(t, store, sid, data, ['EX', 2]);
+
+ // Floors maxage
+ data = { cookie: { maxAge: 2500 }, name: 'tj' };
+ ok = yield store.setAsync(sid, data);
+ t.equal(ok, 'OK', '#set() ok');
+ assertSetCalledWith(t, store, sid, data, ['EX', 2]);
+
+ // store.disableTTL
+ store.disableTTL = true;
+ data = { cookie: {}, name: 'tj' };
+ ok = yield store.setAsync(sid, data);
+ t.equal(ok, 'OK', '#set() ok');
+ assertSetCalledWith(t, store, sid, data);
+ store.disableTTL = false;
+
+ // store.ttl: number
+ store.ttl = 50;
+ data = { cookie: {}, name: 'tj' };
+ ok = yield store.setAsync(sid, data);
+ t.equal(ok, 'OK', '#set() ok');
+ assertSetCalledWith(t, store, sid, data, ['EX', 50]);
+ store.ttl = null;
+
+ // store.ttl: function
+ store.ttl = sinon.stub().returns(200);
+ data = { cookie: {}, name: 'tj' };
+ ok = yield store.setAsync(sid, data);
+ t.equal(ok, 'OK', '#set() ok');
+ assertSetCalledWith(t, store, sid, data, ['EX', 200]);
+ t.ok(store.ttl.called, 'TTL fn was called');
+ t.deepEqual(store.ttl.firstCall.args, [store, data, sid]);
+ store.ttl = null;
+
+ // store.ttl: string (invalid)
+ store.ttl = '123';
+ data = { cookie: {}, name: 'tj' };
+ try {
+ ok = yield store.setAsync(sid, data);
+ t.ok(false, '#set() should throw with bad TTL');
+ } catch (e) {
+ t.ok(/must be a number or function/i.test(e.message), 'bad TTL type throws error');
+ }
+ store.ttl = null;
+
+ store.client.end(false);
+}));
+
+function assertSetCalledWith(t, store, sid, data, addl) {
+ var args = [store.prefix + sid, store.serializer.stringify(data)];
+ if (Array.isArray(addl)) args = args.concat(addl);
+ t.deepEqual(store.client.set.lastCall.args[0], args, '#.set() called with expected params');
+}
+
test('interups', function (t) {
var store = P.promisifyAll(new RedisStore({ port: redisSrv.port, connect_timeout: 500 }));
return store.setAsync('123', { cookie: { maxAge: 2000 }, name: 'tj' })

0 comments on commit b41037e

Please sign in to comment.