Class

CacheService

CacheService()

Constructor

# new CacheService()

Cache service with adapter pattern for flexible backend support.

CacheService provides a unified caching API that works with multiple backends (InMemory, Redis, Datadog) via adapter pattern. It's used at two levels:

  1. HTTP Layer: Via cacheHandler() middleware for route-level caching
  2. Service Layer: Via withCacheable() mixin for method-level caching with entity rehydration

Adapter Requirements: All adapters must implement this interface:

interface CacheAdapter {
  get(key: string): Promise<any>;
  set(key: string, value: any, ttl?: number): Promise<void>;
  del(keys: string | string[]): Promise<void>;
  keys(): Promise<string[]>;
}

Cache Key Generation: Keys are deterministic - same parameters always generate same key regardless of order:

cache.getCacheKey('icons', { page: 1, limit: 10 });
cache.getCacheKey('icons', { limit: 10, page: 1 });
// Both produce: 'icons:a1b2c3d4e5f6...'

Performance Characteristics:

  • InMemory: ~0.01ms per operation (development/testing)
  • Redis: ~1-5ms per operation (production, network overhead)
  • Datadog: ~10-50ms per operation (observability, write-heavy)

View Source src/common/cache/CacheService.js, line 102

Examples
// Development setup with InMemory adapter
const NodeCache = require('node-cache');
const cache = new CacheService(new NodeCacheAdapter(new NodeCache()));
// Production setup with Redis adapter
const redis = require('redis');
const client = await redis.createClient({
  url: process.env.REDIS_URL,
  socket: { reconnectStrategy: (retries) => Math.min(retries * 50, 500) }
}).connect();
const cache = new CacheService(new RedisAdapter(client));
// HTTP route caching
app.get('/api/icons/:id',
  cache.cacheHandler('icons:detail', async (req) => {
    return iconService.getById(req.params.id);
  }, 3600)
);
// Service-level caching (automatic with withCacheable mixin)
class IconService extends withCacheable(BaseService) {
  // All methods like getById() are automatically cached
}

Methods

# cacheHandler(baseKey, handler, ttlopt) → {function}

Express/Fastify middleware for automatic request caching.

Supports cache modes via query parameter ?cacheMode=skip|bust|refresh:

  • DEFAULT: Return cached data if available, otherwise fetch and cache
  • SKIP: Bypass cache, always fetch fresh data
  • BUST: Clear cache entry, fetch fresh data, don't re-cache
  • REFRESH: Clear cache entry, fetch fresh data, cache the result

The middleware automatically:

  • Generates cache keys from request parameters
  • Includes user ID in cache key if authenticated
  • Adds fromCache: true/false to response
  • Handles errors with next()
Parameters:
Name Type Attributes Default Description
baseKey string

Base cache key for this route

handler function

Async function that returns data: async (req) => data

ttl number <optional>
kCACHE_DEFAULT_TTL

Time-to-live in seconds

View Source src/common/cache/CacheService.js, line 318

Express/Fastify middleware function

function
Examples
// Basic usage
app.get('/api/icons',
  cache.cacheHandler('icons:list', async (req) => {
    return iconService.getAll(req.query);
  }, 3600)
);
// Client can control cache behavior:
// GET /api/icons?cacheMode=skip    - Always fresh
// GET /api/icons?cacheMode=bust    - Clear and fetch
// GET /api/icons?cacheMode=refresh - Update cache
// With authentication
app.get('/api/favorites',
  authenticate,
  cache.cacheHandler('favorites', async (req) => {
    return favoriteService.getUserFavorites(req.user.id);
  })
);
// Cache key includes user.id automatically

# async clearCache(optionsopt) → {Promise.<number>}

Clears cache entries by base key prefix or custom matcher function.

Useful for cache invalidation when data changes:

  • Clear all keys with a specific prefix
  • Clear keys matching custom criteria
  • Clear all keys (no parameters)
Parameters:
Name Type Attributes Default Description
options Object <optional>
{}

Clearing options

baseKey string <optional>

Clear all keys starting with this prefix

matcher function <optional>

Custom function to filter keys: (key) => boolean

View Source src/common/cache/CacheService.js, line 404

Number of keys cleared

Promise.<number>
Examples
// Clear all icon-related cache entries
await cache.clearCache({ baseKey: 'icons' });
// Clears: icons:list, icons:detail:*, etc.
// Clear with custom matcher
await cache.clearCache({
  matcher: (key) => key.includes('user:123')
});
// Clear all cache entries
await cache.clearCache();
// Clear after data update
await iconService.updateIcon(id, data);
await cache.clearCache({ baseKey: 'icons' });

# getCacheKey(baseKey, paramsopt, userIdopt) → {string}

Generates a consistent cache key from base key, parameters, and user ID.

Keys are generated by:

  1. Sorting parameter keys alphabetically
  2. Serializing values (objects sorted by keys)
  3. Appending user ID if provided
  4. Hashing the combined string with MD5

This ensures the same parameters always generate the same key, regardless of parameter order.

Parameters:
Name Type Attributes Default Description
baseKey string

The base cache key (e.g., 'users:list', 'products:detail')

params Object <optional>
{}

Query parameters or options

userId number | string <optional>
null

User ID for user-specific caching

View Source src/common/cache/CacheService.js, line 254

Hashed cache key in format 'baseKey:hash'

string
Examples
const key1 = cache.getCacheKey('icons', { page: 1, limit: 10 });
const key2 = cache.getCacheKey('icons', { limit: 10, page: 1 });
// key1 === key2 (order doesn't matter)
// User-specific caching
const key = cache.getCacheKey('favorites', { page: 1 }, userId);
// Returns: 'favorites:abc123def456...'
// With object parameters
const key = cache.getCacheKey('search', {
  filters: { category: 'icons', style: 'outline' },
  sort: 'name'
});

CacheService(adapter)

Constructor

# new CacheService(adapter)

Construct CacheService with cache adapter.

The adapter pattern allows swapping cache backends without changing application code. Common adapters include:

  • NodeCacheAdapter: In-memory caching for development/testing
  • RedisAdapter: Production-ready distributed caching
  • DatadogAdapter: Metrics collection and observability

Adapter Interface: All adapters must implement: get(), set(), del(), keys()

Parameters:
Name Type Description
adapter Object

Cache adapter implementing required interface

get function

Retrieve value by key: async get(key: string) => any

set function

Store value with optional TTL: async set(key: string, value: any, ttl?: number) => void

del function

Delete one or more keys: async del(keys: string | string[]) => void

keys function

List all keys: async keys() => string[]

View Source src/common/cache/CacheService.js, line 206

If adapter is invalid or missing required methods

Error
Examples
// InMemory adapter for development
const cache = new CacheService(new NodeCacheAdapter());
// Redis adapter for production
const redisClient = redis.createClient({ url: process.env.REDIS_URL });
await redisClient.connect();
const cache = new CacheService(new RedisAdapter(redisClient));
// Custom adapter implementation
class CustomAdapter {
  async get(key) { return null; }
  async set(key, value, ttl) { return; }
  async del(keys) { return; }
  async keys() { return []; }
}
const cache = new CacheService(new CustomAdapter());

Methods

# cacheHandler(baseKey, handler, ttlopt) → {function}

Express/Fastify middleware for automatic request caching.

Supports cache modes via query parameter ?cacheMode=skip|bust|refresh:

  • DEFAULT: Return cached data if available, otherwise fetch and cache
  • SKIP: Bypass cache, always fetch fresh data
  • BUST: Clear cache entry, fetch fresh data, don't re-cache
  • REFRESH: Clear cache entry, fetch fresh data, cache the result

The middleware automatically:

  • Generates cache keys from request parameters
  • Includes user ID in cache key if authenticated
  • Adds fromCache: true/false to response
  • Handles errors with next()
Parameters:
Name Type Attributes Default Description
baseKey string

Base cache key for this route

handler function

Async function that returns data: async (req) => data

ttl number <optional>
kCACHE_DEFAULT_TTL

Time-to-live in seconds

View Source src/common/cache/CacheService.js, line 318

Express/Fastify middleware function

function
Examples
// Basic usage
app.get('/api/icons',
  cache.cacheHandler('icons:list', async (req) => {
    return iconService.getAll(req.query);
  }, 3600)
);
// Client can control cache behavior:
// GET /api/icons?cacheMode=skip    - Always fresh
// GET /api/icons?cacheMode=bust    - Clear and fetch
// GET /api/icons?cacheMode=refresh - Update cache
// With authentication
app.get('/api/favorites',
  authenticate,
  cache.cacheHandler('favorites', async (req) => {
    return favoriteService.getUserFavorites(req.user.id);
  })
);
// Cache key includes user.id automatically

# async clearCache(optionsopt) → {Promise.<number>}

Clears cache entries by base key prefix or custom matcher function.

Useful for cache invalidation when data changes:

  • Clear all keys with a specific prefix
  • Clear keys matching custom criteria
  • Clear all keys (no parameters)
Parameters:
Name Type Attributes Default Description
options Object <optional>
{}

Clearing options

baseKey string <optional>

Clear all keys starting with this prefix

matcher function <optional>

Custom function to filter keys: (key) => boolean

View Source src/common/cache/CacheService.js, line 404

Number of keys cleared

Promise.<number>
Examples
// Clear all icon-related cache entries
await cache.clearCache({ baseKey: 'icons' });
// Clears: icons:list, icons:detail:*, etc.
// Clear with custom matcher
await cache.clearCache({
  matcher: (key) => key.includes('user:123')
});
// Clear all cache entries
await cache.clearCache();
// Clear after data update
await iconService.updateIcon(id, data);
await cache.clearCache({ baseKey: 'icons' });

# getCacheKey(baseKey, paramsopt, userIdopt) → {string}

Generates a consistent cache key from base key, parameters, and user ID.

Keys are generated by:

  1. Sorting parameter keys alphabetically
  2. Serializing values (objects sorted by keys)
  3. Appending user ID if provided
  4. Hashing the combined string with MD5

This ensures the same parameters always generate the same key, regardless of parameter order.

Parameters:
Name Type Attributes Default Description
baseKey string

The base cache key (e.g., 'users:list', 'products:detail')

params Object <optional>
{}

Query parameters or options

userId number | string <optional>
null

User ID for user-specific caching

View Source src/common/cache/CacheService.js, line 254

Hashed cache key in format 'baseKey:hash'

string
Examples
const key1 = cache.getCacheKey('icons', { page: 1, limit: 10 });
const key2 = cache.getCacheKey('icons', { limit: 10, page: 1 });
// key1 === key2 (order doesn't matter)
// User-specific caching
const key = cache.getCacheKey('favorites', { page: 1 }, userId);
// Returns: 'favorites:abc123def456...'
// With object parameters
const key = cache.getCacheKey('search', {
  filters: { category: 'icons', style: 'outline' },
  sort: 'name'
});