
# Anulowanie przepływu pracy

Przepływy pracy można anulować programowo lub za pomocą CLI. Po anulowaniu przepływu pracy Queuety ustawia jego status na `cancelled`, ukrywa oczekujące i przetwarzane zadania oraz uruchamia opcjonalną procedurę porządkową.

## Rejestrowanie procedury porządkowej

Użyj `on_cancel()` w kreatorze przepływu pracy, aby zarejestrować klasę uruchamianą po anulowaniu przepływu. Klasa obsługująca procedurę musi implementować metodę `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 ] );
```

Procedura porządkowa otrzymuje publiczny stan przepływu pracy (wszystkie klucze, które nie zaczynają się od `_`):

```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.'
        );
    }
}
```

## Anulowanie za pomocą PHP

Wywołaj `Queuety::cancel_workflow()`, podając identyfikator przepływu pracy:

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

Ta metoda:

1. Blokuje wiersz przepływu pracy
2. Ustawia status przepływu pracy na `cancelled`
3. Ukrywa wszystkie oczekujące i przetwarzane zadania przepływu pracy z komunikatem "Workflow cancelled"
4. Zapisuje zdarzenie `workflow_cancelled` i zatwierdza transakcję
5. Uruchamia kompensacje ukończonych kroków w odwrotnej kolejności (jeśli zarejestrowano je za pomocą `compensate_with()`)
6. Uruchamia procedurę porządkową `on_cancel` (jeśli została zarejestrowana)

Zostanie zgłoszony `RuntimeException`, jeśli przepływ pracy ma już status `completed` lub `cancelled`.

## Anulowanie za pomocą CLI

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

| Opcja | Opis |
|---|---|
| `<id>` | Identyfikator przepływu pracy do anulowania (wymagany) |

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

## Co dzieje się po anulowaniu

Po anulowaniu przepływu pracy:

- **Status** zmienia się na `cancelled`
- **Kompensacje kroków** są uruchamiane w odwrotnej kolejności ukończenia, jeśli zostały dołączone za pomocą `compensate_with()`
- **Procedura porządkowa** jest uruchamiana po oznaczeniu wiersza przepływu pracy jako `cancelled`
- **Oczekujące zadania** przepływu pracy są natychmiast ukrywane
- **Przetwarzane zadania** przepływu pracy są ukrywane; po zakończeniu trwającej procedury obsługi jej wynik zostaje odrzucony, a przepływ pracy nie przechodzi dalej
- **Ukończone zadania** z wcześniejszych kroków pozostają bez zmian
- Rejestrowany jest **wpis dziennika** ze zdarzeniem `workflow_cancelled`

## Anulowany a nieudany przepływ pracy

| Aspekt | Nieudany | Anulowany |
|---|---|---|
| Wyzwalacz | Krok wyczerpuje limit prób ponowienia | Jawne wywołanie `cancel_workflow()` |
| Status | `failed` | `cancelled` |
| Możliwość ponowienia | Tak, za pomocą `retry_workflow()`, chyba że przepływ pracy został już poddany kompensacji | Nie |
| Procedura porządkowa | Nie jest wywoływana | Jest wywoływana, jeśli zarejestrowano ją za pomocą `on_cancel()` |
| Zdarzenie dziennika | `workflow_failed` | `workflow_cancelled` |

## Przykład: anulowanie z potwierdzeniem

Częstym wzorcem jest sprawdzenie statusu przepływu pracy przed jego anulowaniem:

```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 );
}
```
