
# Procesamiento por lotes

Los lotes permiten enviar un grupo de trabajos y hacerles seguimiento como una sola unidad. Puede registrar funciones de retorno de llamada que se ejecuten cuando se complete el lote, cuando falle algún trabajo o cuando el lote termine, independientemente del resultado. Queuety realiza un seguimiento automático del progreso, los fallos y el estado de cancelación.

## Crear un lote

Use `Queuety::create_batch()` para iniciar un `BatchBuilder`. Pase una matriz de instancias de `Contracts\Job` y luego llame a `dispatch()` para crear la fila del lote y todos los trabajos.

```php
use Queuety\Queuety;

$batch = Queuety::create_batch( [
    new ImportUsersJob( $csv_chunk_1 ),
    new ImportUsersJob( $csv_chunk_2 ),
    new ImportUsersJob( $csv_chunk_3 ),
] )
    ->name( 'Import users' )
    ->on_queue( 'imports' )
    ->dispatch();

echo $batch->id; // The batch ID
```

`dispatch()` devuelve un objeto de valor `Batch` con el estado del lote.

También puede pasar matrices de controlador+carga útil en lugar de instancias de trabajos:

```php
$batch = Queuety::create_batch( [
    [ 'handler' => 'import_users', 'payload' => [ 'chunk' => 1 ] ],
    [ 'handler' => 'import_users', 'payload' => [ 'chunk' => 2 ] ],
] )->dispatch();
```

## Funciones de retorno de llamada

Registre clases de controladores que se llamarán en distintos momentos del ciclo de vida del lote. Cada clase de controlador debe tener un método `handle( Batch $batch )`.

```php
$batch = Queuety::create_batch( $jobs )
    ->name( 'Import users' )
    ->then( ImportCompleteHandler::class )
    ->catch( ImportFailedHandler::class )
    ->finally( ImportCleanupHandler::class )
    ->dispatch();
```

| Método | Cuándo se ejecuta |
|---|---|
| `then( $handler_class )` | Todos los trabajos se completaron correctamente (o se establece `allow_failures()`) |
| `catch( $handler_class )` | Falla el primer trabajo del lote |
| `finally( $handler_class )` | El lote termina, tanto si se completó correctamente como si falló |

### Escribir un controlador de función de retorno de llamada

```php
use Queuety\Batch;

class ImportCompleteHandler {
    public function handle( Batch $batch ): void {
        // All users imported. Send a notification.
        error_log( "Batch {$batch->id} completed: {$batch->total_jobs} jobs processed." );
    }
}

class ImportFailedHandler {
    public function handle( Batch $batch ): void {
        error_log( "Batch {$batch->id} had a failure. Failed jobs: {$batch->failed_jobs}" );
    }
}

class ImportCleanupHandler {
    public function handle( Batch $batch ): void {
        // Runs regardless of outcome. Clean up temp files, etc.
    }
}
```

## Permitir fallos

De forma predeterminada, la función de retorno de llamada `then` solo se ejecuta si todos los trabajos del lote se completan correctamente. Llame a `allow_failures()` para permitir que la función de retorno de llamada `then` se ejecute aunque fallen algunos trabajos.

```php
$batch = Queuety::create_batch( $jobs )
    ->then( ReportHandler::class )
    ->allow_failures()
    ->dispatch();
```

## Seguimiento del progreso

El objeto de valor `Batch` proporciona propiedades y métodos para seguir el progreso.

```php
$batch = Queuety::find_batch( $batch_id );

$batch->progress();      // 0-100 percentage
$batch->finished();      // true if all jobs are done
$batch->has_failures();  // true if any job failed
$batch->cancelled();     // true if the batch was cancelled

$batch->total_jobs;      // Total number of jobs
$batch->pending_jobs;    // Jobs still pending
$batch->failed_jobs;     // Number of failed jobs
$batch->failed_job_ids;  // Array of failed job IDs
```

| Método/propiedad | Tipo | Descripción |
|---|---|---|
| `progress()` | `int` | Porcentaje completado de 0 a 100 |
| `finished()` | `bool` | Indica si el lote ha terminado (todos los trabajos se completaron o fallaron) |
| `has_failures()` | `bool` | Indica si falló algún trabajo del lote |
| `cancelled()` | `bool` | Indica si se canceló el lote |
| `$total_jobs` | `int` | Número total de trabajos del lote |
| `$pending_jobs` | `int` | Número de trabajos pendientes |
| `$failed_jobs` | `int` | Número de trabajos fallidos |
| `$failed_job_ids` | `array` | ID de los trabajos que fallaron |
| `$name` | `string\|null` | Nombre opcional del lote |
| `$created_at` | `DateTimeImmutable` | Fecha y hora de creación del lote |
| `$finished_at` | `DateTimeImmutable\|null` | Fecha y hora de finalización del lote |
| `$cancelled_at` | `DateTimeImmutable\|null` | Fecha y hora de cancelación del lote |

## Cancelación

Cancele un lote mediante `BatchManager`. Al cancelar un lote, se establecen `cancelled_at` y `finished_at`, y se ejecuta la función de retorno de llamada `finally`.

```php
Queuety::batch_manager()->cancel( $batch_id );
```

La cancelación marca el lote como cancelado y finalizado, y ejecuta su función de retorno de llamada `finally`. No afecta a los trabajos: los trabajos pendientes de un lote cancelado siguen ejecutándose, pero sus resultados ya no actualizan los contadores del lote ni activan `then`, `catch` o `finally`. Elimine los trabajos usted mismo si no deben ejecutarse.

## Buscar lotes

Busque un lote por su ID:

```php
$batch = Queuety::find_batch( $batch_id );

if ( null === $batch ) {
    // Batch not found.
}
```

## Depurar lotes antiguos

Elimine los lotes finalizados que tengan más días que el número indicado:

```php
$deleted = Queuety::batch_manager()->prune( 30 ); // Delete batches finished > 30 days ago
```

Solo se eliminan los lotes que tienen una marca de tiempo `finished_at` no nula. Los lotes activos nunca se depuran.
