
# Elaborazione in batch

I batch consentono di avviare un gruppo di job e monitorarli come un’unica unità. Potete registrare callback che si attivano quando il batch viene completato, quando un job ha esito negativo o quando il batch termina indipendentemente dall’esito. Queuety monitora automaticamente i progressi, gli errori e lo stato di annullamento.

## Creare un batch

Usate `Queuety::create_batch()` per avviare un `BatchBuilder`. Passate un array di istanze `Contracts\Job`, poi chiamate `dispatch()` per creare la riga del batch e tutti i job.

```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()` restituisce un oggetto valore `Batch` con lo stato del batch.

Potete anche passare array di gestore e payload invece di istanze di job:

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

## Callback

Registrate le classi dei gestori da chiamare nei diversi momenti del ciclo di vita del batch. Ogni classe di gestore deve avere un metodo `handle( Batch $batch )`.

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

| Metodo | Quando viene attivato |
|---|---|
| `then( $handler_class )` | Tutti i job sono stati completati correttamente (oppure è impostato `allow_failures()`) |
| `catch( $handler_class )` | Il primo job del batch ha esito negativo |
| `finally( $handler_class )` | Il batch termina, con esito positivo o negativo |

### Scrivere un gestore di 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.
    }
}
```

## Consentire gli errori

Per impostazione predefinita, la callback `then` si attiva solo se tutti i job del batch vengono completati correttamente. Chiamate `allow_failures()` per permettere alla callback `then` di attivarsi anche quando alcuni job hanno esito negativo.

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

## Monitoraggio dei progressi

L’oggetto valore `Batch` fornisce proprietà e metodi per monitorare i progressi.

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

| Metodo/Proprietà | Tipo | Descrizione |
|---|---|---|
| `progress()` | `int` | Percentuale di completamento da 0 a 100 |
| `finished()` | `bool` | Indica se il batch è terminato (tutti i job sono stati completati o hanno avuto esito negativo) |
| `has_failures()` | `bool` | Indica se alcuni job del batch hanno avuto esito negativo |
| `cancelled()` | `bool` | Indica se il batch è stato annullato |
| `$total_jobs` | `int` | Numero totale di job nel batch |
| `$pending_jobs` | `int` | Numero di job ancora in attesa |
| `$failed_jobs` | `int` | Numero di job con esito negativo |
| `$failed_job_ids` | `array` | ID dei job con esito negativo |
| `$name` | `string\|null` | Nome del batch facoltativo |
| `$created_at` | `DateTimeImmutable` | Data di creazione del batch |
| `$finished_at` | `DateTimeImmutable\|null` | Data di completamento del batch |
| `$cancelled_at` | `DateTimeImmutable\|null` | Data di annullamento del batch |

## Annullamento

Annullate un batch tramite `BatchManager`. L’annullamento imposta `cancelled_at` e `finished_at` e attiva la callback `finally`.

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

L’annullamento contrassegna il batch come annullato e terminato e attiva la callback `finally`. Non modifica i job: quelli in attesa in un batch annullato vengono comunque eseguiti, ma i relativi risultati non aggiornano più i contatori del batch né attivano `then`, `catch` o `finally`. Eliminate voi i job se non devono essere eseguiti.

## Trovare i batch

Cercate un batch tramite il suo ID:

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

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

## Eliminare i batch meno recenti

Rimuovete i batch terminati da più di un determinato numero di giorni:

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

Vengono eliminati solo i batch con una data `finished_at` non nulla. I batch attivi non vengono mai eliminati.
