Comparing version 0.4.1 to 0.5.0
@@ -7,3 +7,12 @@ const crypto = require('crypto'); | ||
const writeScript = new RedisScript(` | ||
function createWriteScript(fields) { | ||
let s = ''; | ||
if (fields) { | ||
for (let i = 0; i < fields.length; i++) { | ||
s += ', "f' + i + '", ARGV[' + (7 + i) + ']'; | ||
} | ||
} | ||
return new RedisScript(` | ||
local prefix = ARGV[1] | ||
@@ -19,3 +28,4 @@ local lastAccess = tonumber(ARGV[2]) | ||
redis.call("zadd", prefix..":user_"..userId, lastAccess, sessionId) | ||
redis.call("hmset", prefix..":sess_"..sessionId, "us", userId, "la", lastAccess, "ex", expires, "ttl", ttl) | ||
redis.call("hmset", prefix..":sess_"..sessionId, "us", userId, "la", lastAccess, "ex", expires, "ttl", ttl` + | ||
s + `) | ||
if (expires > 0) then | ||
@@ -28,2 +38,3 @@ redis.call("zadd", prefix..":EXPIRES", expires, sessionId) | ||
`); | ||
} | ||
@@ -89,2 +100,3 @@ const killScript = new RedisScript(` | ||
* @param {number} [options.wipeInterval=1000] | ||
* @param {Array<String>} [options.additionalFields] | ||
*/ | ||
@@ -104,2 +116,4 @@ constructor(client, appName, options) { | ||
this._wipeTimer = null; | ||
this._additionalFields = options.additionalFields; | ||
this._writeScript = createWriteScript(options.additionalFields); | ||
client.once('close', () => this.quit()); | ||
@@ -153,4 +167,3 @@ } | ||
* @param {number} [options.ttl] Time-To-Live value in seconds | ||
* @param {Object} [options.data] Additional data to set for this sessions | ||
* @param {Boolean} [options.immutable=false] If set to true the session will not be updated on session use. Instead it will run out exactly after the defined ttl. Default: false | ||
* @param {*} [options.*] Additional data to set for this sessions | ||
* @param options | ||
@@ -165,9 +178,9 @@ */ | ||
const sessionId = this._createSessionId(); | ||
const session = new Session(this, { | ||
sessionId, | ||
userId, | ||
ttl | ||
}); | ||
return session.freshen().then(() => session); | ||
const session = new Session(this, {sessionId, userId, ttl}); | ||
/* istanbul ignore else */ | ||
if (this._additionalFields) { | ||
for (const f of this._additionalFields) | ||
session[f] = options[f]; | ||
} | ||
return session._write().then(() => session); | ||
} | ||
@@ -338,3 +351,5 @@ | ||
this._wipeTimer = | ||
setTimeout(() => this._wipe().catch(() => 1), this._wipeInterval) | ||
setTimeout(() => { | ||
this._wipe().catch(/* istanbul ignore next */() => 1) | ||
}, this._wipeInterval) | ||
.unref(); | ||
@@ -463,9 +478,21 @@ if (this._timediff == null) | ||
':sess_' + this.sessionId; | ||
return manager._getClient().then(client => | ||
client.hmget(sessKey, 'us', 'la', 'ex', 'ttl').then(resp => { | ||
this._userId = resp[0]; | ||
this._lastAccess = Number(resp[1]) || 0; | ||
this._expires = Number(resp[2]) || 0; | ||
this._ttl = Number(resp[3]) || 0; | ||
}) | ||
return manager._getClient().then(client => { | ||
const args = ['us', 'la', 'ex', 'ttl']; | ||
/* istanbul ignore else */ | ||
if (manager._additionalFields) { | ||
for (const [i] of manager._additionalFields.entries()) | ||
args.push('f' + i); | ||
} | ||
return client.hmget(sessKey, ...args).then(resp => { | ||
this._userId = resp[0]; | ||
this._lastAccess = Number(resp[1]) || 0; | ||
this._expires = Number(resp[2]) || 0; | ||
this._ttl = Number(resp[3]) || 0; | ||
/* istanbul ignore else */ | ||
if (manager._additionalFields) { | ||
for (const [i, f] of manager._additionalFields.entries()) | ||
this[f] = resp[4 + i]; | ||
} | ||
}); | ||
} | ||
); | ||
@@ -480,18 +507,3 @@ } | ||
freshen() { | ||
const manager = this._manager; | ||
return manager._getClient().then(client => { | ||
this._lastAccess = manager._now(); | ||
this._expires = this._ttl ? | ||
this._lastAccess + this._ttl : 0; | ||
const {sessionId, userId, lastAccess, expires, ttl} = this; | ||
const prefix = manager._ns + ':' + manager._appName; | ||
return writeScript.execute(client, | ||
prefix, lastAccess, userId, sessionId, expires, ttl).then(resp => { | ||
/* istanbul ignore next */ | ||
if (!resp) | ||
throw new Error('Unable to store session due to an unknown error'); | ||
}); | ||
}); | ||
return this._write(); | ||
} | ||
@@ -608,2 +620,30 @@ | ||
* | ||
* @param {Object} [data] | ||
* @return {Promise} | ||
* @private | ||
*/ | ||
_write(data) { | ||
const manager = this._manager; | ||
return manager._getClient().then(client => { | ||
this._lastAccess = manager._now(); | ||
this._expires = this._ttl ? | ||
this._lastAccess + this._ttl : 0; | ||
const {sessionId, userId, lastAccess, expires, ttl} = this; | ||
const prefix = manager._ns + ':' + manager._appName; | ||
const args = [prefix, lastAccess, userId, sessionId, expires, ttl]; | ||
/* istanbul ignore else */ | ||
if (manager._additionalFields) | ||
for (const f of manager._additionalFields) | ||
args.push(this[f] || null); | ||
return manager._writeScript.execute(client, ...args).then(resp => { | ||
/* istanbul ignore next */ | ||
if (!resp) | ||
throw new Error('Unable to store session due to an unknown error'); | ||
}); | ||
}); | ||
} | ||
/** | ||
* | ||
* @param {string|Object} key | ||
@@ -610,0 +650,0 @@ * @param {*} [value] |
{ | ||
"name": "redisess", | ||
"description": "Powerful redis session manager for NodeJS", | ||
"version": "0.4.1", | ||
"version": "0.5.0", | ||
"author": "Panates Ltd.", | ||
@@ -6,0 +6,0 @@ "contributors": [ |
22981
658