
# Töövoo kompenseerimine

Kompenseerimine võimaldab lisada lõpetatud töövoosammule tagasipööramiskäitleja. Queuety talletab sammu lõpetamisel avaliku oleku hetktõmmise, seejärel käivitab kompensatsioonikäitlejad vastupidises järjekorras, kui töövoog tühistatakse või valikuliselt ka siis, kui see nurjub.

## Meetod `compensate_with()`

Kutsu `compensate_with()` välja kohe pärast sammu, mille mõju see peaks tagasi pöörama:

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

Kui töövoog hiljem tühistatakse, käivitab Queuety järgmise:

1. `CancelSubscriptionCompensation`
2. `DeleteRemoteUserCompensation`

## Kompensatsioonikäitlejad

Kompensatsioonikäitlejad rakendavad liidese `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äitleja saab avaliku töövoo oleku sellisena, nagu see oli kohe pärast kompenseeritava sammu lõpetamist. Reserveeritud sisemisi võtmeid ei kaasata.

## Tühistamine ja nurjumine

Otsese tühistamise korral käivitatakse lõpetatud sammude kompensatsioonid alati enne valikulist käitlejat `on_cancel()`.

Nurjumise korral käivitatakse kompensatsioonid ainult siis, kui selle lubad:

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

Ilma funktsioonita `compensate_on_failure()` säilitab nurjunud töövoog lõpetatud sammude ajaloo puutumatuna ning seda saab nurjunud sammust uuesti proovida.

Funktsiooniga `compensate_on_failure()` käivitatakse lõpetatud sammude kompensatsioonid pärast töövoo nurjunuks märkimist. Seejärel viskab `retry_workflow()` vea, sest töövoog on juba kompenseeritud.

## Toetatud sammutüübid

Kompensatsiooni saab lisada järgmistele:

- järjestikused `then()` sammud
- `parallel()` rühmad
- `for_each()` sammud
- `run_workflow()` sammud
- `delay()` viivitussammud
- `wait_for_signal()` signaalisammud
- `wait_for_workflow()` töövoo sõltuvussammud

Funktsioonide `run_workflow()` ja `for_each()` puhul talletatakse kompensatsiooni hetktõmmis pärast pesastatud või harudeks jaotatud töö täielikku lõppemist.

## `on_cancel()` ja kompenseerimine

Kasuta funktsiooni `compensate_with()` lõpetatud sammude kõrvalmõjude vastupidises järjekorras tagasipööramiseks.

Kasuta funktsiooni `on_cancel()` ühe töövootaseme puhastuskäitlejana, mis peaks käivituma alati, kui töövoog otseselt tühistatakse.
