使用注解为Nestjs service层加上缓存

1,963 阅读1分钟

Nestjs自己在controller上已经实现了缓存.却缺乏对service的结果缓存.

下面我们自己通过注解的方式来为service加上缓存.

参考 文章

1. 准备工作

依赖

  • ioredis
  • type-cacheable

命令

npm install type-cacheable
npm install ioredis
npm install @types/ioredis

2.缓存模块

// redis-cache.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { useIoRedisAdapter } from 'type-cacheable';
import IORedis from 'ioredis';

@Injectable()
export class RedisCacheConfigurationMapper {
  public static map(): IORedis.RedisOptions {
    return {
      lazyConnect: true,
      host: process.env.REDIS_URL || 'localhost',
      port: Number(process.env.REDIS_PORT) || 6379,
      db: 7,
    };
  }
}

@Injectable()
export class RedisCacheService implements OnModuleInit {
  private redisInstance: IORedis.Redis | undefined;

  public async onModuleInit(): Promise<void> {
    try {
      if (this.isAlreadyConfigured()) {
        return;
      }
      this.redisInstance = new IORedis(RedisCacheConfigurationMapper.map());
      
      this.redisInstance.on('error', (e: Error) => {
        this.handleError(e);
      });
      useIoRedisAdapter(this.redisInstance);
      await this.redisInstance?.connect();
    } catch (e) {
      this.handleError(e as Error);
    }
  }

  private handleError(e: Error): void {
    console.error('Could not connect to Redis cache instance', e);
  }

  private isAlreadyConfigured(): boolean {
    return this.redisInstance !== undefined;
  }
}

3.增加provider

// app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { OperationLogModule } from '@/modules/operation-log/operation-log.module';
import { UserModule } from '@/modules/user/user.module';
import { JwtGuard } from '@/guards/jwt.guard';
import { APP_GUARD } from '@nestjs/core';
import { RedisCacheService } from '@/common/redis-cache.service';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      entities: ['test/**/*.entity{.ts,.js}', 'src/**/*.entity{.ts,.js}'],
      subscribers: ['src/**/*.subscriber{.ts,.js}'],
      url: process.env.DATABASE_URL || 'postgres://localhost:5432/nest-demo',
      synchronize: true,
      logging: true,
    }),
    OperationLogModule,
    UserModule,
  ],
  providers: [
    {
      provide: APP_GUARD,
      useClass: JwtGuard,
    },
    RedisCacheService,
  ],
})
export class AppModule {
}

4.使用注解缓存结果

// user.service.ts
 @Cacheable({ttlSeconds:CacheTtlSeconds.ONE_WEEK,cacheKey:'users'})
  async findAll(){
    return this.repo.find()
  }

  @Cacheable({ttlSeconds:CacheTtlSeconds.ONE_DAY,cacheKey:args => `user_${args[0]}`})
  async findOne(id){
    return this.repo.findOne(id)
  }

5. 清除缓存

@CacheClear({cacheKey:args => `user_${args[0]}`})
  async updateOne(id,dto){
    console.long('清除缓存')
    return id;
  }

Git地址

github.com/taozhiyuzhu…