
# Kompenzácia pracovného postupu

Kompenzácia umožňuje pripojiť obslužnú funkciu na vrátenie zmien k dokončenému kroku pracovného postupu. Queuety uloží snímku verejného stavu po dokončení daného kroku a následne spustí kompenzačné obslužné funkcie v opačnom poradí, keď sa pracovný postup zruší alebo prípadne zlyhá.

## Metóda `compensate_with()`

Zavolajte `compensate_with()` hneď po kroku, ktorého účinky má vrátiť späť:

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

Ak sa pracovný postup neskôr zruší, spustí sa Queuety:

1. `CancelSubscriptionCompensation`
2. `DeleteRemoteUserCompensation`

## Kompenzačné obslužné funkcie

Kompenzačné obslužné funkcie implementujú `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'] );
    }
}
```

Obslužná funkcia dostane verejný stav pracovného postupu v podobe bezprostredne po dokončení kompenzovaného kroku. Rezervované interné kľúče nie sú zahrnuté.

## Zrušenie a zlyhanie

Pri explicitnom zrušení sa kompenzácie dokončených krokov vždy spustia pred voliteľnou obslužnou funkciou `on_cancel()`.

Pri zlyhaní sa kompenzácie spustia iba vtedy, ak ich výslovne povolíte:

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

Bez `compensate_on_failure()` si neúspešný pracovný postup zachová históriu dokončených krokov a možno ho zopakovať od neúspešného kroku.

Pomocou `compensate_on_failure()` sa dokončené kompenzácie krokov spustia až po označení workflowu ako neúspešného. Potom `retry_workflow()` vyhodí výnimku, pretože workflow už bol kompenzovaný.

## Podporované typy krokov

Kompenzáciu možno priradiť k:

- sekvenčným krokom `then()`
- skupinám `parallel()`
- krokom `for_each()`
- krokom `run_workflow()`
- krokom oneskorenia `delay()`
- krokom signálu `wait_for_signal()`
- krokom závislosti workflowu `wait_for_workflow()`

Pri `run_workflow()` a `for_each()` sa snímka kompenzácie zaznamená až po úplnom dokončení vnorených alebo rozvetvených úloh.

## `on_cancel()` a kompenzácia

Použite `compensate_with()` na vrátenie vedľajších účinkov dokončených krokov v opačnom poradí.

Použite `on_cancel()` ako jediný čistiaci hák na úrovni workflowu, ktorý sa má spustiť vždy, keď sa workflow výslovne zruší.
