Use apicache instead of our broken implementation

pull/1787/head
Chocobozzz 2019-04-25 11:27:13 +02:00
parent d0dba1fce6
commit 47f6409bb8
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
5 changed files with 34 additions and 75 deletions

View File

@ -91,9 +91,9 @@
"@types/bluebird": "3.5.21"
},
"dependencies": {
"apicache": "^1.4.0",
"application-config": "^1.0.1",
"async": "^2.0.0",
"async-lock": "^1.1.2",
"async-lru": "^1.1.1",
"bcrypt": "3.0.5",
"bittorrent-tracker": "^9.0.0",
@ -159,6 +159,7 @@
"youtube-dl": "^1.12.2"
},
"devDependencies": {
"@types/apicache": "^1.2.0",
"@types/async": "^2.0.40",
"@types/async-lock": "^1.1.0",
"@types/bcrypt": "^3.0.0",

View File

@ -71,7 +71,7 @@ class JobQueue {
this.jobRedisPrefix = 'bull-' + WEBSERVER.HOST
const queueOptions = {
prefix: this.jobRedisPrefix,
redis: Redis.getRedisClient(),
redis: Redis.getRedisClientOptions(),
settings: {
maxStalledCount: 10 // transcoding could be long, so jobs can often be interrupted by restarts
}

View File

@ -31,7 +31,7 @@ class Redis {
if (this.initialized === true) return
this.initialized = true
this.client = createClient(Redis.getRedisClient())
this.client = createClient(Redis.getRedisClientOptions())
this.client.on('error', err => {
logger.error('Error in Redis client.', { err })
@ -45,7 +45,7 @@ class Redis {
this.prefix = 'redis-' + WEBSERVER.HOST + '-'
}
static getRedisClient () {
static getRedisClientOptions () {
return Object.assign({},
(CONFIG.REDIS.AUTH && CONFIG.REDIS.AUTH != null) ? { password: CONFIG.REDIS.AUTH } : {},
(CONFIG.REDIS.DB) ? { db: CONFIG.REDIS.DB } : {},
@ -55,6 +55,14 @@ class Redis {
)
}
getClient () {
return this.client
}
getPrefix () {
return this.prefix
}
/************* Forgot password *************/
async setResetPasswordVerificationString (userId: number) {

View File

@ -1,73 +1,16 @@
import * as express from 'express'
import * as AsyncLock from 'async-lock'
import { parseDurationToMs } from '../helpers/core-utils'
import { Redis } from '../lib/redis'
import { logger } from '../helpers/logger'
import * as apicache from 'apicache'
const lock = new AsyncLock({ timeout: 5000 })
// Ensure Redis is initialized
Redis.Instance.init()
function cacheRoute (lifetimeArg: string | number) {
const lifetime = parseDurationToMs(lifetimeArg)
return async function (req: express.Request, res: express.Response, next: express.NextFunction) {
const redisKey = Redis.Instance.generateCachedRouteKey(req)
try {
await lock.acquire(redisKey, async (done) => {
const cached = await Redis.Instance.getCachedRoute(req)
// Not cached
if (!cached) {
logger.debug('No cached results for route %s.', req.originalUrl)
const sendSave = res.send.bind(res)
const redirectSave = res.redirect.bind(res)
res.send = (body) => {
if (res.statusCode >= 200 && res.statusCode < 400) {
const contentType = res.get('content-type')
Redis.Instance.setCachedRoute(req, body, lifetime, contentType, res.statusCode)
.then(() => done())
.catch(err => {
logger.error('Cannot cache route.', { err })
return done(err)
})
} else {
done()
}
return sendSave(body)
}
res.redirect = url => {
done()
return redirectSave(url)
}
return next()
}
if (cached.contentType) res.set('content-type', cached.contentType)
if (cached.statusCode) {
const statusCode = parseInt(cached.statusCode, 10)
if (!isNaN(statusCode)) res.status(statusCode)
}
logger.debug('Use cached result for %s.', req.originalUrl)
res.send(cached.body).end()
return done()
})
} catch (err) {
logger.error('Cannot serve cached route.', { err })
return next()
}
}
const options = {
redisClient: Redis.Instance.getClient(),
appendKey: () => Redis.Instance.getPrefix()
}
const cacheRoute = apicache.options(options).middleware
// ---------------------------------------------------------------------------
export {

View File

@ -16,6 +16,13 @@
dependencies:
any-observable "^0.3.0"
"@types/apicache@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@types/apicache/-/apicache-1.2.0.tgz#5f6e9225e66d22da97042a39ad626b3c158d650d"
integrity sha512-8uatdizj2GbYHtS4u+x4k2aG1thG6JBWKRidcnauXav+Bxe3bHsWS8HSwcybuLE2q39/95cwb4hkHvqmP7ja2w==
dependencies:
"@types/redis" "*"
"@types/async-lock@^1.1.0":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/async-lock/-/async-lock-1.1.1.tgz#81f218213bebcc5f740efe9648272c774a2e4b4b"
@ -276,7 +283,7 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
"@types/redis@^2.8.5":
"@types/redis@*", "@types/redis@^2.8.5":
version "2.8.12"
resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.12.tgz#6405d7ece0d6cc037151b7141cef9ad3cd06f3ac"
integrity sha512-eT5cGYr08OnF6OlAHdc2hVOBAKBpfQQNQHsWEvUwRPFiXRd+vv+hOHSSIo4xB7M5vZOZdjMT2OUlXYqo3YlIGQ==
@ -548,6 +555,11 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
apicache@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/apicache/-/apicache-1.4.0.tgz#3835fbe18717caca3a44cb6272d49b52cac30d3a"
integrity sha512-pX/Sf9q9HNzAC5F+hPgxt8v3eQVZkXL/+8HpAnrDJXFmma80F2aHAAeWTql3BsG87lc3T6A7CFPNWMTl97L/7Q==
append-field@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
@ -695,11 +707,6 @@ async-limiter@~1.0.0:
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
async-lock@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.2.0.tgz#cd6a53cb1ec3f86af25eafdeb6bc7c6e317258b8"
integrity sha512-81HzTQm4+qMj6PwNlnR+y9g7pDdGGzd/YBUrQnHk+BhR28ja2qv497NkQQc1KcKEqh/RShm07di2b0cIWVFrNQ==
async-lru@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/async-lru/-/async-lru-1.1.2.tgz#abe831f3a52123c87d44273615e203b1ef04692e"