mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-03-30 18:47:14 +02:00
Removes a lot of unused (in ABS) functionality, refactors to ES6 style class, and re-enables this custom implementation with check period and ttl of 1 day, and 1000 max entries. The class now only implments the required (as per express-session docs) methods and removes optional methods, except touch() which allows the TTL of an entry to be refreshed without affecting its LRU recency. There is no longer a way to stop the prune timer, but I don't belive the function was ever being called beforehand. The session store's lifetime is the same as the application's, and since it is unref()'d should not cause any shutdown issues.
119 lines
2.8 KiB
JavaScript
119 lines
2.8 KiB
JavaScript
/*!
|
|
* memorystore
|
|
* Copyright(c) 2020 Rocco Musolino <@roccomuso>
|
|
* MIT Licensed
|
|
*/
|
|
//
|
|
// modified for audiobookshelf (update to lru-cache 10)
|
|
// SOURCE: https://github.com/roccomuso/memorystore
|
|
//
|
|
|
|
const debug = require('debug')('memorystore')
|
|
const { LRUCache } = require('lru-cache')
|
|
const { Store } = require('express-session')
|
|
|
|
/**
|
|
* An alternative memory store implementation for express session that prunes stale entries.
|
|
*
|
|
* @param {number} checkPeriod stale entry pruning frequency in ms
|
|
* @param {number} ttl entry time to live in ms
|
|
* @param {number} max LRU cache max entries
|
|
*/
|
|
module.exports = class MemoryStore extends Store {
|
|
constructor(checkPeriod, ttl, max) {
|
|
if (typeof checkPeriod !== 'number' || typeof checkPeriod !== 'number' || typeof checkPeriod !== 'number') {
|
|
throw Error('All arguments must be provided')
|
|
}
|
|
super()
|
|
this.store = new LRUCache({ ttl, max })
|
|
let prune = () => {
|
|
let sizeBefore = this.store.size
|
|
this.store.purgeStale()
|
|
debug('PRUNE size changed by %i entries', sizeBefore - this.store.size)
|
|
}
|
|
setInterval(prune, Math.floor(checkPeriod)).unref()
|
|
debug('INIT MemoryStore constructed with checkPeriod "%i", ttl "%i", max "%i"', checkPeriod, ttl, max)
|
|
}
|
|
|
|
/**
|
|
* Attempt to fetch session by the given `sid`.
|
|
*
|
|
* @param {String} sid
|
|
* @param {Function} fn
|
|
* @api public
|
|
*/
|
|
get(sid, fn) {
|
|
let err = null
|
|
let res = null
|
|
const data = this.store.get(sid)
|
|
debug('GET %s: %s', sid, data)
|
|
if (data) {
|
|
try {
|
|
res = JSON.parse(data)
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
}
|
|
fn && setImmediate(fn, err, res)
|
|
}
|
|
|
|
/**
|
|
* Commit the given `sess` object associated with the given `sid`.
|
|
*
|
|
* @param {String} sid
|
|
* @param {Session} sess
|
|
* @param {Function} fn
|
|
* @api public
|
|
*/
|
|
set(sid, sess, fn) {
|
|
let err = null
|
|
try {
|
|
let jsess = JSON.stringify(sess)
|
|
debug('SET %s: %s', sid, jsess)
|
|
this.store.set(sid, jsess)
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
fn && setImmediate(fn, err)
|
|
}
|
|
|
|
/**
|
|
* Destroy the session associated with the given `sid`.
|
|
*
|
|
* @param {String} sid
|
|
* @param {Function} fn
|
|
* @api public
|
|
*/
|
|
destroy(sid, fn) {
|
|
debug('DESTROY %s', sid)
|
|
let err = null
|
|
try {
|
|
this.store.delete(sid)
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
fn && setImmediate(fn, err)
|
|
}
|
|
|
|
/**
|
|
* Refresh the time-to-live for the session with the given `sid` without affecting
|
|
* LRU recency.
|
|
*
|
|
* @param {String} sid
|
|
* @param {Session} sess
|
|
* @param {Function} fn
|
|
* @api public
|
|
*/
|
|
|
|
touch(sid, sess, fn) {
|
|
debug('TOUCH %s', sid)
|
|
let err = null
|
|
try {
|
|
this.store.has(sid, { updateAgeOnHas: true })
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
fn && setImmediate(fn, err)
|
|
}
|
|
}
|