
# Preklic potekov dela

Poteke dela je mogoče preklicati programsko ali prek CLI. Ob preklicu poteka dela Queuety nastavi njegovo stanje na `cancelled`, skrije čakajoča opravila in opravila v obdelavi ter zažene izbirni obravnavalnik za čiščenje.

## Registracija obravnavalnika za čiščenje

V graditelju poteka dela uporabite `on_cancel()` za registracijo razreda, ki se zažene ob preklicu poteka dela. Razred obravnavalnika mora implementirati metodo `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 ] );
```

Obravnavalnik za čiščenje prejme javno stanje poteka dela (vse ključe, ki se ne začnejo z `_`):

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

## Preklic prek PHP

Pokličite `Queuety::cancel_workflow()` z ID-jem poteka dela:

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

Ta metoda:

1. Zaklene vrstico poteka dela
2. Nastavi stanje poteka dela na `cancelled`
3. Skrije vsa čakajoča opravila in opravila v obdelavi za ta potek dela s sporočilom "Workflow cancelled"
4. Zabeleži dogodek `workflow_cancelled` in potrdi transakcijo
5. V obratnem vrstnem redu zažene kompenzacijske postopke za dokončane korake (če so bili registrirani prek `compensate_with()`)
6. Zažene obravnavalnik za čiščenje `on_cancel` (če je registriran)

Izjema `RuntimeException` se sproži, če je potek dela že v stanju `completed` ali `cancelled`.

## Preklic prek CLI

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

| Možnost | Opis |
|---|---|
| `<id>` | ID poteka dela za preklic (obvezno) |

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

## Kaj se zgodi ob preklicu

Ko je potek dela preklican:

- **Stanje** se spremeni v `cancelled`
- **Kompenzacijski postopki za korake** se izvedejo v obratnem vrstnem redu dokončanja, če ste jih določili z `compensate_with()`
- **Obravnavalnik za čiščenje** se zažene, ko je vrstica poteka dela označena kot `cancelled`
- **Čakajoča opravila** za ta potek dela so takoj skrita
- **Opravila v obdelavi** za ta potek dela so skrita; ko se obravnavalnik v teku konča, se njegov izhod zavrže in potek dela ne nadaljuje
- **Dokončana opravila** iz prejšnjih korakov ostanejo nespremenjena
- **Vnos v dnevniku** z dogodkom `workflow_cancelled` je zabeležen

## Preklic in neuspeh

| Vidik | Neuspešno | Preklicano |
|---|---|---|
| Sprožilec | Korak porabi vse poskuse ponovitve | Izrecni klic `cancel_workflow()` |
| Stanje | `failed` | `cancelled` |
| Ali je mogoče ponoviti | Da, prek `retry_workflow()`, razen če je bil potek dela že kompenziran | Ne |
| Obravnavalnik za čiščenje | Se ne pokliče | Pokliče se, če je registriran prek `on_cancel()` |
| Dogodek v dnevniku | `workflow_failed` | `workflow_cancelled` |

## Primer: preklic s potrditvijo

Pogost vzorec je, da pred preklicem preverite stanje poteka dela:

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