Я недавно начал работать над модулем кэширования для NestJS после того, как столкнулся с теми же проблемами, что и вы.Он доступен на npm в @nestjs-plus/caching
, хотя он еще не готов к использованию, но я поделюсь здесь определением Interceptor.Он полагается на шаблон mixin, чтобы иметь возможность получать данные по маршруту.
import { makeInjectableMixin } from '@nestjs-plus/common';
import {
ExecutionContext,
Inject,
Injectable,
NestInterceptor
} from '@nestjs/common';
import { forkJoin, Observable, of } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
import { Cache, CacheToken } from './cache';
@Injectable()
export abstract class CachingInterceptor implements NestInterceptor {
protected abstract readonly options: CacheOptions;
constructor(@Inject(CacheToken) private readonly cache: Cache) {}
async intercept(
context: ExecutionContext,
call$: Observable<any>
): Promise<Observable<any>> {
const http = context.switchToHttp();
const request = http.getRequest();
const key = this.options.getKey(request);
const cached = await this.cache.get(key);
if (cached != null) {
return of(cached);
}
return call$.pipe(
switchMap(result => {
return forkJoin(
of(result),
this.cache.set(key, result, this.options.ttl)
).pipe(catchError(e => of(result)));
}),
map(([result, setOp]) => result)
);
}
}
export interface CacheOptions {
ttl: number;
getKey: (request) => string;
}
export const makeCacheInterceptor = (options: CacheOptions) => {
return makeInjectableMixin('CachingInterceptor')(
class extends CachingInterceptor {
protected readonly options = options;
}
);
};
export interface Cache {
get: (key: string) => Promise<any | null | undefined>;
set: (key: string, data: any, ttl: number) => Promise<void>;
del: (key: string) => Promise<void>;
}
export const CacheToken = Symbol('CacheToken');
Этот шаблон позволяет применять кэширование для маршрута в ваших контроллерах с различными TTL или методами извлечения ключа кэша из входящего запроса..
@Get()
@UseInterceptors(
makeCacheInterceptor({
getKey: () => '42' // could be req url, query params, etc,
ttl: 5,
}),
)
getHello(): string {
return this.appService.getHello();
}
Единственное, чего здесь не хватает (и библиотеки, над которой я работаю), является гибкий набор реализаций кеша, таких как память, redis, db и т. Д. Я планирую интегрировать с кешем.-manager библиотека, чтобы заполнить этот пробел на этой неделе (это тот же поставщик кеша, который Nest использует для реализации Cache по умолчанию).Не стесняйтесь использовать это в качестве основы для создания своего собственного или следите за обновлениями, когда @nestjs-plus/caching
готов к использованию.Я обновлю этот вопрос позже на этой неделе, когда опубликую готовую производственную версию.