Redis
Utilities for Redis-backed caching, distributed locking, and inter-process communication.
Client Creation
import { createRedis, createRedisOptions } from '@zyno-io/ts-server-foundation';
// Create with default config (REDIS_HOST, REDIS_PORT)
const { client, prefix } = createRedis();
// Create with specific config prefix (uses CACHE_REDIS_* and falls back to REDIS_*)
const { client, prefix } = createRedis('CACHE');Each call creates a separate connection and registers it with the current application. app.stop() closes those clients automatically, including clients acquired before a failed startup completes. disconnectAllRedis() remains available for callers that need to release every tracked Redis client before application shutdown.
Availability Alerts
The generic createAvailabilityMonitor() state machine logs one warning when a dependency becomes unavailable, reports one error if the outage lasts past the configured delay, and rearms after recovery. Call unavailable(error?) and available() from any dependency's lifecycle events.
monitorRedisAvailability() is the Redis-specific adapter. It maps ioredis error and reconnecting events to unavailable and ready to available:
import { monitorRedisAvailability } from '@zyno-io/ts-server-foundation';
const monitor = monitorRedisAvailability(client, logger, {
alertAfterMs: config.REDIS_UNAVAILABLE_ALERT_AFTER_MS,
name: 'SSE Redis'
});The default delay is 60 seconds. This changes alert timing only; it does not slow or limit ioredis reconnection attempts.
Sentinel connections keep one subscription to Sentinel's +switch-master notifications so they reconnect as soon as a failover is announced without opening a detector connection to every discovered Sentinel. A READONLY response also forces master resolution and retries the rejected command, covering promotions where the old master socket remains open after becoming a replica.
Cache
Redis-backed cache with TTL support:
import { Cache } from '@zyno-io/ts-server-foundation';
// String values
await Cache.set('key', 'value', 3600); // TTL in seconds
const value = await Cache.get('key');
// Object values (auto JSON serialization)
await Cache.setObj('user:123', { name: 'Alice', role: 'admin' }, 3600);
const user = await Cache.getObj<{ name: string; role: string }>('user:123');| Method | Description |
|---|---|
Cache.get(key) | Get a string value (returns null if missing) |
Cache.set(key, val, ttl) | Set a string value with TTL in seconds |
Cache.getObj<T>(key) | Get and deserialize a JSON value |
Cache.setObj(key, val, ttl) | Serialize and set a JSON value with TTL |
Uses CACHE_REDIS_* environment variables (falls back to REDIS_*).
Distributed Mutex
Redis-backed distributed locking for coordinating work across multiple instances:
import { withMutex, withMutexes, MutexAcquisitionError } from '@zyno-io/ts-server-foundation';
// Single mutex
const result = await withMutex({
key: ['user', userId],
fn: async didWait => {
// Critical section - only one instance executes at a time
// didWait: true if we had to wait for the lock
return await processPayment(userId);
},
retryCount: 30, // Max retry attempts (default: 30)
retryDelay: 1000, // Delay between retries in ms (default: 1000)
renewInterval: 1000 // Lock renewal interval in ms (default: 1000)
});
// Multiple mutexes (acquired in order)
const result = await withMutexes({
keys: [
['resource', resourceA],
['resource', resourceB]
],
fn: async didWait => {
return await updateResources(resourceA, resourceB);
}
});Keys
Mutex keys can be primitives or arrays: ['resource', 123] becomes resource:123.
Error Handling
Throws MutexAcquisitionError if the lock cannot be acquired within the retry window.
Options
| Option | Type | Default | Description |
|---|---|---|---|
key / keys | MutexKey | — | Lock key(s) — string, number, or array |
fn | (didWait: boolean) => Promise<T> | — | Function to execute under lock |
retryCount | number | 30 | Max retry attempts |
retryDelay | number | 1000 | Delay between retries (ms) |
renewInterval | number | 1000 | Lock renewal interval (ms) |
Modes
Configure via MUTEX_MODE:
local(default) — In-process locking with no Redis dependency. Useful for single-instance or testing scenarios.redis— Uses Redis Lua scripts for atomic acquire/release/renew. Suitable for multi-instance deployments.
Uses MUTEX_REDIS_* environment variables (falls back to REDIS_*).
DevConsole Integration
Active mutexes and acquisition history are visible in the DevConsole Mutex view.
Broadcast Channels
Redis pub/sub for inter-process communication:
import { createBroadcastChannel } from '@zyno-io/ts-server-foundation';
// Create a typed broadcast channel
const channel = createBroadcastChannel<{ userId: string; action: string }>('user-events');
channel.subscribe(data => {
console.log(`${data.userId}: ${data.action}`);
});
channel.publish({ userId: '123', action: 'login' });Distributed Methods
Execute a function locally and broadcast to all instances:
import { createDistributedMethod } from '@zyno-io/ts-server-foundation';
class CacheManager {
invalidate = createDistributedMethod<{ key: string }>(
{
name: 'invalidate',
logger: () => this.logger
},
async data => {
this.localCache.delete(data.key);
}
);
}
// Calling invalidate() runs locally AND broadcasts to all instances
await cacheManager.invalidate({ key: 'user:123' });The logger option takes a getter function so it can reference this.logger even when used as a class field initializer. If omitted, a default logger scoped to Distributed:<name> is used.
Uses BROADCAST_REDIS_* environment variables (falls back to REDIS_*).
Configuration
All Redis utilities support independent connection configuration via environment variable prefixes:
| Utility | Env Prefix | Fallback |
|---|---|---|
| Cache | CACHE_REDIS_* | REDIS_* |
| Mutex | MUTEX_REDIS_* | REDIS_* |
| Broadcast | BROADCAST_REDIS_* | REDIS_* |
| Mesh | MESH_REDIS_* | REDIS_* |
| BullMQ | BULL_REDIS_* | REDIS_* |
Common variables for each prefix:
| Variable | Description | Default |
|---|---|---|
*_REDIS_HOST | Redis host | unset |
*_REDIS_PORT | Redis port | 6379 |
*_REDIS_PREFIX | Key prefix | package name |
*_REDIS_SENTINEL_HOST | Redis Sentinel host | unset |
*_REDIS_SENTINEL_PORT | Redis Sentinel port | 26379 |
*_REDIS_SENTINEL_NAME | Redis Sentinel master name | unset |
For the default shared connection, omit the utility prefix and use REDIS_HOST, REDIS_PORT, REDIS_PREFIX, and REDIS_SENTINEL_*.
REDIS_UNAVAILABLE_ALERT_AFTER_MS controls the default outage grace period used with monitorRedisAvailability(). Its default is 60000.