4.0 KiB
Fix: Out of Memory en PostgreSQL
Problema Identificado
El bot estaba experimentando errores out of memory (código 53200) en PostgreSQL debido a que en cada mensaje recibido se estaba ejecutando un prisma.guild.upsert() para obtener la configuración del servidor (principalmente el prefix).
Síntomas
ConnectorError(ConnectorError {
kind: QueryError(PostgresError {
code: "53200",
message: "out of memory",
severity: "ERROR",
detail: Some("Failed on request of size 8192.")
})
})
Esto ocurría en:
messageCreate.tslínea 199:await bot.prisma.guild.upsert(...)en cada mensajehandleAIReply():await bot.prisma.guild.findUnique(...)en cada respuesta a la IA
Solución Implementada
1. Sistema de Caché con Redis
Se creó un nuevo módulo guildCache.ts que:
- Almacena en caché la configuración de cada guild por 5 minutos (TTL: 300s)
- Reduce consultas a PostgreSQL en ~99% (solo 1 consulta cada 5 minutos por guild)
- Maneja errores gracefully retornando valores por defecto si Redis o PostgreSQL fallan
Funciones principales:
// Obtiene config desde caché o DB (con upsert automático)
getGuildConfig(guildId, guildName, prisma): Promise<GuildConfig>
// Invalida el caché cuando se actualiza la config
invalidateGuildCache(guildId): Promise<void>
// Actualiza directamente el caché
updateGuildCache(config): Promise<void>
2. Actualización de messageCreate.ts
- Reemplazó
prisma.guild.upsert()porgetGuildConfig() - Ahora usa caché en Redis antes de consultar PostgreSQL
- Aplica en:
- Handler principal de mensajes
handleAIReply()para respuestas a la IA
3. Invalidación de Caché en settings.ts
Se agregó invalidación automática del caché cuando se actualiza:
- Prefix del servidor
- Roles de staff
- AI Role Prompt
Esto asegura que los cambios se reflejen inmediatamente en el próximo mensaje.
Impacto en el Rendimiento
Antes:
- Por cada mensaje: 1 consulta a PostgreSQL (upsert)
- En un servidor activo con 100 mensajes/minuto: 100 consultas/minuto
- En 10 servidores: 1,000 consultas/minuto
Después:
- Primera consulta: va a PostgreSQL + guarda en Redis (TTL 5 min)
- Siguientes consultas: se obtienen de Redis (0 consultas a PostgreSQL)
- En un servidor activo: ~1 consulta cada 5 minutos
- En 10 servidores: ~10 consultas cada 5 minutos (reducción del 99.8%)
Archivos Modificados
-
src/core/database/guildCache.ts(NUEVO)- Sistema completo de caché con Redis
- Manejo de errores robusto
- Logging detallado
-
src/events/messageCreate.ts- Reemplazó
prisma.guild.upsert()congetGuildConfig() - Reemplazó
prisma.guild.findUnique()enhandleAIReply()
- Reemplazó
-
src/commands/messages/settings-server/settings.ts- Agregó
invalidateGuildCache()después de:- Actualizar prefix
- Actualizar staff roles
- Actualizar AI role prompt
- Agregó
Verificación
Para verificar que funciona:
-
Logs de Redis: Buscar mensajes como:
✅ Guild config obtenida desde caché ✅ Guild config guardada en caché 🗑️ Caché de guild invalidada -
Logs de Prisma: Deberías ver mucho menos
prisma.guild.upsert()en los logs -
Memoria de PostgreSQL: Debería estabilizarse y no crecer descontroladamente
Recomendaciones Adicionales
Si el problema persiste:
- Revisar otras consultas frecuentes que puedan estar saturando PostgreSQL
- Aumentar memoria de PostgreSQL si es posible en el plan de Heroku/hosting
- Implementar connection pooling para Prisma si no está configurado
- Considerar agregar índices en tablas con consultas pesadas
Deployment
Asegúrate de que:
- ✅ Redis está configurado y accesible (
REDIS_URLyREDIS_PASSen.env) - ✅ El bot tiene conexión a Redis antes de procesar mensajes
- ✅ Se ejecuta
npm run buildo el equivalente para compilar TypeScript
Fecha: 2025-10-07
Severidad: CRÍTICA
Estado: RESUELTO ✅