1+ const Redis = require ( "ioredis" ) ;
2+ const logger = require ( "../logging/log" ) ;
3+ const NodeCache = require ( "node-cache" ) ;
4+ const configuration = require ( "../configuration/config" ) ;
5+ const { default : Redlock } = require ( "redlock" ) ;
6+ const { redis } = require ( "../configuration/config" ) ;
7+
8+ const cacheTtl = configuration . cache . ttl ;
9+
10+ const localCache = new NodeCache ( {
11+ stdTTL : cacheTtl ,
12+ checkperiod : cacheTtl
13+ } ) ;
14+
15+ const redisClient = new Redis ( configuration . redis . url ) ;
16+ const redlockClient = new Redis ( configuration . redis . url ) ;
17+
18+ const redlock = new Redlock (
19+ [ redlockClient ] ,
20+ {
21+ driftFactor : 0.01 ,
22+ retryCount : 100000 ,
23+ retryDelay : 5000 ,
24+ retryJitter : 200 ,
25+ automaticExtensionThreshold : 500
26+ }
27+ ) ;
28+
29+ async function checkCache ( hostname ) {
30+ let memCached = await localCache . get ( hostname ) ;
31+ if ( memCached === undefined ) {
32+ try {
33+ let redisCached = await redisClient . get ( hostname ) ;
34+ if ( redisCached === null ) {
35+ return false
36+ } else {
37+ // Populate local in-memory cache from Redis
38+ localCache . set ( hostname , redisCached ) ;
39+ let cachedResult = JSON . parse ( redisCached ) ;
40+ return cachedResult ;
41+ }
42+ } catch ( err ) {
43+ logger . error ( "Could not check Redis cache" , err )
44+ }
45+ } else {
46+ return JSON . parse ( memCached ) ;
47+ }
48+ }
49+
50+ async function updateCache ( hostname , content ) {
51+ let contentObject = JSON . stringify ( content ) ;
52+ localCache . set ( hostname , contentObject ) ;
53+ try {
54+ await redisClient . set ( hostname , contentObject ) ;
55+ await redisClient . expire ( hostname , cacheTtl ) ;
56+ } catch ( err ) {
57+ logger . error ( "Error adding item to cache" , err ) ;
58+ }
59+ }
60+
61+
62+ async function rateLimitIncr ( key , amount , timeForAmount ) {
63+ const keyTtl = await redisClient . ttl ( key )
64+ logger . debug ( `rateLimitIncr: ${ key } has ttl ${ keyTtl } ` )
65+ var times = await redisClient . incr ( key )
66+ if ( ! keyTtl || keyTtl < 0 ) {
67+ logger . info ( `rateLimitIncr: setting TTL for ${ key } = ${ timeForAmount } seconds` )
68+ await redisClient . expire ( key , timeForAmount )
69+ }
70+
71+ return {
72+ times,
73+ periodInSeconds : timeForAmount ,
74+ keyTtl,
75+ surpassed : times > amount
76+ }
77+ }
78+
79+ module . exports = {
80+ updateCache,
81+ checkCache,
82+ redlockClient,
83+ redlock,
84+ rateLimitIncr
85+ }
0 commit comments