Skip to main content

MemoryStore & Node Pool

Cachemate abstracts physical Redis instances and in-memory caches into an extensible node pool hierarchy with automatic failover and OOM circuit breaking.

import {
MemoryStore,
NodePool,
RedisNode,
NodeDownError,
NodeOomError,
parseRedisUrlSpec,
type CacheNode,
type RedisUrlSpec,
} from 'cachemate';

MemoryStore

MemoryStore is an in-memory, process-local LRU cache backed by lru-cache with byte-accurate size computation.

const memory = new MemoryStore(128); // 128 MB maximum allocation
await memory.set('key', 'value', 60);
const val = await memory.get('key');
console.log(`Current items: ${memory.size}, Bytes: ${memory.calculatedSize}`);

Methods

MethodReturn TypeDescription
get(key: string)Promise<string | null>Gets the string value for a key.
set(key: string, val: string, ttlSec?: number)Promise<void>Sets a string value with an optional TTL in seconds.
del(key: string)Promise<void>Deletes a key.
mget(keys: string[])Promise<(string | null)[]>Retrieves multiple keys.
incr(key: string)Promise<number>Increments integer counter and returns new value.
clear()voidClears all stored keys in memory.

NodePool

NodePool coordinates active and replica nodes, health checking, and automatic fallback to MemoryStore.

const pool = new NodePool({
redisUrls: ['redis://10.0.0.1:6379', 'redis://10.0.0.2:6379'],
memoryMaxMb: 64,
log: (msg) => console.log(msg),
onActivation: async (node) => {
console.log(`New active node: ${node.url}`);
},
});

await pool.ready();

Properties & Methods

  • pool.isMemoryFallback: boolean: true if all Redis nodes are unreachable and traffic is currently routed to MemoryStore.
  • pool.activeIndex: number: Index of the currently active Redis node in pool.nodes.
  • pool.run<T>(fn: (node: CacheNode) => Promise<T>): Promise<T>: Executes an operation on the active node, automatically advancing to the next node if a NodeDownError or NodeOomError is thrown.
  • pool.close(): Promise<void>: Gracefully terminates connections to all nodes.

Error Classes

NodeDownError

Thrown when a Redis socket connection drops, times out, or fails to connect.

export class NodeDownError extends Error {
public readonly isDown = true;
}

NodeOomError

Thrown when Redis responds with an out-of-memory error (OOM command not allowed when used memory > 'maxmemory').

export class NodeOomError extends Error {
public readonly isOom = true;
}

Custom Node Implementations (CacheNode)

You can create custom caching backends by implementing the CacheNode interface:

export interface CacheNode {
readonly url?: string;
up?: boolean;
connect?(): Promise<boolean>;
get(key: string): Promise<string | null>;
set(key: string, val: string, ttlSec?: number): Promise<void>;
del(key: string): Promise<void>;
mget(keys: string[]): Promise<(string | null)[]>;
incr(key: string): Promise<number>;
close?(): Promise<void>;
}