UNPKG

@acuris/leprechaun-cache

Version:

Caching library that supports double checked caching and stale returns to avoid stampede and slow responses

83 lines (75 loc) 2.2 kB
import { CacheStore, CacheItem, Cacheable } from '../types' import { RedisClient } from 'redis' import { v4 as uuidV4 } from 'uuid' function lockKey(key: string): string { return `LOCK-${key}` } export class RedisCacheStore<T extends Cacheable = Cacheable> implements CacheStore<T> { public constructor(private redisClient: RedisClient) {} public get(key: string): Promise<CacheItem<T> | null> { return new Promise<CacheItem<T> | null>((resolve, reject) => { this.redisClient.get(key, (error, result) => { if (error) { reject(error) } if (!result) { resolve(null) } resolve(JSON.parse(result)) }) }) } public set(key: string, data: CacheItem<T>, ttl: number): Promise<boolean> { return new Promise<boolean>((resolve, reject) => { this.redisClient.set(key, JSON.stringify(data), 'PX', ttl, (error, result) => { if (error) { reject(error) } if (result === 'OK') { resolve(true) } resolve(false) }) }) } public del(key: string): Promise<boolean> { return new Promise<boolean>((resolve, reject) => { this.redisClient.del(key, (error, res) => { if (error) { reject(error) } resolve(res > 0) }) }) } public lock(key: string, ttl: number): Promise<string | false> { const lockId = uuidV4() return new Promise<string | false>((resolve, reject) => { this.redisClient.set(lockKey(key), lockId, 'PX', ttl, 'NX', (error, result) => { if (error) { reject(error) } if (result === 'OK') { resolve(lockId) } resolve(false) }) }) } public unlock(key: string, lockId: string): Promise<boolean> { return new Promise((resolve, reject) => { this.redisClient.get(lockKey(key), (error, result) => { if (!error && result && result === lockId) { this.redisClient.del(lockKey(key), err => { if (err) { reject(err) } resolve(true) }) } else { resolve(false) } }) }) } }