redisess
Version:
Powerful redis session manager for NodeJS
85 lines (84 loc) • 2.83 kB
JavaScript
import promisify from 'putil-promisify';
import { RedisScript } from './redis-script.js';
import { getKillAllScript, getKillScript, getWipeScript, getWriteScript, } from './scripts.js';
/**
*
* @class
*/
export class Backend {
/**
*
* @param {Object} client
* @param {Object} [props]
* @param {Object} [props.namespace='sm']
* @param {number} [props.ttl] Time-To-Live value in seconds
* @param {number} [props.wipeInterval=1000]
* @param {Array<String>} [props.additionalFields]
*/
constructor(client, props = {}) {
if (!(client && typeof client.hmset === 'function')) {
throw new TypeError('You must provide redis instance');
}
this.client = client;
this.additionalFields = props.additionalFields
? Object.freeze(props.additionalFields)
: undefined;
this.ns = props.namespace || 'sessions';
this.ttl = Number(props.ttl) >= 0 ? Number(props.ttl) : 30 * 60;
this.killScript = new RedisScript(getKillScript());
this.writeScript = new RedisScript(getWriteScript(props.additionalFields));
this.wipeScript = new RedisScript(getWipeScript());
this.killAllScript = new RedisScript(getKillAllScript());
this._timeDiff = 0;
this.wipeInterval = props.wipeInterval || 1000;
}
/* istanbul ignore next */
/**
* Stops wipe timer
*/
quit() {
this._stopWipeTimer();
}
async wipe() {
this._stopWipeTimer();
const client = await this.getClient();
await this.wipeScript.execute(client, this.ns, this.now());
this._startWipeTimer();
}
async getClient() {
this._startWipeTimer();
if (this.client.status !== 'ready') {
await new Promise(resolve => {
this.client.once('ready', resolve);
});
}
if (this._timeDiff == null)
await this.syncTime(this.client);
return this.client;
}
now() {
return Math.floor(Date.now() / 1000 + this._timeDiff);
}
_stopWipeTimer() {
if (!this._wipeTimer)
return;
clearTimeout(this._wipeTimer);
this._wipeTimer = undefined;
}
_startWipeTimer() {
if (this._wipeTimer)
return;
this._wipeTimer = setTimeout(() => {
this.wipe().catch(/* istanbul ignore next */ () => 1);
}, this.wipeInterval);
this._wipeTimer.unref();
}
async syncTime(client) {
const resp = await promisify.fromCallback(cb => client.time(cb));
// Synchronize redis server time with local time
this._timeDiff =
Date.now() / 1000 -
Math.floor(Number(resp[0]) + Number(resp[1]) / 1000000);
return this.now();
}
}