[NestJS] Cache Me if You Can มาลองทำ Caching ด้วย NestJS กัน
Caching เป็นเทคนิคพื้นฐานที่ใช้บ่อย ถูกใช้อยู่ในหลายๆส่วนทั้งในการระบบ network อย่าง Proxy server หรือเรียกกันว่า cache server หรือแม้การทำ Web cache ที่ช่วยให้โหลดหน้าเว็บเก็บไว้ที่ memory ของ browser ซึ่งทั้งหมดนี้สามารถช่วยให้ประสิทธิภาพการใช้งานของแอปพลิเคชันนั้นมีความรวดเร็วขึ้น มันเป็นการเก็บข้อมูลชั่วคราวเอาไว้ที่ data store เพื่อการเข้าถึงข้อมูลเดิมที่ถูกเรียกบ่อยๆได้อย่างรวดเร็ว ทั้งยังลด workload ในการไป query ข้อมูลจาก database อีกด้วย แต่สำหรับบทความนี้จะพูดการ cache เมื่อมีการเรียกใช้ API เท่านั้นด้วย NestJS
สร้างแอปพลิเคชันอย่างง่ายๆเพื่อให้เข้าใจแนวคิดและวิธีใช้ จะลองทำไปทีละขั้นตอน
1. สร้างโปรเจค
ติดตั้ง nestjs/cli ด้วยคำสั่ง
Npm i -g @nestjs/cli
Generate โปรเจคใหม่ขึ้นมาด้วยคำสั่ง
nest new you_project_name
2. ติดตั้ง Package
Npm install cache-manager
Npm install -D @tyles/cache-manager
3. Register CacheModule
// app.module.ts
4. Inject CacheManager
ใน Controller ของ NestJs เป็นที่รู้กันว่าจะเป็น ตัวสร้าง Rest API ดังนั้นให้กำหนด @Get(‘in-memory) เป็น Path เพื่อทดสอบ Request และ สร้าง Data ขึ้นมาหนึ่งตัวสำหรับทดสอบในที่นี้ผู้เขียนตั้งชื่อตัวแปรว่า fakeDB ประกาศให้เป็น String มีค่าคือ sklsongkiat
จากนั้นให้ Inject module เข้าไปใน Constructure เพื่อเรียกใช้ cache module
จากนั้นมาทำ Get กับ Set ค่า Key ลง data store จาก instance ที่ชื่อ cacheManager
Method ของ get cache นั้น จะ Return เป็น Promise ดังนั้นจะต้องทำ async/await จึงได้ โดยจะต้องกำหนด key ในที่นี้ผู้เขียน ตั้งชื่อว่า ‘name’
โดยที่จะทดสอบว่า มีการเก็บค่า key name นี้หรือไม่ กำหนดการ check ว่า value ที่ได้นั้นถ้ามีให้ return ว่า In-memory Cache
แล้วถ้าไม่มีล่ะ ก็ให้ return ค่า Fake Database ซะ
แต่เดี๋ยวก่อน ยังไม่ได้ set ค่า key name เลยจะไปมีได้อย่างไร ดังนั้นจะต้องใช้ method set ค่าที่กำหนดไว้เริ่มต้น และตั้งเวลาหมดอายุการ cache ไว้ที่ 30 วินาที
จาก code ทั้งหมดที่ได้อธิบายไปนำมาประกอบจะได้ตามด้านล่างนี้
// app.controller.ts
import { Controller, Inject, CACHE_MANAGER, Get } from '@nestjs/common';
import { Cache } from 'cache-manager';
@Controller()
export class AppController {
fakeDB: string = "sklsongkiat";
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) { }
@Get('in-memory')
async getFromMemoryCache() {
let value = await this.cacheManager.get('name');
if (value) {
return {
dataFrom: 'In-memory Cache',
name: value
}
}
await this.cacheManager.set('name', this.fakeDB, { ttl: 30 });
return {
dataFrom: "Fake Database",
name: this.fakeDB
}
}
}
เมื่อนำมาทดสอบด้วย PostMan
Request ครั้งที่ 1 สั่งเกตได้ว่า ได้ค่าจาก Return ตัวแปรตั้งต้น
Request ครั้งที่ 2 จะได้จาก Cache เพราะถูก set ตัวแปรตั้งต้นที่มีค่า sklsongkiat เข้าไปแล้ว
Request ครั้งที่ 3 หลังจาก 30 วินาที จะเห็นว่าค่าที่ได้จะได้จาก Fake Database
ผู้อ่านอาจจะยังไม่เชื่อ คิดว่าผู้เขียนเอารูปเดิมมาให้ดูหรือเปล่า แบบนี้ต้องลองดูครับ
Ref:
https://docs.nestjs.com/techniques/caching
https://www.learmoreseekmore.com/2020/11/nestjs-inmemory-cache.html