Vai al contenuto

Compensazione del workflow

La compensazione consente di associare un gestore di rollback a un passaggio completato del workflow. Queuety memorizza uno snapshot dello stato pubblico al termine del passaggio, quindi esegue i gestori di compensazione in ordine inverso quando il workflow viene annullato o, facoltativamente, quando non riesce.

Il metodo compensate_with()

Chiamate compensate_with() subito dopo il passaggio che deve annullare:

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

Se il workflow viene annullato in seguito, viene eseguito Queuety:

  1. CancelSubscriptionCompensation
  2. DeleteRemoteUserCompensation

Gestori di compensazione

I gestori di compensazione implementano 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'] );
    }
}

Il gestore riceve lo stato pubblico del workflow così com'era subito dopo il completamento del passaggio compensato. Le chiavi interne riservate non sono incluse.

Annullamento o errore

In caso di annullamento esplicito, le compensazioni dei passaggi completati vengono sempre eseguite prima del gestore facoltativo on_cancel().

In caso di errore, le compensazioni vengono eseguite solo se le attivate esplicitamente:

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

Senza compensate_on_failure(), un workflow non riuscito conserva intatta la cronologia dei passaggi completati ed è possibile riprovare dal passaggio non riuscito.

Con compensate_on_failure(), le compensazioni dei passaggi completati vengono eseguite dopo che il workflow è contrassegnato come non riuscito. In seguito, retry_workflow() genera un'eccezione perché il workflow è già stato compensato.

Tipi di passaggio supportati

È possibile associare la compensazione a:

  • passaggi sequenziali then()
  • gruppi parallel()
  • passaggi for_each()
  • passaggi run_workflow()
  • passaggi di attesa delay()
  • passaggi di segnale wait_for_signal()
  • passaggi di dipendenza del workflow wait_for_workflow()

Per run_workflow() e for_each(), lo snapshot di compensazione viene registrato dopo che il lavoro annidato o ramificato è terminato del tutto.

on_cancel() e compensazione

Usate compensate_with() per annullare in ordine inverso gli effetti collaterali dei passaggi completati.

Usate on_cancel() per un singolo hook di pulizia a livello di workflow, da eseguire ogni volta che il workflow viene annullato esplicitamente.