
# Pembatalan Alur Kerja

Alur kerja dapat dibatalkan secara terprogram atau melalui CLI. Saat alur kerja dibatalkan, Queuety menetapkan statusnya menjadi `cancelled`, mengubur job tertunda atau yang sedang diproses, dan menjalankan handler pembersihan opsional.

## Mendaftarkan handler pembersihan

Gunakan `on_cancel()` pada pembuat alur kerja untuk mendaftarkan kelas yang dijalankan saat alur kerja dibatalkan. Kelas handler harus mengimplementasikan metode `handle( array $state ): void`.

```php
use Queuety\Queuety;

Queuety::workflow( 'import_data' )
    ->then( FetchDataHandler::class )
    ->then( TransformDataHandler::class )
    ->then( LoadDataHandler::class )
    ->on_cancel( ImportCleanupHandler::class )
    ->dispatch( [ 'source_url' => $url ] );
```

Handler pembersihan menerima status publik alur kerja (semua kunci yang tidak diawali `_`):

```php
class ImportCleanupHandler {

    public function handle( array $state ): void {
        // Clean up any partial imports.
        if ( isset( $state['temp_table'] ) ) {
            global $wpdb;
            $wpdb->query( "DROP TABLE IF EXISTS {$state['temp_table']}" );
        }

        // Notify the user.
        wp_mail(
            $state['notify_email'] ?? '',
            'Import cancelled',
            'Your data import was cancelled.'
        );
    }
}
```

## Membatalkan melalui PHP

Panggil `Queuety::cancel_workflow()` dengan ID alur kerja:

```php
Queuety::cancel_workflow( $workflow_id );
```

Metode ini:

1. Mengunci baris alur kerja
2. Mengatur status alur kerja menjadi `cancelled`
3. Mengubur semua tugas yang tertunda dan sedang diproses untuk alur kerja dengan pesan "Workflow cancelled"
4. Mencatat peristiwa `workflow_cancelled` dan melakukan commit
5. Menjalankan kompensasi langkah yang telah selesai dalam urutan terbalik (jika ada yang didaftarkan melalui `compensate_with()`)
6. Menjalankan handler pembersihan `on_cancel` (jika terdaftar)

`RuntimeException` akan dilempar jika alur kerja sudah `completed` atau `cancelled`.

## Membatalkan melalui CLI

```bash
wp queuety workflow cancel <id>
```

| Opsi | Deskripsi |
|---|---|
| `<id>` | ID workflow yang akan dibatalkan (wajib) |

```bash
wp queuety workflow cancel 42
```

## Yang terjadi saat pembatalan

Saat alur kerja dibatalkan:

- **Status** berubah menjadi `cancelled`
- **Kompensasi langkah** dijalankan dalam urutan penyelesaian terbalik jika Anda memasangnya dengan `compensate_with()`
- **Handler pembersihan** dijalankan setelah baris alur kerja ditandai sebagai `cancelled`
- **Tugas tertunda** untuk alur kerja langsung dikubur
- **Tugas yang sedang diproses** untuk alur kerja dikubur; saat handler yang sedang berjalan selesai, keluarannya dibuang dan alur kerja tidak berlanjut
- **Tugas yang telah selesai** dari langkah sebelumnya dibiarkan apa adanya
- **Entri log** dengan peristiwa `workflow_cancelled` dicatat

## Dibatalkan vs. Gagal

| Aspek | Gagal | Dibatalkan |
|---|---|---|
| Pemicu | Sebuah langkah kehabisan percobaan ulang | Pemanggilan eksplisit ke `cancel_workflow()` |
| Status | `failed` | `cancelled` |
| Dapat dicoba ulang | Ya, melalui `retry_workflow()`, kecuali alur kerja sudah dikompensasi | Tidak |
| Handler pembersihan | Tidak dipanggil | Dipanggil jika didaftarkan melalui `on_cancel()` |
| Peristiwa log | `workflow_failed` | `workflow_cancelled` |

## Contoh: pembatalan dengan konfirmasi

Pola yang umum adalah memeriksa status alur kerja sebelum membatalkannya:

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

if ( null === $status ) {
    throw new \RuntimeException( 'Workflow not found.' );
}

if ( 'running' === $status->status->value || 'paused' === $status->status->value ) {
    Queuety::cancel_workflow( $workflow_id );
}
```
