
# Batas Waktu Alur Kerja

Alur kerja dapat diberi batas waktu. Jika alur kerja yang berjalan belum selesai dalam durasi yang ditentukan, Queuety menandainya gagal dan secara opsional memanggil handler. Alur kerja yang dijeda atau menunggu sinyal atau alur kerja lain tidak kedaluwarsa selama menunggu. Batas waktu diperiksa kira-kira sekali per menit oleh proses `wp queuety work` yang berjalan lama, bukan oleh worker `--once` atau mekanisme cadangan WP-Cron. Ini berfungsi sebagai sakelar pengaman untuk alur kerja berdurasi panjang yang tidak boleh berjalan tanpa batas.

## Mengatur batas waktu

Gunakan `must_complete_within()` pada pembuat alur kerja untuk mengatur durasi maksimum yang diizinkan. Gunakan `on_deadline()` untuk mendaftarkan handler yang dijalankan saat batas waktu terlampaui.

```php
use Queuety\Queuety;

Queuety::workflow( 'data_import' )
    ->then( FetchDataHandler::class )
    ->then( TransformDataHandler::class )
    ->then( LoadDataHandler::class )
    ->must_complete_within( hours: 24 )
    ->on_deadline( ImportTimeoutHandler::class )
    ->dispatch( [ 'source' => $url ] );
```

Metode `must_complete_within()` menerima parameter bernama yang nilainya dijumlahkan:

```php
->must_complete_within( hours: 2, minutes: 30 )  // 2.5 hours
->must_complete_within( days: 1 )                 // 24 hours
->must_complete_within( seconds: 3600 )           // 1 hour
->must_complete_within( days: 1, hours: 12 )      // 36 hours
```

## Handler batas waktu

Kelas handler `on_deadline()` harus mengimplementasikan metode `handle( array $state ): void`. Handler menerima status publik alur kerja (semua kunci yang tidak diawali `_`).

```php
class ImportTimeoutHandler {

    public function handle( array $state ): void {
        // Alert the team.
        wp_mail(
            'ops@example.com',
            'Import workflow timed out',
            'Workflow for source ' . ( $state['source'] ?? 'unknown' ) . ' exceeded its deadline.'
        );

        // Clean up partial work.
        if ( isset( $state['temp_file'] ) ) {
            unlink( $state['temp_file'] );
        }
    }
}
```

Handler batas waktu bersifat opsional. Jika Anda hanya ingin alur kerja gagal tanpa menjalankan logika khusus, gunakan `must_complete_within()` tanpa `on_deadline()`.

## Cara kerja pemeriksaan batas waktu

Worker memeriksa batas waktu yang terlampaui setiap 60 detik sebagai bagian dari loop pemrosesannya. Saat menemukan alur kerja yang `status`-nya masih `running` dan `deadline_at`-nya sudah lewat, worker memanggil handler `on_deadline` jika terdaftar, menandai alur kerja gagal dengan pesan kesalahan `Deadline exceeded`, dan mencatat peristiwa log `workflow_deadline_exceeded`. Batas waktunya sendiri disimpan sebagai stempel waktu `deadline_at` pada baris alur kerja dan dihitung saat pengiriman berdasarkan durasi yang dikonfigurasi.

## Yang terjadi saat kedaluwarsa

Saat alur kerja melewati batas waktunya, statusnya berubah menjadi `failed`, pesan kesalahan diatur menjadi `Deadline exceeded`, handler batas waktu dijalankan secara sinkron jika terdaftar, dan entri log `workflow_deadline_exceeded` dicatat. Tugas yang sedang berjalan tidak dihentikan di tengah eksekusi, tetapi alur kerja tidak akan berlanjut melewati batas langkah yang kedaluwarsa. Jika handler batas waktu itu sendiri melempar pengecualian, pengecualian tersebut ditangkap secara diam-diam dan alur kerja tetap berakhir dengan status gagal.

## Metode WorkflowBuilder

| Metode | Deskripsi |
|---|---|
| `must_complete_within( int $seconds = 0, int $minutes = 0, int $hours = 0, int $days = 0 )` | Mengatur durasi maksimum yang diizinkan. Semua parameter dijumlahkan. |
| `on_deadline( string $handler_class )` | Mendaftarkan handler yang dipanggil saat batas waktu terlampaui. |

## Contoh: batas waktu dengan percobaan ulang

Jarang ada manfaatnya mencoba ulang alur kerja yang gagal karena batas waktu. `retry_workflow()` meresetnya ke `running` dan memasukkan kembali langkah yang gagal ke antrean, tetapi tidak menghapus atau memperpanjang batas waktu, sehingga pemeriksaan batas waktu berikutnya akan menggagalkannya lagi dalam kira-kira satu menit. Kirim alur kerja baru sebagai gantinya.

```php
$status = Queuety::workflow_status( $workflow_id );

if ( 'failed' === $status->status->value ) {
    // Check if it was a deadline failure.
    // You may want to dispatch a new workflow instead of retrying.
    Queuety::retry_workflow( $workflow_id );
}
```

## Batas waktu vs. penundaan tidur

Batas waktu berlaku untuk seluruh durasi alur kerja. Penundaan tidur (`->delay()`) menjeda alur kerja selama durasi tetap sebagai bagian dari rangkaian langkahnya. Alur kerja dengan penundaan tidur 1 jam dan batas waktu 2 jam akan gagal jika langkah non-tidur memerlukan total lebih dari 1 jam.
