Created
May 4, 2023 20:02
-
-
Save green3g/1c6417a524a28b8093135005e941b731 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Application, HookContext } from '@feathersjs/feathers'; | |
import Redis, {RedisOptions} from 'ioredis'; | |
import crypto from 'crypto'; | |
import Cache from 'ioredis-cache'; | |
import logger from '../../logger'; | |
export const ONE_HOUR = 3600; | |
export const ONE_DAY = ONE_HOUR * 24; | |
export const ONE_WEEK = ONE_DAY * 7; | |
export interface IAppRedisOptions extends RedisOptions { | |
appKey: string; | |
} | |
export const defaultRedisOptions: IAppRedisOptions = { | |
keyPrefix: 'cache_', | |
appKey: 'cache', | |
}; | |
export function redisCache(opt: IAppRedisOptions){ | |
return function(app: Application){ | |
opt = { | |
...defaultRedisOptions, | |
...opt, | |
}; | |
logger.info({msg: 'Initializing cache', opt}); | |
const redis = new Redis(opt); | |
const cache = new Cache(redis); | |
const appKey = opt.appKey || 'redis'; | |
app.set(appKey, cache); | |
}; | |
} | |
export function getHash(context: HookContext): string{ | |
const hashParams = { | |
query: context.params.query, | |
paginate: context.params.paginate, | |
id: context.id, | |
}; | |
const hash = crypto.createHash('sha256').update(JSON.stringify(hashParams)).digest('hex'); | |
return hash; | |
} | |
export function getPrefix(context: HookContext): string{ | |
const prefix = context.path.replace(/\//g, '_'); | |
return prefix; | |
} | |
export function getKey(context: HookContext): string{ | |
const prefix = getPrefix(context); | |
const hash = getHash(context); | |
return `${prefix}__${hash}`; | |
} | |
export function beforeHook(appKey: string){ | |
return async (context: HookContext) => { | |
const cache = context.app.get(appKey) as Cache; | |
if(!cache){ | |
logger.error('Cache not initialized with provided key: ' + appKey); | |
} | |
context.params.cacheKey = getKey(context); | |
const result = await cache.getCache(context.params.cacheKey); | |
if (result) { | |
context.params.cacheHit = true; | |
logger.info({msg: 'Cache hit', cacheKey: context.params.cacheKey}); | |
context.result = result; | |
return context; | |
} | |
logger.info({msg: 'Cache miss', cacheKey: context.params.cacheKey}); | |
return context; | |
}; | |
} | |
export function afterHook(appKey: string, expires = ONE_HOUR){ | |
return async (context: HookContext) => { | |
const cache = context.app.get(appKey) as Cache; | |
if(!cache){ | |
logger.error('Cache not initialized with provided key: ' + appKey); | |
return; | |
} | |
if(!context.params.cacheHit){ | |
await cache.setCache(context.params.cacheKey, context.result, expires); | |
logger.info({msg: 'Cache updated', cacheKey: context.params.cacheKey}); | |
} | |
return context; | |
}; | |
} | |
export function purgeCacheHook(appKey: string, path?: string){ | |
return async (context: HookContext) => { | |
const cache = context.app.get(appKey) as Cache; | |
if(!cache){ | |
logger.error('Cache not initialized with provided key: ' + appKey); | |
return; | |
} | |
const purgePrefix = path || getPrefix(context); | |
await cache.deletePattern(`${purgePrefix}*`); | |
logger.info({msg: 'Cache purged', prefix: purgePrefix}); | |
return context; | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment