READ-THROUGH

Introduction

  • This article will guide you on implementing READ-THROUGH in NestJS with Redis and Postgres
  • I will also use @nestjs/cache-manager to create an Abstraction layer
  • That is a Cache Interceptor acting as the single source of truth where the app only needs to retrieve data from it. If the cache is unavailable, it will query the Database to fetch data and save it into the cache
  • Regarding the theoretical content, you can review the previous article where I covered it
alt text

Detail

Please install the following packages

bun add cache-manager cache-manager-redis-yet @nestjs/cache-manager

Create file module/cache-manager.module.ts to create CacheManagerModule connecting to Redis. The app will view this as the data source and only fetch data from here

import {CacheModule} from '@nestjs/cache-manager'
import {Module} from '@nestjs/common'
import {ConfigModule, ConfigService} from '@nestjs/config'
import {redisStore} from 'cache-manager-redis-yet'

@Module({
  imports: [
    CacheModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => ({
        store: await redisStore({
          socket: {
            host: configService.get<string>('REDIS_HOST'),
            port: configService.get<number>('REDIS_PORT'),
          },
          ttl: 60000,
        }),
      }),
    }),
  ],
  exports: [CacheModule],
})
export class CacheManagerModule {}

Create file service/product.service.ts

import {CACHE_MANAGER} from '@nestjs/cache-manager'
import {Inject, Injectable} from '@nestjs/common'
import type {Cache} from 'cache-manager'
import {eq} from 'drizzle-orm'
import type {NodePgDatabase} from 'drizzle-orm/node-postgres'
import * as schema from 'src/drizzle-orm/schema/schema'

@Injectable()
export class ProductService {
  constructor(
    @Inject('DRIZZLE_DB') private readonly db: NodePgDatabase<typeof schema>,
    @Inject(CACHE_MANAGER) private readonly cacheManager: Cache
  ) {}

  async getProductById(id: number) {
    const cacheKey = `product:${id}`

    return await this.cacheManager.wrap(
      cacheKey,
      () =>
        this.db
          .select()
          .from(schema.products)
          .where(eq(schema.products.id, id))
          .then(res => res[0]),
      60000
    )
  }
}
  • The function getProductById is implemented following READ-THROUGH. When fetching data with cacheKey, if it is still in the cache, it will return immediately. If it has expired, it will query from the Database
  • The 60000 part is Time To Live (TTL), which is an optional value allowing you to customize it for each individual case

Create file controller/product.controller.ts

import {Controller, Get, Param, ParseIntPipe} from '@nestjs/common'
import {ProductService} from 'src/service/product.service'

@Controller('products')
export class ProductsController {
  constructor(private readonly productService: ProductService) {}

  @Get(':id')
  async getProduct(@Param('id', ParseIntPipe) id: number) {
    return await this.productService.getProductById(id)
  }
}

Modify file app.module.ts

import {Module} from '@nestjs/common'
import {ConfigModule} from '@nestjs/config'
import {ProductsController} from './controller/product.controller'
import {drizzleProvider} from './drizzle-orm'
import {CacheManagerModule} from './module/cache-manager.module'
import {ValkeyModule} from './module/valkey.module'
import {ProductService} from './service/product.service'

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: '.env',
    }),
    ValkeyModule,
    CacheManagerModule,
  ],
  controllers: [
    ProductsController,
  ],
  providers: [
    drizzleProvider,
    ProductService,
  ],
})
export class AppModule {}

As a result, after caching, the response speed will be much faster alt text alt text

Happy coding!

See more articles here.{:target="_target"}

Comments

Popular posts from this blog

All Practice Series

Understanding React Server Component

Kubernetes Deployment for Zero Downtime

Sitemap

Deploying a NodeJS Server on Google Kubernetes Engine

React Practice Series

Docker Practice Series

A Handy Guide to Using Dynamic Import in JavaScript

Setting up Kubernetes Dashboard with Kind

Helm for beginer - Deploy nginx to Google Kubernetes Engine