Skip to content

Instantly share code, notes, and snippets.

@rajeshpillai
Last active March 18, 2025 10:39
Show Gist options
  • Select an option

  • Save rajeshpillai/b3cc78ffabca9be31b5ce0a9bc01e7df to your computer and use it in GitHub Desktop.

Select an option

Save rajeshpillai/b3cc78ffabca9be31b5ce0a9bc01e7df to your computer and use it in GitHub Desktop.
Redis Cache for Node.js
// 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