Greco Cell — Punto de venta
Contexto
Sistema de punto de venta para el cliente personal Greco Cell (telefonía celular). Cliente personal de Sergio, no facturado vía Electrosystems.
Estado real: activo pero sin movimiento reciente. Hay requerimientos pendientes que Sergio quiere reanudar (estado paralelo a deportescampeon).
Tareas pendientes
- #097 📅 2026-06-04 — Recopilar / revisar la lista de requerimientos pendientes del cliente.
- #098 📅 2026-06-06 — Reanudar trabajo activo.
- #095 📅 2026-06-10 — Diagnosticar la razón por la que a veces hay que reiniciar mysql y/o php-fpm.
En progreso
(Nada activo. Proyecto en pausa de facto.)
Notas técnicas
🚨 Runbook: incidente activo (mysql/php-fpm)
Cuando Sergio diga “ya está pasando en grecocell” — leer este bloque y ejecutar en orden. NO reiniciar nada hasta tener el snapshot.
Acceso: ssh grecocell (llave id_rsa_es, user sergio, NOPASSWD para mysql y mysqladmin). Todo lo siguiente es read-only.
Paso 1 — captura inmediata (≤30s):
ssh grecocell '
echo "=== processlist ==="
sudo -n mysql -e "SELECT ID,USER,HOST,DB,COMMAND,TIME,STATE,LEFT(INFO,300) FROM information_schema.processlist WHERE COMMAND NOT IN (\"Sleep\",\"Daemon\") ORDER BY TIME DESC;"
echo "=== innodb status (locks/waits) ==="
sudo -n mysql -e "SHOW ENGINE INNODB STATUS\G" | sed -n "/LATEST DETECTED DEADLOCK\|TRANSACTIONS\|LATEST FOREIGN/,/^---/p" | head -80
echo "=== memoria/io ahora ==="
free -h; echo "---"; vmstat 1 3
echo "=== fpm workers + mysql conn ==="
pgrep -c -f "php-fpm: pool"; ss -ant | awk "\$5 ~ /:3306\$/ || \$4 ~ /:3306\$/ {c++} END {print c+0}"
'
Paso 2 — snapshot histórico (los 10-15 min previos):
ssh grecocell 'tail -20 /var/log/grecocell-snapshot.log'
Buscar: mysql_slow_running subiendo sostenido, fpm cerca de 96, mem_avail_mb cayendo.
Paso 3 — slow log:
ssh grecocell 'sudo -n mysql -e "SELECT start_time, user_host, query_time, lock_time, rows_examined, LEFT(sql_text,400) FROM mysql.slow_log ORDER BY start_time DESC LIMIT 20\G"'
La query culpable casi seguro aparece aquí. Anotar rows_examined y patrón (SELECT ... FROM cortes WHERE fecha BETWEEN ...).
Paso 4 — nginx 504 confirmation (no requiere sudo de Antigravity):
ssh grecocell 'tail -200 /var/log/nginx/access.log 2>/dev/null | awk "\$9 ~ /^5/" | tail -20'
Si los logs son root:adm sin acceso, pedir a Sergio: sudo tail -200 /var/log/nginx/error.log.
Paso 5 — descartar OOM:
Pedir a Sergio (necesita sudo password): sudo dmesg -T | tail -50 | grep -iE "oom|kill|memory".
Paso 6 — decisión de reinicio:
- Si hay query atorada identificada en processlist →
sudo mysqladmin -uroot kill <ID>(mata SOLO esa query, sin reiniciar mysql entero). Workers fpm se desbloquean solos. - Si fpm está pegado pero mysql ya no tiene queries lentas →
sudo systemctl reload php8.3-fpm(más suave que restart). - Si todo lo demás falla → restart mysql (perderemos slow log volátil — exportar antes con paso 3).
Tras estabilizar: dejar correr 15 min más para que snapshot capture el “post-incidente”, luego presentar a Sergio diagnóstico + propuesta de fix permanente (probable: índice missing en cortes.fecha o cortes.sucursal_id).
Stack
- Local: Laravel 11 + Livewire 3 + PHP 8.2 (composer.json). Sail para dev. (Nota previa “Inertia + Vue” del 2026-05-08 estaba incorrecta — es Livewire.)
- Prod (VPS DigitalOcean, host
grecocellen~/.ssh/config, IP24.199.99.50):- Ubuntu 24.10, kernel 6.11.0-29-generic
- MySQL 8.0.42, nginx 1.26.0, PHP 8.3.11-FPM
- 3.8 GB RAM, 0 swap, uptime 292 días (al 2026-05-15)
- App en
/var/www/grecocell, usersergiocon sudo - SSH llave
id_rsa_es
Config relevante de prod (descubierta 2026-05-15)
- PHP-FPM pool (
/etc/php/8.3/fpm/pool.d/www.conf):pm = dynamic,pm.max_children = 96← alto para 3.8 GBpm.start_servers = 6,pm.min/max_spare = 6/19,pm.max_requests = 500- Socket UNIX
/run/php/php8.3-fpm.sock
- MySQL (defaults excepto donde indique):
max_connections = 151,innodb_buffer_pool_size = 128 MB(default)wait_timeout = interactive_timeout = 28800Max_used_connections = 13desde último restart de mysql (~5.6 días) → bajo, sin saturación de conexiones
- nginx: site
/etc/nginx/sites-enabled/grecocell,fastcgi_read_timeoutdefault 60s - Slow query log: activado dinámicamente 2026-05-15 con
long_query_time=1.0,log_output=TABLE,FILE, archivo en/var/lib/mysql/grecocell-slow.log. Cambio volátil — se pierde al reiniciar mysql; pendiente persistir enmysqld.cnfsi la config nos sirve.
Setup de diagnóstico instalado 2026-05-15
- Script
/usr/local/bin/grecocell-snapshot.shcorre cada 60s víagrecocell-snapshot.timer(systemd). - Log
/var/log/grecocell-snapshot.logownersergio:sergio, rotado por logrotate (14 días, compress). - Cada línea registra:
load,mem_used_mb,mem_avail_mb,fpm(workers),mysql_thr_conn,run,mysql_slow_running(queries no-Sleep, no-Daemon, TIME>3),conn3306(TCP only). - Baseline en reposo: load <0.1, fpm=6-12, mysql_thr 1-3, conn3306 7-14, mem_avail ~2.8 GB.
Acceso de Antigravity
- SSH a
grecocellvía~/.ssh/config, llaveid_rsa_es. NOPASSWDconfigurado por Sergio 2026-05-15 paramysqlymysqladmin.- Otros sudo (sed, install, systemctl, journalctl, dmesg, cat de logs root) requieren password — pedir a Sergio cuando haga falta.
Hipótesis de los reinicios mysql/php-fpm
- Síntoma: timeout de nginx (504), generalmente noches a hora de cierre, cuando varias sucursales corren el reporte diario. Pasa de forma errática (antes ~cada 1-2 días, ahora menos tras cambios sin documentar). A veces reiniciar mysql arregla; a veces hay que reiniciar php-fpm.
- Ruta probable:
/cortes/reporte(CortesController::reporte, paginado a 100, filtra por fecha + sucursales conwhereDateywhereIn). - Hipótesis principal (2026-05-15): una query de cortes/reporte ocasionalmente cruza 60s (timeout nginx), no por saturación de conexiones (Max_used_connections=13) sino por single-query lenta posiblemente sin índice apropiado o con N+1 amplificado. Reiniciar mysql mata la query; reiniciar fpm libera workers atorados esperándola. El slow log debería capturar la culpable antes del próximo 504.
- Hipótesis secundaria: memoria —
pm.max_children=96con 3.8 GB y 0 swap es un riesgo si la query se vuelve pesada en RAM (Eloquent + relaciones grandes), pero el patrón de conexiones no la apoya como causa primaria.
Pendiente de documentar aquí
- Lista concreta de requerimientos pendientes del cliente.
Bitácora
2026-05-08
- Pidió Sergio: registrar el proyecto.
- Hice: archivo creado con cliente y status.
- Falta: todo — necesita ser revisitado.
2026-05-15
- Pidió Sergio: preparar todo para diagnosticar los reinicios mysql/php-fpm la próxima vez que pasen — él avisa, yo ya con permisos y contexto listo.
- Hice:
- Inventario completo de stack prod (Ubuntu 24.10, MySQL 8.0.42, PHP 8.3-FPM, nginx 1.26, 3.8 GB RAM sin swap, uptime 292 días).
- Identificada ruta sospechosa:
CortesController::reporte(/cortes/reporte). - Descubierto pool FPM
max_children=96(alto para 3.8 GB) y MySQLMax_used_connections=13(bajo → debilita hipótesis de saturación). - A. Slow query log activado dinámicamente (
long_query_time=1.0,log_output=TABLE,FILE, archivo en/var/lib/mysql/grecocell-slow.log). Volátil — se pierde al reiniciar mysql. - B. Snapshot cada 60s instalado:
/usr/local/bin/grecocell-snapshot.sh+ systemd timergrecocell-snapshot.timer+ logrotate. Log en/var/log/grecocell-snapshot.log(owner sergio:sergio, lo leo sin sudo). Captura: load, mem, fpm workers, mysql threads, slow_running, conn3306. Verificado funcionando con baseline limpio. - C. NOPASSWD para mysql/mysqladmin configurado por Sergio para que yo pueda correr
SHOW PROCESSLIST/SHOW ENGINE INNODB STATUSsin esperarlo. - Plan de diagnóstico documentado en sección “Notas técnicas” arriba.
- Falta:
- Esperar al próximo incidente. Sergio avisa.
- Si la config nos sirve tras el primer incidente, persistir slow log en
/etc/mysql/mysql.conf.d/mysqld.cnf. - Acciones correctivas (índices, tuning, swap, bajar
max_children, etc.) — solo después de tener evidencia del slow log + snapshot.