aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/middlewares
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-05-23 10:03:26 +0200
committerChocobozzz <me@florianbigard.com>2018-05-23 10:03:26 +0200
commitb40f057594d51ae64e9d638d3b5877e544214b53 (patch)
treebd7918e8b5ab4f688422125a925cca9b6ff527bc /server/middlewares
parente1a540b5fa14b0fafa63f99e344927b10fdbee00 (diff)
downloadPeerTube-b40f057594d51ae64e9d638d3b5877e544214b53.tar.gz
PeerTube-b40f057594d51ae64e9d638d3b5877e544214b53.tar.zst
PeerTube-b40f057594d51ae64e9d638d3b5877e544214b53.zip
Handle concurrent requests in cache middleware
Diffstat (limited to 'server/middlewares')
-rw-r--r--server/middlewares/cache.ts53
1 files changed, 33 insertions, 20 deletions
diff --git a/server/middlewares/cache.ts b/server/middlewares/cache.ts
index c589ef683..bf6659687 100644
--- a/server/middlewares/cache.ts
+++ b/server/middlewares/cache.ts
@@ -1,39 +1,52 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as AsyncLock from 'async-lock'
2import { Redis } from '../lib/redis' 3import { Redis } from '../lib/redis'
3import { logger } from '../helpers/logger' 4import { logger } from '../helpers/logger'
4 5
6const lock = new AsyncLock({ timeout: 5000 })
7
5function cacheRoute (lifetime: number) { 8function cacheRoute (lifetime: number) {
6 return async function (req: express.Request, res: express.Response, next: express.NextFunction) { 9 return async function (req: express.Request, res: express.Response, next: express.NextFunction) {
7 const cached = await Redis.Instance.getCachedRoute(req) 10 const redisKey = Redis.Instance.buildCachedRouteKey(req)
11
12 await lock.acquire(redisKey, async (done) => {
13 const cached = await Redis.Instance.getCachedRoute(req)
8 14
9 // Not cached 15 // Not cached
10 if (!cached) { 16 if (!cached) {
11 logger.debug('Not cached result for route %s.', req.originalUrl) 17 logger.debug('Not cached result for route %s.', req.originalUrl)
12 18
13 const sendSave = res.send.bind(res) 19 const sendSave = res.send.bind(res)
14 20
15 res.send = (body) => { 21 res.send = (body) => {
16 if (res.statusCode >= 200 && res.statusCode < 400) { 22 if (res.statusCode >= 200 && res.statusCode < 400) {
17 const contentType = res.getHeader('content-type').toString() 23 const contentType = res.getHeader('content-type').toString()
18 Redis.Instance.setCachedRoute(req, body, lifetime, contentType, res.statusCode) 24 Redis.Instance.setCachedRoute(req, body, lifetime, contentType, res.statusCode)
19 .catch(err => logger.error('Cannot cache route.', { err })) 25 .then(() => done())
26 .catch(err => {
27 logger.error('Cannot cache route.', { err })
28 return done(err)
29 })
30 }
31
32 return sendSave(body)
20 } 33 }
21 34
22 return sendSave(body) 35 return next()
23 } 36 }
24 37
25 return next() 38 if (cached.contentType) res.contentType(cached.contentType)
26 }
27 39
28 if (cached.contentType) res.contentType(cached.contentType) 40 if (cached.statusCode) {
41 const statusCode = parseInt(cached.statusCode, 10)
42 if (!isNaN(statusCode)) res.status(statusCode)
43 }
29 44
30 if (cached.statusCode) { 45 logger.debug('Use cached result for %s.', req.originalUrl)
31 const statusCode = parseInt(cached.statusCode, 10) 46 res.send(cached.body).end()
32 if (!isNaN(statusCode)) res.status(statusCode)
33 }
34 47
35 logger.debug('Use cached result for %s.', req.originalUrl) 48 return done()
36 return res.send(cached.body).end() 49 })
37 } 50 }
38} 51}
39 52