Skip to content

Object caching for Node.js with LRU and Redis backends. Wraps async functions with automatic key generation and request deduplication.

License

Notifications You must be signed in to change notification settings

vnykmshr/obcachejs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

obcachejs

npm version CI License Node

Object caching for Node.js. Wraps async functions and caches results with automatic key generation.

Features

  • LRU in-memory cache with TTL support
  • Optional Redis backend for distributed caching
  • Request deduplication (prevents thundering herd)
  • Promise and callback APIs
  • TypeScript definitions included

Installation

npm install obcachejs

Requires Node.js 18+

Quick Start

const obcache = require('obcachejs');

const cache = new obcache.Create({ max: 1000, maxAge: 60000 });

const getUser = cache.wrap(function(id, callback) {
  // Simulate async database lookup
  setTimeout(() => callback(null, { id, name: 'User ' + id }), 10);
});

// Promise style
const user = await getUser(123);
console.log(user); // { id: 123, name: 'User 123' }

// Callback style
getUser(456, (err, user) => console.log(user));

API

obcache.Create(options)

Creates a cache instance.

const cache = new obcache.Create({
  max: 1000,           // max keys (default: 1000)
  maxAge: 60000,       // TTL in ms
  queueEnabled: true   // deduplicate concurrent requests
});

Options:

Option Description
max Maximum number of cached keys
maxSize Maximum cache size in bytes (alternative to max)
maxAge Time-to-live in milliseconds
queueEnabled Enable request deduplication
dispose Function called when entries are evicted
reset.interval Auto-reset interval in ms
reset.firstReset First reset time (Date or ms)

cache.wrap(fn, [thisobj], [skipArgs])

Wraps a callback-based function with caching. The wrapped function:

  • Returns a Promise when called without a callback
  • Calls the callback when provided as last argument
  • Generates cache keys from function name and arguments
const cached = cache.wrap(myAsyncFn);

// Exclude arguments from key generation
const cached = cache.wrap(function(id, timestamp, cb) {
  // timestamp won't affect cache key
  cb(null, result);
}, null, [1]);

cache.warmup(fn, ...args, value)

Pre-populate cache for given arguments.

cache.warmup(getUser, 123, { id: 123, name: 'Alice' });

cache.invalidate(fn, ...args)

Remove cached entry for given arguments.

cache.invalidate(getUser, 123);

cache.isReady()

Returns true when cache backend is ready. Always true for LRU, waits for connection with Redis.

cache.stats

Cache statistics object.

{
  hit: 0,      // cache hits
  miss: 0,     // cache misses
  reset: 0,    // number of resets
  pending: 0   // queued requests
}

Redis Backend

const cache = new obcache.Create({
  max: 10000,
  maxAge: 300000,
  id: 1,  // required for Redis
  redis: {
    host: 'localhost',
    port: 6379,
    connectTimeout: 5000
  }
});

// Wait for connection
if (!cache.isReady()) {
  // handle not ready
}

Redis options:

Option Description
host Redis host
port Redis port
url Connection URL (alternative to host/port)
database Redis database number
connectTimeout Connection timeout in ms (default: 5000)
twemproxy Enable twemproxy compatibility

Debug Interface

Register caches for inspection:

obcache.debug.register(cache, 'users');

// Express middleware
app.get('/debug/cache', obcache.debug.view);

// Console output
obcache.debug.log();

Security Warning: The debug endpoint exposes cached data via ?detail=cachename and allows cache flushing via POST with ?flush=cachename. Never expose this endpoint publicly. Always protect it with authentication middleware:

app.get('/debug/cache', requireAdmin, obcache.debug.view);

How It Works

obcachejs generates cache keys by hashing the function name and serialized arguments using sigmund. When a wrapped function is called:

  1. Generate key from function name + arguments
  2. Check cache for existing value
  3. On hit: return cached value
  4. On miss: call original function, cache result, return

With queueEnabled, concurrent calls with the same key are queued and resolved together, preventing duplicate work.

TypeScript

Type definitions are included.

const obcache = require('obcachejs');
// or with ES modules: import obcache from 'obcachejs';

const cache = new obcache.Create({ max: 100 });

Types available: Cache, CacheOptions, CacheStats, CachedFunction.

Security

  • Redis authentication: Use the url option with credentials: redis://user:pass@host:port
  • Secrets: Never cache sensitive data (tokens, passwords, PII) without encryption
  • Network: Use TLS for Redis in production (rediss:// protocol)
  • Eviction: Cached data persists until TTL expires or LRU evicts; plan accordingly

Report security issues via GitHub issues with [SECURITY] prefix.

License

BSD-3-Clause

About

Object caching for Node.js with LRU and Redis backends. Wraps async functions with automatic key generation and request deduplication.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 8