feat(cache): migrar caché de guilds de Redis a Appwrite para mejorar rendimiento y persistencia
This commit is contained in:
124
README/FIX_OUT_OF_MEMORY.md
Normal file
124
README/FIX_OUT_OF_MEMORY.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# 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.ts` línea 199: `await bot.prisma.guild.upsert(...)` en cada mensaje
|
||||
- `handleAIReply()`: `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:
|
||||
```typescript
|
||||
// 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()` por `getGuildConfig()`
|
||||
- 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
|
||||
|
||||
1. **`src/core/database/guildCache.ts`** (NUEVO)
|
||||
- Sistema completo de caché con Redis
|
||||
- Manejo de errores robusto
|
||||
- Logging detallado
|
||||
|
||||
2. **`src/events/messageCreate.ts`**
|
||||
- Reemplazó `prisma.guild.upsert()` con `getGuildConfig()`
|
||||
- Reemplazó `prisma.guild.findUnique()` en `handleAIReply()`
|
||||
|
||||
3. **`src/commands/messages/settings-server/settings.ts`**
|
||||
- Agregó `invalidateGuildCache()` después de:
|
||||
- Actualizar prefix
|
||||
- Actualizar staff roles
|
||||
- Actualizar AI role prompt
|
||||
|
||||
## Verificación
|
||||
|
||||
Para verificar que funciona:
|
||||
|
||||
1. **Logs de Redis**: Buscar mensajes como:
|
||||
```
|
||||
✅ Guild config obtenida desde caché
|
||||
✅ Guild config guardada en caché
|
||||
🗑️ Caché de guild invalidada
|
||||
```
|
||||
|
||||
2. **Logs de Prisma**: Deberías ver **mucho menos** `prisma.guild.upsert()` en los logs
|
||||
|
||||
3. **Memoria de PostgreSQL**: Debería estabilizarse y no crecer descontroladamente
|
||||
|
||||
## Recomendaciones Adicionales
|
||||
|
||||
Si el problema persiste:
|
||||
|
||||
1. **Revisar otras consultas frecuentes** que puedan estar saturando PostgreSQL
|
||||
2. **Aumentar memoria de PostgreSQL** si es posible en el plan de Heroku/hosting
|
||||
3. **Implementar connection pooling** para Prisma si no está configurado
|
||||
4. **Considerar agregar índices** en tablas con consultas pesadas
|
||||
|
||||
## Deployment
|
||||
|
||||
Asegúrate de que:
|
||||
- ✅ Redis está configurado y accesible (`REDIS_URL` y `REDIS_PASS` en `.env`)
|
||||
- ✅ El bot tiene conexión a Redis antes de procesar mensajes
|
||||
- ✅ Se ejecuta `npm run build` o el equivalente para compilar TypeScript
|
||||
|
||||
---
|
||||
|
||||
**Fecha**: 2025-10-07
|
||||
**Severidad**: CRÍTICA
|
||||
**Estado**: RESUELTO ✅
|
||||
Reference in New Issue
Block a user