Memorarea în cache poate fi un ghimpe în partea oricărui dezvoltator. Am petrecut prea multe ore luptându-mă cu API-uri lente și baze de date supraîncărcate, căutând o soluție care să fie atât eficientă, cât și ușor de implementat.
De aceea am fost încântat când Karol ( karol71927 ), un membru talentat al organizației noastre open-source, Nestixis , a creat @nestixis/cache-manager.
Această bibliotecă ușoară, alimentată de Redis, a simplificat stocarea în cache în proiectele mele NestJS și sunt dornic să vă spun cum a făcut diferența.
Provocarea: complexitatea stocării în cache în NestJS
Scenariul este prea familiar: aplicația dvs. rulează fără probleme până când traficul crește și, brusc, baza de date se blochează sub sarcină. Memorarea în cache este soluția evidentă - stocați datele o dată, serviți-le rapid - dar integrarea lor în NestJS este adesea greoaie. Redis oferă capabilități puternice, dar configurarea acestuia implică, de obicei, configurații dezacordate, gestionarea politicilor de expirare și definirea cheilor de cache personalizate.
Aveam nevoie de un instrument care să simplifice procesul, permițând în același timp control precis asupra a ceea ce este stocat în cache, cum ar fi parametrii de solicitare sau interogările.
Așadar, Karol a conceput @nestixis/cache-manager pentru a aborda aceste puncte dureroase cu o abordare curată și eficientă. Acest pachet oferă un API simplu pentru gestionarea memorării în cache Redis, complet cu TTL-uri configurabile și suport pentru strategii avansate de stocare în cache. Este disponibil la depozitul său GitHub , iar designul său reflectă angajamentul echipei noastre față de instrumente practice și reutilizabile.
Noțiuni introductive: Configurare fără întreruperi
Instalarea este cât se poate de simplă:
npm i @nestixis/cache-manager
Pentru a-l integra în aplicația dvs. NestJS, înregistrați-l într-un modul:
import { Module } from '@nestjs/common'; import { CacheModule } from '@nestixis/cache-manager'; import { ConfigModule, ConfigService } from '@nestjs/config'; @Module({ imports: [ CacheModule.registerAsync({ isGlobal: true, imports: [ConfigModule], useFactory: (configService: ConfigService) => ({ redis: { host: configService.get('REDIS_HOST') || 'localhost', port: +configService.get('REDIS_PORT') || 6379, }, cachePrefix: 'cache:', defaultCacheTTL: 1000, // 1-second default }), inject: [ConfigService], }), ], }) export class AppModule {}
Acest lucru configurează memorarea în cache Redis în aplicația dvs. cu efort minim. De acolo, puteți interacționa manual cu acesta într-un serviciu:
import { Injectable } from '@nestjs/common'; import { CacheManager } from '@nestixis/cache-manager'; @Injectable() export class MyService { constructor(private readonly cacheManager: CacheManager) {} async getData(key: string) { const cached = await this.cacheManager.get(key); if (cached) return cached; const data = await this.fetchData(); await this.cacheManager.add(key, data, 1000); // Cache for 1 second return data; } async clearData(key: string) { await this.cacheManager.remove(key); } private fetchData() { return new Promise((resolve) => setTimeout(() => resolve('Data'), 2000)); } }
Ceea ce diferențiază acest pachet este capacitatea sa de a stoca în cache pe baza detaliilor specifice cererii - o caracteristică inclusă cu grijă Karol. Ia asta
controlor:
import { Controller, Get, Post, Delete, Param, UseInterceptors } from '@nestjs/common'; import { CacheInterceptor, CacheRemoveInterceptor, CacheTrackBy } from '@nestixis/cache-manager'; import { MyService } from './my.service'; @Controller('site/:token') @CacheTrackBy({ prefix: 'site', ttl: 10000, // 10 seconds by: [ { by: 'param', name: 'token', }, ], }) export class SiteController { constructor(private readonly service: MyService) {} @Get() @UseInterceptors(CacheInterceptor) async get(@Param('token') token: string) { return this.service.getData(`site:${token}`); } // Will clear cache on add or remove of resource to keep fresh state @Post() @UseInterceptors(CacheRemoveInterceptor) async add(@Param('token') token: string) { await this.service.getData(`site:${token}`); // Refresh data } @Delete() @UseInterceptors(CacheRemoveInterceptor) async remove(@Param('token') token: string) { await this.service.clearData(`site:${token}`); } }
Decoratorul @CacheTrackBy
este cheia aici. Se asigură că stocarea în cache este legată de parametrul :token, astfel încât /site/abc și /site/xyz primesc fiecare intrarea în cache.
Îl puteți ajusta pentru a utiliza interogări sau alte criterii, oferind flexibilitatea pe care mi-am dorit-o întotdeauna. CacheInterceptor se ocupă de solicitările GET, în timp ce CacheRemoveInterceptor șterge memoria cache la actualizări - elegant și intuitiv.