promcache
v2.1.7
Published
**PromCache** โมดูลสำหรับการทำ LRU cache แบบ asynchronous
Readme
PromCache โมดูลสำหรับการทำ LRU cache แบบ asynchronous
ถ้า key ที่อ่าน มีค่าอยู่ใน cache จะส่งคืนค่าทันที แต่ถ้าไม่มีจะส่งคืนค่าเป็น promise object ของ key ดังกล่าวเสมอ (ซึ่งจะ resolve ภายหลังจากที่ค่าตัวแปรมาถึง) ในขณะเดียวกันก็เรียกฟังก์ชั่น fetFunction ต่อ เพื่อโหลดค่าจากแหล่งข้อมูล เพื่อมา resolve promise และเก็บค่าไว้ใน cache
การสร้าง cache object
const PromCache = require("promcache");
let promcache = new PromCache({
max: 500,
maxAge: 60*1000
});การเรียกใช้ข้างต้น จะใช้ memory เป็น cache หากต้องการใช้ redis เป็น cache อีกชั้นนึงก็สามารถผ่าน redis object เข้าไปได้เลย cache ทั้งสองตัวจะทำงานพร้อมกัน module จะพยายามดึงค่าจาก memory cache ก่อน หากไม่พบจึงจะไปดึงจาก redis และสุดท้าย หากไม่มีค่าจริงๆ จึงจะเรียกจาก fetch function และนำกลับมาก cache ที่ redis และ memory เราสามารเซต max และ maxAge ของ redis ได้โดยการเซตฟิวด์ redisMax และ redisMaxAge
const PromCache = require("promcache");
const Redis = require('ioredis');
let redis = new Redis();
let promcache = new PromCache({
max: 500,
maxAge: 60*1000,
redis: redis,
// redisMax : 1000,
// redisMaxAge : 60000,
// namespace : "myapp"
});หากไม่ต้องการให้ promise ถูก cache หลังจาก resolve สามารถเซต resetAfterResolved เป็น true
const PromCache = require("promcache");
const Redis = require('ioredis');
let redis = new Redis();
let promcache = new PromCache({
max: 500,
maxAge: 60*1000,
resetAfterResolved: true
});และหากไม่ต้องการให้ promise อัพเดตค่าลง redis สามารถเซต redisReadOnly เป็น true ได้ จะมีประโยชน์ในกรณีที่เรามี 2 process ใช้ redis cache ร่วมกัน แต่ต้องการให้มีแค่ process เดียวเท่านั้นที่อัพเดตค่าบน redis
const PromCache = require("promcache");
const Redis = require('ioredis');
let redis = new Redis();
let promcache = new PromCache({
max: 500,
maxAge: 60*1000,
redisReadOnly: true
});การเรียกใช้
การอ่านค่าจาก cache
promcache.get(cache_key, fetch_function [,param]);cache_key เป็น string ค่า key ของ cache
fetch_function(callback [, param]) เป็นฟังก์ชั่นที่จะถูกเรียกเมื่อ cache ไม่มีค่า ไว้ใช้ใส่โค้ดส่วนของการอ่านค่า เมื่อทุกอย่างเสร็จ ให้ callabck กลับด้วยค่าที่ได้มา ค่านี้จะถูกนำไป cache ตามเงื่อนไขเวลาที่กำหนด
param เป็น object ที่ต้องการจะ pass เข้าไปใน fetch_function โดยปกติ ถ้าเขียนเป็น nested function อาจจะไม่จำเป็นต้องใช้
การลบค่าจาก cache จะลบพร้อมกันทั้งบน memory cache และ redis cache
promcache.del(cache_key);- cache_key เป็น string ค่า key ของ cache
cache key สามารถเขียนเป็น pattern ที่ติด wildcard * ได้ เช่น
promcache.del('home:*:temp');คำสั่งข้างบนจะลบ cache ที่มี key ต่อไปนี้
- home:bedroom:temp
- home:kitchen:temp
ตัวอย่าง
let uid = 'u1234'
let value = await promcache.get(`user:${uid}`, (callback) => {
call_async_remote_api(uid).then( (val) => {
callback(val);
}
});สามารถคุมได้ว่าจะ cache หรือไม่ ถ้าไม่ cache ให้ส่ง parameter ที่ 2 เป็น false
let value = await promcache.get(`user:${uid}`, (callback) => {
call_async_remote_api().then( (val) => {
callback(val, false);
}
});สามารถส่งผ่าน parameter จากข้างนอกได้ หากต้องการ
let value = await promcache.get(`user:u1234`, (callback, arg) => {
call_async_remote_api(arg.uid).then( (val) => {
callback(val, false);
}
}, {uid: 'u1234'});การสร้าง mock promcache object เพื่อทำ dependency injection ใน unit test โดยการ create โดยไม่ต้องตั้ง option แบบนี้
const PromCache = require("promcache");
let promcache = new PromCache();promcache object ที่ได้ จะมีฟังก์ชั่นเหมือนเดิมทุกอย่าง เพียงแต่จะไม่มีการ cache ใดๆทั้งสิ้น
การ retry fetch function
การเรียก remote function บางครั้งอาจมี time out เกิดขึ้นแบบไม่คาดฝันจากปัจจัยที่ควบคุมไม่ได้ เพื่อที่จะรับมือกับความไม่แน่นอนนั้น เราสามารถบอก promcache ให้มีการ retry หาก callback failed ด้วยการ set up promcache ในลักษณะนี้
let promcache = new PromCache({
max: 500,
maxAge: 60*1000,
attempt: 5,
minFetchRetryWaitTime: 1000,
maxFetchRetryWaitTime: 4000
});- retry คือจำนวนครั้งที่จะทำซ้ำ ค่า default เป็น 0 คือไม่ retry
- minRetryWaitTime จำนวนวินาทีต่ำสุดที่จะรอก่อน retry (default คือ 1000)
- maxRetryWaitTime จำนวนวินาทีสูงสุดที่จะรอก่อน retry โดยการ retry ครั้งแรก จะรอเป็นระยะ minWaitTime ก่อน หากไม่สำเร็จ จะทำซ้ำด้วยการรอด้วยระยะเวลา 2 เท่าของค่าเดิม และทำเช่นนี้ไปเรื่อยๆ แต่จะไม่เกิน maxWaitTime (default คือ 16000)
การบ่งบอกว่า remote function failed ทำได้ด้วยการเรียก callback โดยไม่ส่งกลับ parameter
ตัวอย่าง
let uid = 'u1234'
let value = await promcache.get(`user:${uid}`, (callback) => {
call_async_remote_api(uid).then( (val) => {
callback(val);
}.catch(e) {
callback();
}
});