Vai al contenuto

Ramificazione condizionale

I workflow possono passare a un passaggio con nome in base all'output di un passaggio precedente. Per farlo, si restituisce una chiave speciale _next_step nel valore restituito dal passaggio.

Se volete tornare specificamente a un passaggio precedente in base allo stato del workflow, consultate Ripetizioni. In questo modo il collegamento all'indietro resta esplicito nella definizione del workflow, invece di essere nascosto in una classe di passaggio.

Passaggi con nome

Assegnate un nome ai passaggi usando il secondo argomento di ->then():

PHP
use Queuety\Queuety;

Queuety::workflow( 'process_order' )
    ->then( ValidateOrderHandler::class, 'validate' )
    ->then( ChargePaymentHandler::class, 'charge' )
    ->then( FulfillOrderHandler::class, 'fulfill' )
    ->then( SendConfirmationHandler::class, 'confirm' )
    ->then( HandleFailureHandler::class, 'failure' )
    ->dispatch( [ 'order_id' => 123 ] );

Senza un nome esplicito, i passaggi vengono denominati in base al loro indice ('0', '1', '2' e così via).

La chiave _next_step

Un passaggio può restituire _next_step per passare a un passaggio con nome, saltando tutti quelli intermedi. I passaggi successivi alla destinazione del salto vengono comunque eseguiti in ordine: senza un salto, il workflow prosegue semplicemente con il passaggio successivo nell'elenco, quindi nell'esempio precedente un passaggio confirm completato correttamente prosegue con failure, a meno che non restituisca un _next_step che lo salta oppure HandleFailureHandler controlli prima la presenza di una chiave error:

PHP
use Queuety\Step;

class ValidateOrderHandler implements Step {
    public function handle( array $state ): array {
        $order = wc_get_order( $state['order_id'] );

        if ( ! $order || $order->get_status() === 'cancelled' ) {
            return [
                'error'  => 'Order is invalid or cancelled',
                '_next_step'  => 'failure',
            ];
        }

        return [
            'order_total' => $order->get_total(),
            'customer_id' => $order->get_customer_id(),
        ];
    }

    public function config(): array {
        return [];
    }
}

Quando ValidateOrderHandler restituisce _next_step => 'failure', il workflow salta charge, fulfill e confirm, passando direttamente al passaggio failure. La chiave _next_step viene usata dal motore del workflow e non viene salvata nello stato.

Modelli di ramificazione

Salto in base a una condizione

PHP
class CheckInventoryHandler implements Step {
    public function handle( array $state ): array {
        $in_stock = check_inventory( $state['sku'] );

        if ( ! $in_stock ) {
            return [
                'reason' => 'Out of stock',
                '_next_step'  => 'notify_backorder',
            ];
        }

        return [ 'inventory_reserved' => true ];
    }

    public function config(): array {
        return [];
    }
}

Completamento anticipato

Passate al passaggio finale per saltare le elaborazioni non necessarie:

PHP
class CheckCacheHandler implements Step {
    public function handle( array $state ): array {
        $cached = get_transient( "report_{$state['user_id']}" );

        if ( $cached ) {
            return [
                'report_url' => $cached,
                '_next_step'      => 'done',
            ];
        }

        return [ 'cache_miss' => true ];
    }

    public function config(): array {
        return [];
    }
}

Esempio completo

PHP
Queuety::workflow( 'content_pipeline' )
    ->then( CheckCacheHandler::class, 'check_cache' )
    ->then( FetchDataHandler::class, 'fetch' )
    ->then( CallLLMHandler::class, 'generate' )
    ->then( SaveResultHandler::class, 'save' )
    ->then( ReturnCachedHandler::class, 'done' )
    ->dispatch( [ 'user_id' => 42 ] );

Se il controllo della cache trova un risultato, il workflow passa direttamente da check_cache a done, saltando fetch, generate e save. Se non trova risultati, i passaggi vengono eseguiti in ordine e save prosegue anche con done, quindi ReturnCachedHandler deve gestire entrambi i percorsi.