Last active
March 18, 2025 10:39
-
-
Save rajeshpillai/b3cc78ffabca9be31b5ce0a9bc01e7df to your computer and use it in GitHub Desktop.
Redis Cache for Node.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // cache/baseCache.js | |
| // This is our abstract base class defining the contract for our cache implementations. | |
| class BaseCache { | |
| async get(key) { | |
| throw new Error('Method "get" must be implemented'); | |
| } | |
| async set(key, value, ttl) { | |
| throw new Error('Method "set" must be implemented'); | |
| } | |
| async del(key) { | |
| throw new Error('Method "del" must be implemented'); | |
| } | |
| } | |
| module.exports = BaseCache; | |
| // cache/in_memory_cache.js | |
| require('dotenv').config(); | |
| const BaseCache = require('./baseCache'); | |
| const DEFAULT_TTL = process.env.CACHE_DEFAULT_TTL | |
| ? parseInt(process.env.CACHE_DEFAULT_TTL, 10) | |
| : 60; | |
| class InMemoryCache extends BaseCache { | |
| constructor(defaultTTL = DEFAULT_TTL) { | |
| super(); | |
| this.store = new Map(); | |
| this.defaultTTL = defaultTTL; | |
| } | |
| async get(key) { | |
| const record = this.store.get(key); | |
| if (!record) return null; | |
| // Check if expired | |
| if (record.expireAt && record.expireAt < Date.now()) { | |
| this.store.delete(key); | |
| return null; | |
| } | |
| return record.value; | |
| } | |
| async set(key, value, ttl) { | |
| ttl = ttl || this.defaultTTL; | |
| const expireAt = ttl ? Date.now() + ttl * 1000 : null; | |
| this.store.set(key, { value, expireAt }); | |
| } | |
| async del(key) { | |
| return this.store.delete(key); | |
| } | |
| } | |
| module.exports = InMemoryCache; | |
| // cache/redis_cache.js | |
| require('dotenv').config(); | |
| const Redis = require('ioredis'); | |
| const BaseCache = require('./baseCache'); | |
| const DEFAULT_TTL = process.env.CACHE_DEFAULT_TTL | |
| ? parseInt(process.env.CACHE_DEFAULT_TTL, 10) | |
| : 60; | |
| class RedisCache extends BaseCache { | |
| constructor(defaultTTL = DEFAULT_TTL) { | |
| super(); | |
| this.defaultTTL = defaultTTL; | |
| this.client = new Redis(process.env.REDIS_URL); | |
| this.client.on('error', (err) => { | |
| console.error('Redis error:', err); | |
| }); | |
| } | |
| async get(key) { | |
| return await this.client.get(key); | |
| } | |
| async set(key, value, ttl) { | |
| ttl = ttl || this.defaultTTL; | |
| if (ttl) { | |
| await this.client.set(key, value, 'EX', ttl); | |
| } else { | |
| await this.client.set(key, value); | |
| } | |
| } | |
| async del(key) { | |
| await this.client.del(key); | |
| } | |
| } | |
| module.exports = RedisCache; | |
| // cache/index.js | |
| require('dotenv').config(); | |
| const InMemoryCache = require('./inMemoryCache'); | |
| const RedisCache = require('./redisCache'); | |
| // Choose Redis in production; otherwise use in-memory cache. | |
| const cache = process.env.NODE_ENV === 'production' | |
| ? new RedisCache() | |
| : new InMemoryCache(); | |
| module.exports = cache; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment