Created
August 9, 2024 20:08
-
-
Save ivanzigoni/7c58b3b9c096724976951290112733e8 to your computer and use it in GitHub Desktop.
cache interceptor using redis for nestjs
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 {CACHE_MANAGER, Cache} from '@nestjs/cache-manager'; | |
import {Injectable, NestInterceptor, ExecutionContext, CallHandler, Inject, Optional} from '@nestjs/common'; | |
import {Request} from 'express'; | |
import {Observable, of} from 'rxjs'; | |
import {tap} from 'rxjs/operators'; | |
import {CACHE_CONFIG, ONE_DAY_IN_MS} from '../constants'; | |
import {ICacheConfigProvider} from '../interface/cache-config.interface'; | |
@Injectable() | |
export class RedisCacheInterceptor implements NestInterceptor { | |
constructor( | |
@Inject(CACHE_MANAGER) private readonly cacheService: Cache, | |
@Optional() @Inject(CACHE_CONFIG) private readonly cacheConfig: ICacheConfigProvider, | |
) {} | |
private getConfigObject(respondeObject: unknown) { | |
const configObject = this.cacheConfig && this.cacheConfig.getConfig(respondeObject); | |
if (configObject) { | |
return configObject; | |
} | |
const defaultConfig = {shouldCache: true, ttlInMs: ONE_DAY_IN_MS}; | |
return defaultConfig; | |
} | |
async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<unknown>> { | |
const http = context.switchToHttp().getRequest() as Request; | |
const cachedResponse = await this.fetchFromRedis(http); | |
if (cachedResponse) { | |
return of(cachedResponse); | |
} | |
return next.handle().pipe(tap((body) => this.createOnRedis(http.url, body))); | |
} | |
async fetchFromRedis(http: Request) { | |
const cachedResponse = await this.cacheService.get(http.url); | |
if (cachedResponse) { | |
return cachedResponse; | |
} | |
} | |
async createOnRedis(key: string, responseBody: unknown) { | |
const {shouldCache, ttlInMs} = this.getConfigObject(responseBody); | |
if (shouldCache) { | |
await this.saveOnRedis(key, responseBody, ttlInMs); | |
} | |
return responseBody; | |
} | |
async saveOnRedis(key: string, responseBody: unknown, ttlInMs: number) { | |
const ttlObject = this.buildTtl(ttlInMs); | |
return this.cacheService.set(key, responseBody, ttlObject as unknown as number); | |
} | |
buildTtl(ttlInMs: number): {ttl: number} { | |
const ttlInSeconds = ttlInMs / 1000; | |
// tipagem na biblioteca está errada. redis requer ttl em segundos e em objeto | |
// https://stackoverflow.com/questions/75669471/nestjs-cache-manager-taking-global-ttl-value | |
return {ttl: ttlInSeconds}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment