UNPKG

redisess

Version:

Powerful redis session manager for NodeJS

85 lines (84 loc) 2.83 kB
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(); } }