
# Processamento em lotes

Os lotes permitem despachar um grupo de trabalhos e acompanhá-los como uma única unidade. Você pode registrar callbacks acionados quando o lote é concluído, quando qualquer trabalho falha ou quando o lote termina, independentemente do resultado. Queuety acompanha automaticamente o progresso, as falhas e o estado de cancelamento.

## Criar um lote

Use `Queuety::create_batch()` para iniciar um `BatchBuilder`. Passe um array de instâncias `Contracts\Job` e depois chame `dispatch()` para criar o registro do lote e todos os trabalhos.

```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()` retorna um objeto de valor `Batch` com o estado do lote.

Você também pode passar arrays de handler e payload no lugar de instâncias de trabalho:

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

## Callbacks

Registre classes de handler para serem chamadas em diferentes momentos do ciclo de vida do lote. Cada classe de handler deve ter um 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 | Quando é acionado |
|---|---|
| `then( $handler_class )` | Todos os trabalhos foram concluídos com sucesso (ou `allow_failures()` está definido) |
| `catch( $handler_class )` | O primeiro trabalho do lote falha |
| `finally( $handler_class )` | O lote termina, tenha sido concluído com sucesso ou falhado |

### Escrever um handler de callback

```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 falhas

Por padrão, o callback `then` só é acionado se todos os trabalhos do lote forem bem-sucedidos. Chame `allow_failures()` para permitir que o callback `then` seja acionado mesmo quando alguns trabalhos falharem.

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

## Acompanhamento do progresso

O objeto de valor `Batch` oferece propriedades e métodos para acompanhar o progresso.

```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/Propriedade | Tipo | Descrição |
|---|---|---|
| `progress()` | `int` | Percentual de conclusão de 0 a 100 |
| `finished()` | `bool` | Indica se o lote terminou (todos os trabalhos concluídos ou falharam) |
| `has_failures()` | `bool` | Indica se algum trabalho do lote falhou |
| `cancelled()` | `bool` | Indica se o lote foi cancelado |
| `$total_jobs` | `int` | Número total de trabalhos no lote |
| `$pending_jobs` | `int` | Número de trabalhos ainda pendentes |
| `$failed_jobs` | `int` | Número de trabalhos que falharam |
| `$failed_job_ids` | `array` | IDs dos trabalhos que falharam |
| `$name` | `string\|null` | Nome opcional do lote |
| `$created_at` | `DateTimeImmutable` | Quando o lote foi criado |
| `$finished_at` | `DateTimeImmutable\|null` | Quando o lote terminou |
| `$cancelled_at` | `DateTimeImmutable\|null` | Quando o lote foi cancelado |

## Cancelamento

Cancele um lote por meio de `BatchManager`. O cancelamento define `cancelled_at` e `finished_at` e aciona o callback `finally`.

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

O cancelamento marca o lote como cancelado e concluído e aciona seu callback `finally`. Ele não afeta os trabalhos: os trabalhos pendentes em um lote cancelado ainda são executados, mas seus resultados deixam de atualizar os contadores do lote ou acionar `then`, `catch` ou `finally`. Exclua os trabalhos manualmente se eles não puderem ser executados.

## Localizar lotes

Busque um lote pelo ID:

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

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

## Remover lotes antigos

Remova lotes concluídos há mais dias do que o número especificado:

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

Somente lotes com um registro de data e hora `finished_at` não nulo são excluídos. Lotes ativos nunca são removidos.
