
# Annulation de workflow

Les workflows peuvent être annulés par programmation ou via CLI. Lorsqu’un workflow est annulé, Queuety définit son état sur `cancelled`, met en retrait tous les travaux en attente ou en cours de traitement et exécute un gestionnaire de nettoyage facultatif.

## Enregistrer un gestionnaire de nettoyage

Utilisez `on_cancel()` sur le constructeur du workflow pour enregistrer une classe exécutée lors de l’annulation du workflow. Cette classe doit implémenter une méthode `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 ] );
```

Le gestionnaire de nettoyage reçoit l’état public du workflow (toutes les clés qui ne commencent pas par `_`) :

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

## Annuler via PHP

Appelez `Queuety::cancel_workflow()` avec l’ID du workflow :

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

Cette méthode :

1. Verrouille la ligne du workflow
2. Définit l’état du workflow sur `cancelled`
3. Met en retrait tous les travaux en attente et en cours de traitement du workflow avec le message "Workflow cancelled"
4. Enregistre un événement `workflow_cancelled` et valide la transaction
5. Exécute les compensations des étapes terminées dans l’ordre inverse (si elles ont été enregistrées via `compensate_with()`)
6. Exécute le gestionnaire de nettoyage `on_cancel` (s’il est enregistré)

Une exception `RuntimeException` est levée si le workflow est déjà `completed` ou `cancelled`.

## Annuler via CLI

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

| Option | Description |
|---|---|
| `<id>` | ID du workflow à annuler (obligatoire) |

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

## Que se passe-t-il lors d’une annulation ?

Lorsqu’un workflow est annulé :

- **État** passe à `cancelled`
- **Compensations des étapes** sont exécutées dans l’ordre inverse d’achèvement si vous les avez associées avec `compensate_with()`
- **Gestionnaire de nettoyage** est exécuté après que la ligne du workflow a été marquée `cancelled`
- **Travaux en attente** du workflow sont immédiatement mis en retrait
- **Travaux en cours de traitement** du workflow sont mis en retrait ; lorsque le gestionnaire en cours termine, son résultat est ignoré et le workflow ne progresse pas
- **Travaux terminés** des étapes précédentes restent inchangés
- **Entrée de journal** avec l’événement `workflow_cancelled` est enregistrée

## Annulé ou en échec

| Aspect | En échec | Annulé |
|---|---|---|
| Déclencheur | Une étape épuise ses tentatives de nouvelle tentative | Appel explicite à `cancel_workflow()` |
| État | `failed` | `cancelled` |
| Nouvelle tentative possible | Oui, via `retry_workflow()`, sauf si le workflow a déjà été compensé | Non |
| Gestionnaire de nettoyage | Non appelé | Appelé s’il est enregistré via `on_cancel()` |
| Événement de journal | `workflow_failed` | `workflow_cancelled` |

## Exemple : annulation avec confirmation

Un modèle courant consiste à vérifier l’état du workflow avant de l’annuler :

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