【问题标题】:I want to implement custom caching in nestjs我想在nestjs中实现自定义缓存
【发布时间】:2019-02-05 05:22:59
【问题描述】:

nsetjs 中的默认缓存机制没有提供足够的灵活性,因为您不能使用 @Cache 指令或类似的东西注释单个 routes/methods

我希望能够设置自定义 ttl 以及我不想缓存每条路由。可能出于此目的将缓存移动到服务级别甚至是有意义的,但还不确定。

只是想知道如何使用 nestjs 框架以更好的方式做到这一点。只是为了缓存一个特定的路由或服务方法。

【问题讨论】:

    标签: typescript nestjs


    【解决方案1】:

    在遇到与您相同的问题后,我最近开始为 NestJS 开发缓存模块。它可以在 npm @nestjs-plus/caching 上找到,虽然它还没有完全准备好使用,但我将在这里分享拦截器定义。它依赖于 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 等。我计划与缓存管理器库集成以填补这一空白本周(它与 Nest 用于默认缓存实现的缓存提供程序相同)。随意将其用作创建您自己的基础或继续关注@nestjs-plus/caching 何时可以使用。我将在本周晚些时候发布一个生产就绪版本时更新这个问题。

    【讨论】:

    • 你知道有什么方法可以使用内置的@CacheTTL装饰器吗?
    猜你喜欢
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 1970-01-01
    相关资源
    最近更新 更多