Colas Híbridas & Orquestación Horizon
Mañuti implementa un modelo de procesamiento asíncrono híbrido que combina la velocidad de Redis 7.0 como broker de mensajería en memoria con la persistencia relacional de MariaDB para la auditoría de fallos y el seguimiento de lotes. La orquestación y telemetría de estos workers es gobernada por Laravel Horizon.
1. Topología del Sistema Híbrido
En arquitecturas de alto rendimiento, delegar el almacenamiento de colas completas a MySQL mediante bloqueos de fila (SELECT ... FOR UPDATE) provoca contención de base de datos. Por otro lado, usar Redis exclusivamente para registrar errores implica pérdida de trazabilidad si la memoria se recicla.
Mañuti resuelve esta disyuntiva segregando responsabilidades:
flowchart TD
REQ["[Petición Web / Controlador]"]
REDIS["Redis (Memoria RAM)<br/>(Cola de Tránsito / Streaming)"]
WORKER["Procesamiento del Trabajo"]
FAIL["[MariaDB: failed_jobs]<br/>(Historial Inmutable)"]
BATCH["[MariaDB: job_batches]<br/>(Estado Atómico Transaccional)"]
REQ -->|"1. Dispatch(Job) en microsegundos"| REDIS
REDIS -->|"2. Worker Horizon consume y procesa"| WORKER
WORKER -->|"(Si falla N veces)"| FAIL
WORKER -->|"(Progreso de Lote)"| BATCH
2. Configuración del Núcleo (config/queue.php & .env)
El archivo .env establece las conexiones correspondientes:
# Broker de mensajería de colas en tránsito
QUEUE_CONNECTION=redis
# Driver persistente para registrar excepciones definitivas
QUEUE_FAILED_DRIVER=database-uuids
En config/queue.php, el seguimiento de lotes se ancla a MariaDB:
'batching' => [
'database' => env('DB_CONNECTION', 'mysql'),
'table' => 'job_batches',
],
'failed' => [
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
'database' => env('DB_CONNECTION', 'mysql'),
'table' => 'failed_jobs',
],
3. Configuración y Balanceo en Horizon (config/horizon.php)
Para optimizar recursos en producción, Horizon implementa la estrategia de Auto-Balancing, creando y destruyendo workers de forma elástica según el volumen de la cola:
// config/horizon.php
'environments' => [
'production' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default', 'auditoria', 'imports', 'exports'],
'balance' => 'auto', // Ajuste dinámico de procesos
'minProcesses' => 2,
'maxProcesses' => 10,
'balanceMaxShift' => 1,
'balanceCooldown' => 3,
'tries' => 3,
'timeout' => 120, // Timeout en segundos por Job
],
],
],
4. Demonio de Sistema (/etc/supervisor/conf.d/horizon.conf)
Supervisor vigila al maestro de Horizon para garantizar que la cola nunca quede desatendida tras un reinicio del sistema operativo o fallo de memoria:
[program:horizon]
process_name=%(program_name)s
command=/usr/bin/php /var/www/framedev12/artisan horizon
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/framedev12/storage/logs/horizon.log
stopwaitsecs=3600
Nota sobre stopwaitsecs=3600: Este parámetro otorga hasta 1 hora a los workers en ejecución para completar trabajos largos pendientes antes de forzar su terminación (Graceful Shutdown).
5. Control de Acceso al Dashboard de Horizon (RBAC)
El acceso a la interfaz web /horizon no utiliza autenticación básica HTTP ni contraseñas estáticas en .env. Se integra de forma nativa con el sistema de RBAC Aditivo y Permisos:
- Se define el permiso
horizon.viewen la tablapermissions. - Se asocia al rol
Super Admin. - El
HorizonServiceProviderevalúa la capacidad antes de autorizar el renderizado del dashboard:
// app/Providers/HorizonServiceProvider.php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Laravel\Horizon\HorizonApplicationServiceProvider;
class HorizonServiceProvider extends HorizonApplicationServiceProvider
{
protected function gate(): void
{
Gate::define('viewHorizon', function ($user) {
return $user->can('horizon.view');
});
}
}
// config/horizon.php
'middleware' => ['web', 'auth', 'auditar:acceso_horizon'],