การตั้งค่าใช้งาน Redis ใน NestJS ง่าย ๆ

Oct. 29, 2024 · boychawin

ในบทความนี้จะพามาการตั้งค่า Redis ใน NestJS ด้วยการใช้ไลบรารี ioredis พร้อมการอธิบายแนวทางการตั้งค่าครับ

1. ตั้งค่า Config สำหรับ Redis

เริ่มต้นจากการสร้างไฟล์ redis.config.ts โดยใช้ registerAs เพื่อดึงค่าจาก .env และใช้ในโปรเจกต์ เราจะตั้งค่าเช่น host, port, cacheKey (ใช้แทน password ของ Redis) และ ciphers (ใช้สำหรับการเชื่อมต่อแบบ TLS)

// redis.config.ts
import { registerAs } from '@nestjs/config';

interface IRedisEnv {
  HOSTNAME: string;
  PORT: string;
  CACHE_KEY: string;
  CIPHERS: string;
}

const configRedis: IRedisEnv = process.env.REDIS
  ? JSON.parse(process.env.REDIS)
  : {};

export default registerAs('redis', () => ({
  host: configRedis.HOSTNAME,
  port: configRedis.PORT,
  cacheKey: configRedis.CACHE_KEY,
  ciphers: configRedis.CIPHERS,
}));

export interface IRedis {
  host: string;
  port: string;
  cacheKey: string;
  ciphers: string;
}

2. สร้าง Redis Module

ในไฟล์ redis.module.ts เราจะตั้งค่า Factory สำหรับ Redis instance และลงทะเบียนการเชื่อมต่อกับ NestJS โดยใช้ ConfigService เพื่อดึงค่าจาก config ที่ตั้งไว้

// redis.module.ts
import { Global, Logger, Module, OnApplicationShutdown } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { ModuleRef } from '@nestjs/core';
import { RedisKey } from './redis.constants';
import Redis from 'ioredis';
import { RedisService } from './redis.service';
import { IRedis } from './redis.config';

@Global()
@Module({
  providers: [
    {
      provide: RedisKey,
      useFactory: async (configService: ConfigService) => {
        const logger = new Logger('Redis');
        const redisConfig = configService.get<IRedis>('redis');
        const redis = new Redis({
          host: redisConfig.host,
          port: Number(redisConfig.port),
          password: redisConfig.cacheKey,
          db: 0,
          tls: redisConfig.ciphers
            ? {
                minVersion: 'TLSv1.2',
                ciphers: redisConfig.ciphers,
              }
            : undefined,
          retryStrategy(times) {
            const delay = Math.min(times * 50, 2000);
            return delay;
          },
        });
        redis.on('connect', () => {
          logger.log('Connected.');
        });
        redis.on('error', (err) => {
          logger.error('Failed to connect to Redis.', err);
        });
        redis.on('connecting', () => {
          logger.debug(
            `Attempting to connect to Redis at ${redis.options.host}:${redis.options.port}`,
          );
        });
        return redis;
      },
      inject: [ConfigService],
    },
    RedisService,
  ],
  exports: [RedisService],
})
export class RedisModule implements OnApplicationShutdown {
  constructor(private readonly moduleRef: ModuleRef) {}
  async onApplicationShutdown() {
    const redis: Redis = this.moduleRef.get(RedisKey);
    redis.disconnect();
  }
}

3. การใช้งาน Redis ใน Service

ใน redis.service.ts เราจะสร้างฟังก์ชัน set และ get สำหรับการบันทึกและเรียกค่าจาก Redis

// redis.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { RedisKey } from './redis.constants';
import Redis from 'ioredis';

@Injectable()
export class RedisService {
  constructor(
    @Inject(RedisKey)
    private readonly redis: Redis,
  ) {}

  async set(
    key: string,
    value: string | number | Buffer,
    expire?: number,
  ): Promise<string> {
    if (expire) {
      return this.redis.set(key, value, 'EX', expire);
    }
    return this.redis.set(key, value);
  }

  async get(key: string): Promise<string> {
    return this.redis.get(key);
  }
}

4. การนำไปใช้งานใน

สุดท้าย เพื่อทดสอบการใช้งาน Redis เช่น การตรวจสอบข้อมูล หากยังไม่มีใน Redis จะเพิ่มข้อมูลใหม่

...
  constructor(
    ...,
    private readonly redisService: RedisService
  ) { }

  @Get()
  async testRedis() {
    const key = 'testData';
    const data = await this.redisService.get(key);
    if (!data) {
      await this.redisService.set(key, JSON.stringify({ message: 'Hello Redis!' }));
      return 'Data set in Redis!';
    }
    return `Data found: ${data}`;
  }

สรุป

การตั้งค่า Redis ใน NestJS ด้วย ioredis ไม่ยากอย่างที่คิด แค่เราแยกขั้นตอนและตั้งค่าชัดเจน ทั้งยังสามารถดึงข้อมูลไปใช้ใน Service และ Controller ได้อย่างง่ายดาย