
# Pagar pengaman alur kerja

Alur kerja bergaya agen bersifat fleksibel, tetapi juga memudahkan pembuatan proses duplikat atau membuat perencana menghasilkan lebih banyak pekerjaan daripada yang dimaksudkan. Queuety menyediakan pagar pengaman ringan pada tingkat alur kerja agar Anda dapat mempertahankan fleksibilitas itu tanpa kehilangan kendali.

Untuk model sumber daya yang lebih luas terkait penerimaan worker dan metadata biaya per tugas, lihat [Manajemen Sumber Daya](https://queuety.inline0.dev/id/docs/features/resource-management).

## Beri versi pada definisi alur kerja

Gunakan `version()` untuk menambahkan label versi tingkat aplikasi pada definisi alur kerja:

```php
Queuety::workflow( 'research_run' )
    ->version( 'research.v2' )
    ->then( PlanResearchStep::class )
    ->then( DraftResearchSummaryStep::class )
    ->dispatch();
```

Versi disimpan bersama status alur kerja, ditampilkan melalui `workflow_status()`, dicetak oleh `wp queuety workflow status`, dan disertakan dalam ekspor alur kerja.

Queuety juga menyimpan `definition_hash` deterministik untuk setiap proses alur kerja. Hash diturunkan dari definisi alur kerja yang diserialisasi dan berguna saat Anda perlu mengidentifikasi dengan tepat bentuk alur kerja yang sedang dijalankan oleh proses yang masih berlangsung setelah deployment.

## Buat dispatch idempoten

Gunakan `idempotency_key()` saat pemanggil mungkin mencoba ulang permintaan yang sama:

```php
Queuety::workflow( 'research_run' )
    ->idempotency_key( 'brief:42:research' )
    ->then( PlanResearchStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```

Jika alur kerja di-dispatch ulang dengan kunci yang sudah pernah digunakan, Queuety mengembalikan ID alur kerja asli alih-alih membuat proses duplikat. Kunci berlaku secara global untuk semua nama alur kerja, jadi sertakan nama alur kerja dalam kunci jika alur kerja berbeda dapat menggunakan kunci yang sama.

Ini sangat berguna untuk:

- Endpoint API yang mungkin dicoba ulang oleh klien atau gateway
- Konsumen webhook yang dapat menerima pengiriman duplikat
- Langkah perencana yang seharusnya hanya membuat satu proses orkestrasi untuk setiap entitas eksternal

Kunci idempotensi disimpan di tabel `queuety_workflow_dispatch_keys`.

## Tetapkan batas alur kerja

Gunakan batas alur kerja untuk menggagalkan proses yang melampaui cakupan yang Anda rencanakan:

```php
Queuety::workflow( 'research_run' )
    ->max_transitions( 20 )
    ->max_for_each_items( 12 )
    ->max_state_bytes( 32768 )
    ->max_cost_units( 40 )
    ->max_started_workflows( 8 )
    ->then( PlanResearchStep::class )
    ->for_each( 'tasks', ExecuteResearchTask::class, 'results' )
    ->dispatch();
```

### `max_transitions()`

Membatasi jumlah langkah alur kerja yang dapat selesai sebelum proses gagal. Ini berguna untuk melindungi alur kerja yang bercabang secara dinamis atau dapat mengunjungi kembali bagian yang sama melalui `_next_step`.

### `max_for_each_items()`

Membatasi jumlah item yang ditemukan saat runtime dan dapat diperluas oleh satu langkah `for_each()`. Ini berguna untuk sistem perencana/eksekutor ketika agen mungkin menemukan jauh lebih banyak pekerjaan cabang daripada yang dimaksudkan.

### `max_state_bytes()`

Membatasi ukuran status alur kerja publik yang dienkode. Ini membantu mencegah alur kerja yang berjalan lama berkembang menjadi blob besar yang lambat diperiksa, diekspor, atau dicoba ulang.

### `max_cost_units()`

Membatasi total unit biaya yang dikonsumsi oleh langkah yang selesai. Unit biaya berasal dari metadata langkah atau tugas yang ditentukan Queuety saat memasukkan pekerjaan ke antrean. Pekerjaan pengguna biasa secara default menggunakan `1`, placeholder orkestrasi seperti penundaan dan wait menggunakan `0`, dan handler dapat menetapkan nilai positif yang lebih tinggi melalui `config()` atau properti tugas. Hanya `cost_units` pada definisi langkah yang dapat menetapkan nilai `0`.

Ini berguna jika alur kerja dapat mengunjungi kembali bagian yang sama atau melakukan for-each atas pekerjaan yang mahal dengan cara yang tidak tercermin dalam jumlah langkah saja. Perencana yang terus menjalankan ulang pemanggilan model yang mahal mungkin tetap berada dalam batas `max_transitions()`, tetapi tetap melampaui cakupan biaya yang Anda maksudkan.

### `max_started_workflows()`

Membatasi jumlah alur kerja tingkat teratas yang dapat dimulai oleh suatu proses melalui `start_workflows()` atau `start_agents()`. Batas diperiksa sebelum alur kerja anak di-dispatch, sehingga alur kerja induk gagal tanpa membuat sebagian grup yang sudah melampaui batas.

Jika anggaran terlampaui, Queuety langsung menggagalkan alur kerja alih-alih mencoba ulang langkah tersebut. Satu pengecualian: ketika `Queuety::signal()` menyelesaikan penantian dan transisi yang dihasilkan melampaui anggaran, pengecualian dilemparkan ke pemanggil `signal()`, penyisipan sinyal dibatalkan, dan alur kerja tetap menunggu.

## Memantau batas pengaman

Status alur kerja menampilkan:

- `definition_version`
- `definition_hash`
- `idempotency_key`
- `budget`

Payload `budget` mencakup batas yang dikonfigurasi beserta penggunaan saat ini, termasuk ukuran status publik saat ini dalam byte.

Contoh:

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

$state->definition_version; // 'research.v2'
$state->definition_hash;    // '4c7a...'
$state->idempotency_key;    // 'brief:42:research'
$state->budget;             // [ 'max_transitions' => 20, ... ]
```
