
# Pemrosesan Batch

Batch memungkinkan Anda menjalankan sekelompok job dan melacaknya sebagai satu unit. Anda dapat mendaftarkan callback yang dijalankan saat batch selesai, saat ada job yang gagal, atau saat batch berakhir apa pun hasilnya. Queuety melacak progres, kegagalan, dan status pembatalan secara otomatis.

## Membuat batch

Gunakan `Queuety::create_batch()` untuk memulai `BatchBuilder`. Berikan array berisi instans `Contracts\Job`, lalu panggil `dispatch()` untuk membuat baris batch dan semua 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()` mengembalikan objek nilai `Batch` yang berisi status batch.

Anda juga dapat memberikan array handler+payload alih-alih instans job:

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

## Callback

Daftarkan kelas handler yang akan dipanggil pada titik berbeda dalam siklus hidup batch. Setiap kelas handler harus memiliki metode `handle( Batch $batch )`.

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

| Metode | Kapan dijalankan |
|---|---|
| `then( $handler_class )` | Semua job berhasil diselesaikan (atau `allow_failures()` ditetapkan) |
| `catch( $handler_class )` | Job pertama dalam batch gagal |
| `finally( $handler_class )` | Batch selesai, baik berhasil maupun gagal |

### Menulis handler 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.
    }
}
```

## Mengizinkan kegagalan

Secara default, callback `then` hanya dijalankan jika semua job dalam batch berhasil. Panggil `allow_failures()` agar callback `then` tetap dijalankan meskipun beberapa job gagal.

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

## Pelacakan progres

Objek nilai `Batch` menyediakan properti dan metode untuk melacak progres.

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

| Metode/Properti | Tipe | Deskripsi |
|---|---|---|
| `progress()` | `int` | Persentase penyelesaian dari 0 hingga 100 |
| `finished()` | `bool` | Apakah batch telah selesai (semua job selesai atau gagal) |
| `has_failures()` | `bool` | Apakah ada job dalam batch yang gagal |
| `cancelled()` | `bool` | Apakah batch telah dibatalkan |
| `$total_jobs` | `int` | Jumlah total job dalam batch |
| `$pending_jobs` | `int` | Jumlah job yang masih tertunda |
| `$failed_jobs` | `int` | Jumlah job yang gagal |
| `$failed_job_ids` | `array` | ID job yang gagal |
| `$name` | `string\|null` | Nama batch opsional |
| `$created_at` | `DateTimeImmutable` | Waktu batch dibuat |
| `$finished_at` | `DateTimeImmutable\|null` | Waktu batch selesai |
| `$cancelled_at` | `DateTimeImmutable\|null` | Waktu batch dibatalkan |

## Pembatalan

Batalkan batch melalui `BatchManager`. Pembatalan batch menetapkan `cancelled_at` dan `finished_at`, serta menjalankan callback `finally`.

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

Pembatalan menandai batch sebagai dibatalkan dan selesai, lalu menjalankan callback `finally`. Pembatalan tidak memengaruhi job: job tertunda dalam batch yang dibatalkan tetap berjalan, tetapi hasilnya tidak lagi memperbarui penghitung batch atau memicu `then`, `catch`, atau `finally`. Hapus sendiri job tersebut jika job tidak boleh dijalankan.

## Menemukan batch

Cari batch berdasarkan ID-nya:

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

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

## Membersihkan batch lama

Hapus batch yang sudah selesai dan lebih lama dari jumlah hari tertentu:

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

Hanya batch dengan stempel waktu `finished_at` yang tidak null yang akan dihapus. Batch aktif tidak pernah dibersihkan.
