
# Työnkulun korvaustoiminnot

Korvaustoiminnolla voit liittää palautuskäsittelijän valmiiseen työnkulun vaiheeseen. Queuety tallentaa julkisen tilan tilannekuvan vaiheen valmistuessa ja suorittaa sitten korvauskäsittelijät käänteisessä järjestyksessä, kun työnkulku peruutetaan tai valinnaisesti epäonnistuu.

## `compensate_with()`-menetelmä

Kutsu `compensate_with()`-toimintoa heti sen vaiheen jälkeen, jonka vaikutukset se kumoaa:

```php
use Queuety\Queuety;

Queuety::workflow( 'provision_account' )
    ->then( CreateRemoteUserStep::class )
    ->compensate_with( DeleteRemoteUserCompensation::class )
    ->then( CreateSubscriptionStep::class )
    ->compensate_with( CancelSubscriptionCompensation::class )
    ->then( SendWelcomeEmailStep::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

Jos työnkulku myöhemmin peruutetaan, Queuety suoritetaan:

1. `CancelSubscriptionCompensation`
2. `DeleteRemoteUserCompensation`

## Korvauskäsittelijät

Korvauskäsittelijät toteuttavat rajapinnan `Contracts\Compensation`:

```php
use Queuety\Contracts\Compensation;

final class DeleteRemoteUserCompensation implements Compensation {
    public function handle( array $state ): void {
        remote_api_delete_user( $state['remote_user_id'] );
    }
}
```

Käsittelijä saa julkisen työnkulun tilan sellaisena kuin se oli heti korvatun vaiheen valmistuttua. Varattuja sisäisiä avaimia ei sisällytetä.

## Peruuttaminen ja epäonnistuminen

Nimenomaisen peruutuksen yhteydessä valmiiden vaiheiden korvaustoiminnot suoritetaan aina ennen valinnaista `on_cancel()`-käsittelijää.

Epäonnistumistilanteessa korvaustoiminnot suoritetaan vain, jos otat ne käyttöön:

```php
Queuety::workflow( 'provision_account' )
    ->then( CreateRemoteUserStep::class )
    ->compensate_with( DeleteRemoteUserCompensation::class )
    ->then( CreateSubscriptionStep::class )
    ->compensate_with( CancelSubscriptionCompensation::class )
    ->then( ChargeCardStep::class )
    ->compensate_on_failure()
    ->dispatch( $payload );
```

Ilman `compensate_on_failure()`-toimintoa epäonnistunut työnkulku säilyttää valmiiden vaiheiden historian, ja suoritusta voi yrittää uudelleen epäonnistuneesta vaiheesta alkaen.

Kun `compensate_on_failure()` on käytössä, valmiiden vaiheiden korvaustoiminnot suoritetaan sen jälkeen, kun työnkulku on merkitty epäonnistuneeksi. Tämän jälkeen `retry_workflow()` heittää poikkeuksen, koska työnkululle on jo tehty korvaustoiminnot.

## Tuetut vaihetyypit

Korvaustoimintoja voi liittää seuraaviin:

- peräkkäiset `then()`-vaiheet
- `parallel()`-ryhmät
- `for_each()`-vaiheet
- `run_workflow()`-vaiheet
- `delay()`-viivevaiheet
- `wait_for_signal()`-signaalivaiheet
- `wait_for_workflow()`-työnkulun riippuvuusvaiheet

Vaiheissa `run_workflow()` ja `for_each()` korvaustoiminnon tilannekuva tallennetaan, kun sisäkkäinen tai haarautunut työ on kokonaan valmistunut.

## `on_cancel()` ja korvaustoiminnot

Käytä `compensate_with()`-toimintoa valmiiden vaiheiden sivuvaikutusten kumoamiseen käänteisessä järjestyksessä.

Käytä `on_cancel()`-toimintoa työnkulun tason siivouskoukkuna, joka suoritetaan aina, kun työnkulku nimenomaisesti peruutetaan.
