Redis
Overview
@modularityjs/redis provides a shared ioredis client used by all Redis-backed drivers (cache-redis, lock-redis, queue-redis). It manages the connection lifecycle — connecting during boot and disconnecting on shutdown.
It is kind shared, not a contract: RedisService is concrete, and getClient() returns ioredis's own Redis type. Consumers use the full client surface — pipelines, Lua eval, streams, pub/sub — so no abstract could describe it that a different client library could satisfy. There is one implementation by construction, and nothing to swap. Wire RedisModule once; every *-redis driver injects RedisService from it rather than opening its own connection.
Setup
import { RedisModule } from '@modularityjs/redis';
const modules = [
RedisModule.forRoot({
url: process.env.REDIS_URL, // e.g. redis://localhost:6379
}),
// ... Redis drivers
];The url is required — there is no localhost fallback. Boot fails with a ValidationException (MJS0015) until an explicit redis:// or rediss:// URL is passed.
Configuration
| Option | Default | Description |
|---|---|---|
url | required | Connection URL (redis://… / rediss://…); carries host, port, credentials, and db |
keyPrefix | 'modularityjs:' | Prefix for all keys (used by drivers, not ioredis) |
lazyConnect | true | Defer connection until onInit |
commandTimeoutMs | 5000 | Per-command timeout (ioredis commandTimeout, 0 disables) |
maxRetriesPerRequest | - | ioredis per-request retry cap |
Key Prefixing
All Redis drivers build keys using the pattern:
{RedisConfig.keyPrefix}{driver namespace}{key}For example, with default config:
- Cache key
user:1becomesmodularityjs:cache:user:1 - Lock key
payment:123becomesmodularityjs:lock:payment:123 - Queue stream
ordersbecomesmodularityjs:queue:stream:orders
The prefix is not passed to ioredis's keyPrefix option (which breaks Lua scripts). Instead, each driver builds the full key manually for consistency across all Redis commands including eval.
Lifecycle
onInit— connects to Redis. If the connection fails, boot fails immediately.onShutdown— gracefully disconnects viaQUIT.
Direct Access
Inject RedisService for custom Redis operations beyond what the framework drivers provide:
import { Inject, Injectable } from '@modularityjs/di';
import { RedisService } from '@modularityjs/redis';
@Injectable()
class LeaderboardService {
constructor(@Inject(RedisService) private readonly redis: RedisService) {}
async addScore(userId: string, score: number): Promise<void> {
const client = this.redis.getClient();
await client.zadd('leaderboard', score, userId);
}
async getTopPlayers(count: number): Promise<string[]> {
const client = this.redis.getClient();
return client.zrevrange('leaderboard', 0, count - 1);
}
}getClient() returns the raw ioredis Redis instance. The global keyPrefix from RedisConfig is not applied automatically to direct client calls -- build keys manually when needed.
Environment Configuration
RedisModule does not register a ConfigSchemaPool entry and does not read from ConfigService. To configure Redis from environment variables, the consumer must read process.env (or query ConfigService against its own schema) and pass the value to RedisModule.forRoot({...}):
RedisModule.forRoot({
url: process.env.REDIS_URL, // redis://user:pass@redis.prod.internal:6379/0
});