
# Kompensasi Alur Kerja

Kompensasi memungkinkan Anda memasang handler pemulihan pada langkah alur kerja yang telah selesai. Queuety menyimpan snapshot status publik saat langkah tersebut selesai, lalu menjalankan handler kompensasi dalam urutan terbalik ketika alur kerja dibatalkan atau, secara opsional, ketika gagal.

## Metode `compensate_with()`

Panggil `compensate_with()` tepat setelah langkah yang ingin dibatalkan dampaknya:

```php
use Queuety\Queuety;

Queuety::workflow( 'provision_account' )
    ->then( CreateRemoteUserStep::class )
    ->compensate_with( DeleteRemoteUserCompensation::class )
    ->then( CreateSubscriptionStep::class )
    ->compensate_with( CancelSubscriptionCompensation::class )
    ->then( SendWelcomeEmailStep::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

Jika alur kerja kemudian dibatalkan, Queuety dijalankan:

1. `CancelSubscriptionCompensation`
2. `DeleteRemoteUserCompensation`

## Handler kompensasi

Handler kompensasi mengimplementasikan `Contracts\Compensation`:

```php
use Queuety\Contracts\Compensation;

final class DeleteRemoteUserCompensation implements Compensation {
    public function handle( array $state ): void {
        remote_api_delete_user( $state['remote_user_id'] );
    }
}
```

Handler menerima status publik alur kerja sebagaimana kondisinya tepat setelah langkah yang dikompensasi selesai. Kunci internal yang dicadangkan tidak disertakan.

## Pembatalan vs. kegagalan

Saat pembatalan eksplisit, kompensasi langkah yang telah selesai selalu dijalankan sebelum handler `on_cancel()` opsional.

Saat terjadi kegagalan, kompensasi hanya dijalankan jika Anda mengaktifkannya:

```php
Queuety::workflow( 'provision_account' )
    ->then( CreateRemoteUserStep::class )
    ->compensate_with( DeleteRemoteUserCompensation::class )
    ->then( CreateSubscriptionStep::class )
    ->compensate_with( CancelSubscriptionCompensation::class )
    ->then( ChargeCardStep::class )
    ->compensate_on_failure()
    ->dispatch( $payload );
```

Tanpa `compensate_on_failure()`, alur kerja yang gagal mempertahankan riwayat langkah yang telah selesai dan dapat dicoba ulang dari langkah yang gagal.

Dengan `compensate_on_failure()`, kompensasi langkah yang telah selesai dijalankan setelah alur kerja ditandai gagal. Setelah itu, `retry_workflow()` melempar pengecualian karena alur kerja sudah dikompensasi.

## Jenis langkah yang didukung

Kompensasi dapat dipasang pada:

- langkah `then()` berurutan
- grup `parallel()`
- langkah `for_each()`
- langkah `run_workflow()`
- langkah penundaan `delay()`
- langkah sinyal `wait_for_signal()`
- langkah dependensi alur kerja `wait_for_workflow()`

Untuk `run_workflow()` dan `for_each()`, snapshot kompensasi dicatat setelah pekerjaan bersarang atau bercabang sepenuhnya selesai.

## `on_cancel()` vs. kompensasi

Gunakan `compensate_with()` untuk membatalkan dampak samping dari langkah yang telah selesai dalam urutan terbalik.

Gunakan `on_cancel()` untuk satu hook pembersihan tingkat alur kerja yang harus dijalankan setiap kali alur kerja dibatalkan secara eksplisit.
