VOOZH about

URL: https://dev.to/sur-ser/implementing-idempotency-with-nestjs-redisx-a-practical-guide-2d9p

⇱ Implementing Idempotency with NestJS RedisX: A Practical Guide - DEV Community


Handling duplicate requests in APIs, especially in payment systems, is a headache. NestJS RedisX offers a neat way to tackle this with its Idempotency Plugin. Let’s dig into how you can set this up.

Getting Started with Idempotency

First things first, install the necessary packages. You'll need both the core and idempotency packages of NestJS RedisX:

npm install @nestjs-redisx/core @nestjs-redisx/idempotency

Configuring the Module

To make the Idempotency Plugin work its magic, you need to configure it in your main module. This setup ensures that the plugin is ready to catch any duplicate requests globally.

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { RedisModule } from '@nestjs-redisx/core';
import { IdempotencyPlugin } from '@nestjs-redisx/idempotency';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { IdempotencyInterceptor } from '@nestjs-redisx/idempotency';

@Module({
 imports: [
 ConfigModule.forRoot(),
 RedisModule.forRootAsync({
 imports: [ConfigModule],
 inject: [ConfigService],
 plugins: [
 IdempotencyPlugin.registerAsync({
 imports: [ConfigModule],
 inject: [ConfigService],
 useFactory: (config: ConfigService) => ({
 defaultTtl: 86400, // 24 hours
 headerName: 'Idempotency-Key',
 }),
 }),
 ],
 useFactory: (config: ConfigService) => ({
 clients: {
 host: config.get('REDIS_HOST', 'localhost'),
 port: config.get('REDIS_PORT', 6379),
 },
 }),
 }),
 ],
 providers: [
 { provide: APP_INTERCEPTOR, useClass: IdempotencyInterceptor },
 ],
})
export class AppModule {}

Decorating Your Endpoints

Once your module is good to go, use the @Idempotent decorator on your endpoints. This ensures that each request is uniquely processed based on the Idempotency-Key.

import { Controller, Post, Body } from '@nestjs/common';
import { Idempotent } from '@nestjs-redisx/idempotency';

@Controller('payments')
export class PaymentsController {
 constructor(private readonly paymentService: PaymentService) {}

 @Post()
 @Idempotent()
 async createPayment(@Body() dto: CreatePaymentDto) {
 return this.paymentService.process(dto);
 }
}

Behind the Scenes

Here’s the lowdown: the Idempotency Plugin checks each request’s Idempotency-Key. If it’s seen the key before, it serves the cached result. No re-processing, no fuss.

  • Body Fingerprinting: It goes a step further by ensuring the request body’s fingerprint matches the key. This prevents using the same key for different data.
  • Concurrent Handling: If multiple requests with the same key pop up, the plugin handles them in sequence, avoiding any duplication.

Incorporating an idempotency layer using NestJS RedisX is pretty straightforward. It's a solid way to dodge duplicate processing in sensitive areas like payments. Want to dive deeper? Check out the official documentation.