
# Trabajadores

Los trabajadores son procesos de larga duración que consultan la base de datos en busca de trabajos pendientes, los ejecutan y hacen avanzar los flujos de trabajo. El comando `wp queuety work` se ejecuta dentro de WP-CLI, mientras que la cola se reclama directamente desde MySQL mediante el mejor controlador de base de datos Queuety disponible.

El plugin también instala una alternativa predeterminada WordPress cron que se ejecuta una vez por minuto para entornos sin acceso al shell. Esta página trata sobre los trabajadores WP-CLI dedicados, que son el modo de despliegue recomendado para lograr un mayor rendimiento.

## Iniciar un trabajador

```bash
wp queuety work
```

Esto inicia un único trabajador en la cola `default`. Se ejecuta en bucle: reclama un trabajo, lo ejecuta y repite el proceso. Cuando la cola está vacía, espera `QUEUETY_WORKER_SLEEP` segundos (valor predeterminado: 1) antes de volver a consultarla.

### Opciones

| Opción | Descripción |
|---|---|
| `--queue=<queue>` | Queue(s) que se procesarán; sepárelas con comas para ordenarlas por prioridad (valor predeterminado: `default`) |
| `--once` | Procesa como máximo un trabajo y sale |
| `--workers=<n>` | Crea N procesos de trabajadores (requiere las extensiones `pcntl` y `posix`) |
| `--min-workers=<n>` | Número mínimo de trabajadores para un grupo adaptable. Requiere `--max-workers` |
| `--max-workers=<n>` | Número máximo de trabajadores para un grupo adaptable |

```bash
# Process a specific queue
wp queuety work --queue=emails

# Process at most one job and exit
wp queuety work --once

# Run 4 concurrent workers
wp queuety work --workers=4

# Scale between 2 and 6 workers as backlog changes
wp queuety work --queue=providers --min-workers=2 --max-workers=6
```

## Prioridades de varias colas

Un solo trabajador puede procesar varias colas en orden de prioridad. Pase una lista de nombres de cola separados por comas a `--queue`:

```bash
wp queuety work --queue=critical,default,low
```

El trabajador intenta reclamar un trabajo de cada cola en el orden indicado. Primero comprueba `critical`. Si `critical` tiene un trabajo, lo procesa. Si `critical` está vacía, pasa a `default` y luego a `low`. Así, las colas de mayor prioridad siempre se vacían antes que las de menor prioridad.

### Cómo funciona el orden de prioridad

En cada iteración, el trabajador intenta reclamar un trabajo de la primera cola de la lista. Si esa cola está vacía o en pausa, pasa a la siguiente y continúa hasta encontrar un trabajo o agotar la lista. Si no encuentra ningún trabajo, espera y vuelve a intentarlo. Este modelo de prioridad estricta significa que un flujo constante de trabajos `critical` dejará sin atender los trabajos `default` y `low`. Si necesita garantizar el rendimiento de las colas de menor prioridad, use trabajadores dedicados.

### Uso de varias colas en PHP

Los métodos `Worker::run()` y `Worker::flush()` aceptan una cadena o una matriz:

```php
// Comma-separated string
Queuety::worker()->run( 'critical,default,low' );

// Array
Queuety::worker()->run( [ 'critical', 'default', 'low' ] );

// flush() also supports multi-queue
$count = Queuety::worker()->flush( 'critical,default,low' );
```

### Estrategias de despliegue

**Los trabajadores dedicados por cola** le dan control total sobre la concurrencia y el aislamiento. Cada cola tiene su propio trabajador process(es) y no puede quedarse sin atención por culpa de otras colas:

```ini
[program:queuety-critical]
command=wp queuety work --queue=critical
numprocs=4

[program:queuety-default]
command=wp queuety work --queue=default
numprocs=2

[program:queuety-low]
command=wp queuety work --queue=low
numprocs=1
```

**El orden de prioridad con un solo trabajador** es más fácil de gestionar y funciona bien cuando las colas de menor prioridad pueden tolerar retrasos:

```ini
[program:queuety-worker]
command=wp queuety work --queue=critical,default,low
numprocs=2
```

También puede combinar ambos enfoques: trabajadores dedicados para `critical` que garanticen el rendimiento y un trabajador ordenado por prioridad para todo lo demás:

```ini
[program:queuety-critical]
command=wp queuety work --queue=critical
numprocs=2

[program:queuety-fallback]
command=wp queuety work --queue=default,low
numprocs=2
```

## Admisión según los recursos disponibles

Los trabajadores hacen más que reclamar la siguiente fila pendiente. Antes de iniciar un trabajo reclamado, Queuety puede aplicar comprobaciones generales de admisión basadas en el grupo de concurrencia del trabajo y el perfil de ejecución reciente de ese controlador.

Para consultar el modelo general, incluido cómo se relaciona con los metadatos de los trabajos y los presupuestos de los flujos de trabajo, vea [Gestión de recursos](https://queuety.inline0.dev/es/docs/features/resource-management).

Un grupo de concurrencia establece un límite compartido para varios controladores o clases de trabajos. Si asigna el mismo grupo y límite a varios proveedores que requieren muchos recursos, el trabajador liberará el trabajo recién reclamado en lugar de iniciarlo cuando el grupo alcance el límite. Así, las colas independientes no saturan un mismo sistema posterior solo porque haya varios trabajadores inactivos.

Los registros de ejecución recientes también alimentan un perfil de admisión sencillo. Cuando la admisión según los recursos está activada, Queuety consulta la duración media reciente y la memoria máxima del controlador que va a ejecutar. Si el trabajador actual está cerca de su límite de memoria configurado, un grupo de colas o proveedores ya alcanzó su presupuesto ponderado, el contenedor actual no parece tener suficiente memoria disponible para el perfil observado del controlador, o una ejecución del tipo `--once` está cerca de agotar su tiempo disponible, Queuety aplaza el trabajo en vez de iniciar una tarea que probablemente no terminará correctamente.

La política se activa desde la definición del trabajo, no desde el comando del trabajador:

```php
class CallProviderStep implements \Queuety\Step {
    public function handle( array $state ): array {
        // ...
    }

    public function config(): array {
        return [
            'concurrency_group' => 'providers',
            'concurrency_limit' => 3,
            'cost_units' => 5,
        ];
    }
}
```

Se pueden adjuntar los mismos metadatos a clases de trabajos que admitan despacho mediante propiedades públicas o a un despacho individual a través de `PendingJob::concurrency_group()` y `PendingJob::cost_units()`.

El perfil de admisión del trabajador se controla con estas constantes:

| Constante | Descripción |
|---|---|
| `QUEUETY_RESOURCE_ADMISSION` | Activa o desactiva las comprobaciones de admisión basadas en perfiles |
| `QUEUETY_RESOURCE_PROFILE_WINDOW_MINUTES` | Periodo que se consulta para crear perfiles recientes de controladores |
| `QUEUETY_RESOURCE_PROFILE_TTL` | Tiempo de vida en caché de los perfiles recientes de controladores |
| `QUEUETY_RESOURCE_MEMORY_HEADROOM_MB` | Reserva de memoria antes de admitir otro trabajo |
| `QUEUETY_RESOURCE_SYSTEM_MEMORY_AWARENESS` | Activa o desactiva las comprobaciones aproximadas de memoria del contenedor o del host |
| `QUEUETY_RESOURCE_SYSTEM_MEMORY_HEADROOM_MB` | Reserva de memoria del sistema antes de admitir otro trabajo |
| `QUEUETY_RESOURCE_QUEUE_COST_BUDGETS` | Presupuestos de coste ponderado por nombre de cola |
| `QUEUETY_RESOURCE_GROUP_COST_BUDGETS` | Presupuestos de coste ponderado por `concurrency_group` |
| `QUEUETY_RESOURCE_TIME_HEADROOM_MS` | Reserva de tiempo para ejecuciones de trabajadores de una sola ejecución |

## Ciclo de vida del trabajador

Un trabajador se detiene correctamente, una vez terminado el trabajo actual, cuando se cumple alguna de estas condiciones:

| Condición | Configuración |
|---|---|
| Número máximo de trabajos procesados | `QUEUETY_WORKER_MAX_JOBS` (valor predeterminado: 1000) |
| Memoria máxima superada | `QUEUETY_WORKER_MAX_MEMORY` (valor predeterminado: 128 MB) |

Tras detenerse, el trabajador sale correctamente. En producción, un gestor de procesos lo reinicia automáticamente.

Las señales aún no se gestionan correctamente ([#4](https://github.com/inline0/queuety/issues/4)). Un proceso `wp queuety work` individual no instala ningún controlador de señales, por lo que `SIGTERM` o `SIGINT` (Ctrl+C) lo termina de inmediato, incluso en mitad de un trabajo. El trabajo queda `processing` hasta que la recuperación de trabajos obsoletos lo restablece después de `QUEUETY_STALE_TIMEOUT` segundos, así que asegúrese de que los controladores puedan volver a intentarse sin riesgo. Un grupo de trabajadores reenvía `SIGTERM` a sus procesos secundarios, pero estos no actúan al recibirla, por lo que el grupo sigue ejecutándose hasta que se detengan por uno de los motivos anteriores. Para detener un grupo, configure el gestor de procesos con un tiempo de espera para la detención, tras el cual enviará `SIGKILL`.

## Concurrencia de varios trabajadores

La opción `--workers=N` crea N procesos secundarios mediante `pcntl_fork()`. Cada proceso secundario crea su propia conexión a la base de datos y procesa trabajos de forma independiente. El proceso principal supervisa los procesos secundarios y reinicia los que se bloqueen.

```bash
wp queuety work --queue=default --workers=4
```

Requisitos:
Deben estar instaladas las extensiones `pcntl` y `posix` PHP (sin `pcntl`, el comando falla con «pcntl extension is required for --workers=N.»). Cada proceso secundario usa su propia conexión a la base de datos, por lo que la configuración de MySQL `max_connections` debe admitir todo el grupo. Los grupos adaptables (`--min-workers`/`--max-workers`) tienen los mismos requisitos.

## Grupos adaptables de trabajadores

Los grupos adaptables mantienen activos un número mínimo de trabajadores y luego aumentan o reducen su número dentro del intervalo configurado:

```bash
wp queuety work --queue=providers --min-workers=2 --max-workers=6
```

El proceso principal supervisa el volumen de trabajos reclamables del conjunto de colas seleccionado y ajusta el número de procesos secundarios para adaptarse a ese volumen, sin superar el máximo configurado. Cuando disminuye la actividad de la cola, el grupo espera el periodo de gracia por inactividad antes de reducir su tamaño, para evitar que los picos breves provoquen cambios constantes en la lista de procesos.

El aumento de escala sigue siendo prudente. Cuando Queuety puede consultar la telemetría de memoria del contenedor o del host, no añade más procesos secundarios si no queda memoria suficiente para otro trabajador completo.

El bucle de escalado del proceso principal se controla con:

| Constante | Descripción |
|---|---|
| `QUEUETY_WORKER_POOL_SCALE_INTERVAL` | Frecuencia con la que el proceso principal ajusta el tamaño del grupo |
| `QUEUETY_WORKER_POOL_IDLE_GRACE` | Tiempo que el volumen de trabajos debe permanecer bajo antes de reducir el tamaño |

## Recuperación de trabajos obsoletos

Si un trabajador se bloquea mientras procesa un trabajo, este queda en estado `processing`. Un trabajador de larga duración comprueba aproximadamente una vez por minuto si hay trabajos que llevan más de `QUEUETY_STALE_TIMEOUT` segundos en estado `processing`. Los trabajos obsoletos que aún tengan intentos disponibles se vuelven a intentar tras el periodo de espera configurado; los que ya agotaron sus intentos quedan enterrados y su flujo de trabajo se marca como fallido. Los trabajadores `--once` y la alternativa WP-Cron no realizan esta comprobación.

Recupere manualmente los trabajos obsoletos:

```bash
wp queuety recover
```

## Modo de vaciado

Procesa todos los trabajos pendientes y sale. Es útil para pruebas o para procesar lotes una sola vez:

```bash
wp queuety flush
wp queuety flush --queue=emails
```

## Despliegue en producción

En producción, use un gestor de procesos para mantener los trabajadores en ejecución. Aquí tiene dos opciones habituales.

### Supervisord

```ini
[program:queuety-default]
command=wp queuety work --queue=default
directory=/var/www/html
autostart=true
autorestart=true
numprocs=2
process_name=%(program_name)s_%(process_num)02d
stdout_logfile=/var/log/queuety-default.log
stderr_logfile=/var/log/queuety-default-error.log

[program:queuety-emails]
command=wp queuety work --queue=emails
directory=/var/www/html
autostart=true
autorestart=true
numprocs=1
stdout_logfile=/var/log/queuety-emails.log
stderr_logfile=/var/log/queuety-emails-error.log
```

### Systemd

```ini
[Unit]
Description=Queuety Worker (default queue)
After=mysql.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/html
ExecStart=/usr/local/bin/wp queuety work --queue=default
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

Activar e iniciar:

```bash
sudo systemctl enable queuety-worker
sudo systemctl start queuety-worker
```

### Consejos de despliegue

Ejecute trabajadores separados para distintas colas cuando necesite mayor aislamiento. Use `--workers=N` para cargas de trabajo limitadas por la CPU y prefiera trabajadores supervisados individualmente cuando la carga se centre sobre todo en la E/S. Configure `QUEUETY_WORKER_MAX_JOBS` si quiere reinicios periódicos que liberen memoria y vigile el número de `buried` a través de [webhooks](https://queuety.inline0.dev/es/docs/features/webhooks) o [métricas](https://queuety.inline0.dev/es/docs/features/metrics).
