aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/middlewares
diff options
context:
space:
mode:
Diffstat (limited to 'server/middlewares')
-rw-r--r--server/middlewares/cache/shared/api-cache.ts50
1 files changed, 27 insertions, 23 deletions
diff --git a/server/middlewares/cache/shared/api-cache.ts b/server/middlewares/cache/shared/api-cache.ts
index f8846dcfc..86c5095b5 100644
--- a/server/middlewares/cache/shared/api-cache.ts
+++ b/server/middlewares/cache/shared/api-cache.ts
@@ -7,6 +7,7 @@ import { isTestInstance, parseDurationToMs } from '@server/helpers/core-utils'
7import { logger } from '@server/helpers/logger' 7import { logger } from '@server/helpers/logger'
8import { Redis } from '@server/lib/redis' 8import { Redis } from '@server/lib/redis'
9import { HttpStatusCode } from '@shared/models' 9import { HttpStatusCode } from '@shared/models'
10import { asyncMiddleware } from '@server/middlewares'
10 11
11export interface APICacheOptions { 12export interface APICacheOptions {
12 headerBlacklist?: string[] 13 headerBlacklist?: string[]
@@ -40,24 +41,25 @@ export class ApiCache {
40 buildMiddleware (strDuration: string) { 41 buildMiddleware (strDuration: string) {
41 const duration = parseDurationToMs(strDuration) 42 const duration = parseDurationToMs(strDuration)
42 43
43 return (req: express.Request, res: express.Response, next: express.NextFunction) => { 44 return asyncMiddleware(
44 const key = Redis.Instance.getPrefix() + 'api-cache-' + req.originalUrl 45 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
45 const redis = Redis.Instance.getClient() 46 const key = Redis.Instance.getPrefix() + 'api-cache-' + req.originalUrl
47 const redis = Redis.Instance.getClient()
46 48
47 if (!redis.connected) return this.makeResponseCacheable(res, next, key, duration) 49 if (!Redis.Instance.isConnected()) return this.makeResponseCacheable(res, next, key, duration)
48 50
49 try { 51 try {
50 redis.hgetall(key, (err, obj) => { 52 const obj = await redis.hGetAll(key)
51 if (!err && obj && obj.response) { 53 if (obj?.response) {
52 return this.sendCachedResponse(req, res, JSON.parse(obj.response), duration) 54 return this.sendCachedResponse(req, res, JSON.parse(obj.response), duration)
53 } 55 }
54 56
55 return this.makeResponseCacheable(res, next, key, duration) 57 return this.makeResponseCacheable(res, next, key, duration)
56 }) 58 } catch (err) {
57 } catch (err) { 59 return this.makeResponseCacheable(res, next, key, duration)
58 return this.makeResponseCacheable(res, next, key, duration) 60 }
59 } 61 }
60 } 62 )
61 } 63 }
62 64
63 private shouldCacheResponse (response: express.Response) { 65 private shouldCacheResponse (response: express.Response) {
@@ -93,21 +95,22 @@ export class ApiCache {
93 } as CacheObject 95 } as CacheObject
94 } 96 }
95 97
96 private cacheResponse (key: string, value: object, duration: number) { 98 private async cacheResponse (key: string, value: object, duration: number) {
97 const redis = Redis.Instance.getClient() 99 const redis = Redis.Instance.getClient()
98 100
99 if (redis.connected) { 101 if (Redis.Instance.isConnected()) {
100 try { 102 await Promise.all([
101 redis.hset(key, 'response', JSON.stringify(value)) 103 redis.hSet(key, 'response', JSON.stringify(value)),
102 redis.hset(key, 'duration', duration + '') 104 redis.hSet(key, 'duration', duration + ''),
103 redis.expire(key, duration / 1000) 105 redis.expire(key, duration / 1000)
104 } catch (err) { 106 ])
105 logger.error('Cannot set cache in redis.', { err })
106 }
107 } 107 }
108 108
109 // add automatic cache clearing from duration, includes max limit on setTimeout 109 // add automatic cache clearing from duration, includes max limit on setTimeout
110 this.timers[key] = setTimeout(() => this.clear(key), Math.min(duration, 2147483647)) 110 this.timers[key] = setTimeout(() => {
111 this.clear(key)
112 .catch(err => logger.error('Cannot clear Redis key %s.', key, { err }))
113 }, Math.min(duration, 2147483647))
111 } 114 }
112 115
113 private accumulateContent (res: express.Response, content: any) { 116 private accumulateContent (res: express.Response, content: any) {
@@ -184,6 +187,7 @@ export class ApiCache {
184 encoding 187 encoding
185 ) 188 )
186 self.cacheResponse(key, cacheObject, duration) 189 self.cacheResponse(key, cacheObject, duration)
190 .catch(err => logger.error('Cannot cache response', { err }))
187 } 191 }
188 } 192 }
189 193
@@ -235,7 +239,7 @@ export class ApiCache {
235 return response.end(data, cacheObject.encoding) 239 return response.end(data, cacheObject.encoding)
236 } 240 }
237 241
238 private clear (target: string) { 242 private async clear (target: string) {
239 const redis = Redis.Instance.getClient() 243 const redis = Redis.Instance.getClient()
240 244
241 if (target) { 245 if (target) {
@@ -243,7 +247,7 @@ export class ApiCache {
243 delete this.timers[target] 247 delete this.timers[target]
244 248
245 try { 249 try {
246 redis.del(target) 250 await redis.del(target)
247 } catch (err) { 251 } catch (err) {
248 logger.error('Cannot delete %s in redis cache.', target, { err }) 252 logger.error('Cannot delete %s in redis cache.', target, { err })
249 } 253 }
@@ -255,7 +259,7 @@ export class ApiCache {
255 delete this.timers[key] 259 delete this.timers[key]
256 260
257 try { 261 try {
258 redis.del(key) 262 await redis.del(key)
259 } catch (err) { 263 } catch (err) {
260 logger.error('Cannot delete %s in redis cache.', key, { err }) 264 logger.error('Cannot delete %s in redis cache.', key, { err })
261 } 265 }