Skip to content

Instantly share code, notes, and snippets.

@ivanzigoni
Created August 9, 2024 20:08
Show Gist options
  • Save ivanzigoni/7c58b3b9c096724976951290112733e8 to your computer and use it in GitHub Desktop.
Save ivanzigoni/7c58b3b9c096724976951290112733e8 to your computer and use it in GitHub Desktop.
cache interceptor using redis for nestjs
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