Redis
Configuracao do Redis com ioredis, Docker, cache, sessoes e integracao automatica com BullMQ.
O Redis e configurado automaticamente pelo PlazerCLI quando voce seleciona features que dependem dele (BullMQ, rate limiting, sessoes) ou quando voce o habilita diretamente. O PlazerCLI usa o ioredis como client por sua robustez, suporte a cluster e reconnect automatico.
O Redis e auto-habilitado quando voce escolhe BullMQ, Rate Limiting ou WebSockets com adapter Redis. Voce nao precisa seleciona-lo manualmente nesses casos.
Docker Compose
O PlazerCLI adiciona o servico Redis ao docker-compose.yml:
# docker-compose.yml
services:
redis:
image: redis:7-alpine
container_name: ${PROJECT_NAME}-redis
ports:
- '6379:6379'
volumes:
- redis_data:/data
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 10s
timeout: 5s
retries: 5
volumes:
redis_data:
Modulo Redis (NestJS)
No NestJS, o PlazerCLI gera um modulo global com provider ioredis:
// apps/api/src/redis/redis.module.ts
import { Global, Module } from '@nestjs/common';
import { RedisService } from './redis.service';
@Global()
@Module({
providers: [RedisService],
exports: [RedisService],
})
export class RedisModule {}
// apps/api/src/redis/redis.service.ts
import { Injectable, OnModuleDestroy } from '@nestjs/common';
import Redis from 'ioredis';
@Injectable()
export class RedisService extends Redis implements OnModuleDestroy {
constructor() {
super({
host: process.env.REDIS_HOST || 'localhost',
port: Number(process.env.REDIS_PORT) || 6379,
password: process.env.REDIS_PASSWORD || undefined,
maxRetriesPerRequest: null,
retryStrategy: (times) => Math.min(times * 50, 2000),
});
}
async onModuleDestroy() {
await this.quit();
}
}
Cache helper
O PlazerCLI gera um helper de cache reutilizavel:
// apps/api/src/redis/cache.helper.ts
import { RedisService } from './redis.service';
export class CacheHelper {
constructor(private readonly redis: RedisService) {}
async get<T>(key: string): Promise<T | null> {
const data = await this.redis.get(key);
return data ? JSON.parse(data) : null;
}
async set(key: string, value: unknown, ttlSeconds = 3600): Promise<void> {
await this.redis.set(key, JSON.stringify(value), 'EX', ttlSeconds);
}
async del(key: string): Promise<void> {
await this.redis.del(key);
}
async invalidatePattern(pattern: string): Promise<void> {
const keys = await this.redis.keys(pattern);
if (keys.length > 0) {
await this.redis.del(...keys);
}
}
}
// Uso em um service:
@Injectable()
export class UsersService {
private cache: CacheHelper;
constructor(private redis: RedisService) {
this.cache = new CacheHelper(redis);
}
async findById(id: string) {
const cached = await this.cache.get(`user:${id}`);
if (cached) return cached;
const user = await this.prisma.user.findUnique({ where: { id } });
await this.cache.set(`user:${id}`, user, 1800); // 30 min
return user;
}
}
Express / Fastify
Nos frameworks Express e Fastify, o Redis e exportado como singleton:
// apps/api/src/lib/redis.ts
import Redis from 'ioredis';
export const redis = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: Number(process.env.REDIS_PORT) || 6379,
password: process.env.REDIS_PASSWORD || undefined,
maxRetriesPerRequest: null,
});
redis.on('error', (err) => console.error('Redis error:', err));
redis.on('connect', () => console.log('Redis connected'));
// Uso em qualquer rota:
import { redis } from '../lib/redis';
app.get('/api/products/:id', async (req, res) => {
const cached = await redis.get(`product:${req.params.id}`);
if (cached) return res.json(JSON.parse(cached));
const product = await db.product.findUnique({ where: { id: req.params.id } });
await redis.set(`product:${req.params.id}`, JSON.stringify(product), 'EX', 3600);
res.json(product);
});
Variaveis de ambiente
| Variavel | Padrao | Descricao |
|---|---|---|
REDIS_HOST | localhost | Host do servidor Redis |
REDIS_PORT | 6379 | Porta do servidor Redis |
REDIS_PASSWORD | (vazio) | Senha do Redis (opcional em dev) |