
# Anularea fluxurilor de lucru

Fluxurile de lucru pot fi anulate programatic sau prin CLI. Când un flux de lucru este anulat, Queuety îi setează starea la `cancelled`, îngroapă toate joburile în așteptare sau în curs de procesare și rulează un gestionar opțional pentru curățare.

## Înregistrarea unui gestionar pentru curățare

Folosiți `on_cancel()` în constructorul fluxului de lucru pentru a înregistra o clasă care rulează atunci când fluxul este anulat. Clasa gestionarului trebuie să implementeze o 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 ] );
```

Gestionarul pentru curățare primește starea publică a fluxului de lucru (toate cheile care nu încep cu `_`):

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

## Anularea prin PHP

Apelați `Queuety::cancel_workflow()` cu ID-ul fluxului de lucru:

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

Această metodă:

1. Blochează rândul fluxului de lucru
2. Setează starea fluxului de lucru la `cancelled`
3. Îngroapă toate joburile în așteptare și în curs de procesare ale fluxului, cu mesajul "Workflow cancelled"
4. Înregistrează un eveniment `workflow_cancelled` și confirmă tranzacția
5. Rulează compensările pașilor finalizați în ordine inversă (dacă au fost înregistrate prin `compensate_with()`)
6. Rulează gestionarul pentru curățare `on_cancel` (dacă este înregistrat)

Se aruncă o `RuntimeException` dacă fluxul de lucru este deja `completed` sau `cancelled`.

## Anularea prin CLI

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

| Opțiune | Descriere |
|---|---|
| `<id>` | ID-ul fluxului de lucru de anulat (obligatoriu) |

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

## Ce se întâmplă la anulare

Când un flux de lucru este anulat:

- **Starea** se schimbă la `cancelled`
- **Compensările pașilor** rulează în ordinea inversă a finalizării, dacă le-ați atașat cu `compensate_with()`
- **Gestionarul pentru curățare** rulează după ce rândul fluxului de lucru a fost marcat `cancelled`
- **Joburile în așteptare** ale fluxului de lucru sunt îngropate imediat
- **Joburile în curs de procesare** ale fluxului de lucru sunt îngropate; când gestionarul aflat în execuție își termină activitatea, rezultatul este eliminat, iar fluxul de lucru nu continuă
- **Joburile finalizate** din pașii anteriori rămân neschimbate
- **O intrare în jurnal** cu evenimentul `workflow_cancelled` este înregistrată

## Anulat sau eșuat

| Aspect | Eșuat | Anulat |
|---|---|---|
| Declanșator | Un pas își epuizează încercările de reîncercare | Apel explicit la `cancel_workflow()` |
| Stare | `failed` | `cancelled` |
| Se poate reîncerca | Da, prin `retry_workflow()`, dacă fluxul de lucru nu a fost deja compensat | Nu |
| Gestionar pentru curățare | Nu este apelat | Este apelat dacă a fost înregistrat prin `on_cancel()` |
| Eveniment în jurnal | `workflow_failed` | `workflow_cancelled` |

## Exemplu: anulare cu confirmare

Un model obișnuit este să verificați starea fluxului de lucru înainte de anulare:

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