Saltar al contenido

Ejecutar flujos de trabajo

Un flujo de trabajo puede iniciar un flujo secundario en uno de sus pasos. El principal se pausa hasta que termina la ejecución del flujo secundario y, después, combina el estado final de este con el suyo.

El método ->run_workflow()

PHP
use Queuety\Queuety;

$enrichment = Queuety::workflow( 'enrich_user' )
    ->then( FetchSocialHandler::class )
    ->then( FetchCreditScoreHandler::class );

Queuety::workflow( 'onboarding' )
    ->then( CreateAccountHandler::class )
    ->run_workflow( 'enrich_user', $enrichment )
    ->then( SendWelcomeEmailHandler::class )
    ->dispatch( [ 'email' => 'user@example.com' ] );

El método run_workflow() acepta dos argumentos:

  1. Un nombre para la ejecución del flujo de trabajo
  2. Una instancia de WorkflowBuilder que define los pasos de esa ejecución

Cómo funciona

Cuando el flujo de trabajo principal llega a un paso run_workflow:

  1. La ejecución del flujo de trabajo se envía como un flujo independiente con su propio ID
  2. El flujo de trabajo principal se pausa
  3. La ejecución del flujo de trabajo avanza por sus pasos con normalidad
  4. Al completarse la ejecución, su estado final se combina con el estado del flujo principal
  5. El flujo de trabajo principal se reanuda en el paso siguiente

Estado del principal y del secundario

La ejecución del flujo secundario recibe el estado acumulado actual del flujo principal como carga inicial. Así, los pasos secundarios pueden acceder a los datos generados por pasos anteriores del principal:

PHP
class CreateAccountHandler implements Step {
    public function handle( array $state ): array {
        $user_id = wp_create_user( $state['email'], wp_generate_password() );
        return [ 'user_id' => $user_id ];
    }

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

// This run-workflow step can access 'user_id' from the parent
class FetchSocialHandler implements Step {
    public function handle( array $state ): array {
        $profile = fetch_social_profile( $state['user_id'] );
        return [ 'social_data' => $profile ];
    }

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

Combinación del estado

Cuando termina la ejecución del flujo secundario, su estado final (sin claves internas como _steps, _queue, _priority, _max_attempts) se combina con el estado del flujo principal. El paso siguiente del principal ve todos los datos de sus pasos anteriores y de la ejecución del flujo secundario:

PHP
class SendWelcomeEmailHandler implements Step {
    public function handle( array $state ): array {
        // Has access to:
        // - $state['email'] (from initial dispatch)
        // - $state['user_id'] (from CreateAccountHandler)
        // - $state['social_data'] (from run-workflow's FetchSocialHandler)
        // - $state['credit_score'] (from run-workflow's FetchCreditScoreHandler)

        send_welcome_email( $state['email'], $state['social_data'] );
        return [ 'welcome_sent' => true ];
    }

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

Opciones de ejecución del flujo de trabajo

Las opciones on_queue(), with_priority() y max_attempts() del constructor de ejecuciones se aplican al flujo secundario. Las demás opciones de nivel de flujo del constructor secundario, como on_cancel(), prune_state_after(), must_complete_within(), version(), idempotency_key(), los límites de max_*() y compensate_on_failure(), no se transfieren:

PHP
$sub = Queuety::workflow( 'heavy_processing' )
    ->on_queue( 'background' )
    ->with_priority( Priority::Normal )
    ->max_attempts( 5 )
    ->then( StepA::class )
    ->then( StepB::class );

Queuety::workflow( 'parent' )
    ->run_workflow( 'heavy', $sub )
    ->then( FinalStep::class )
    ->dispatch( $payload );

Ejecuciones anidadas

Las ejecuciones de flujos de trabajo también pueden contener otras ejecuciones, lo que permite anidarlas sin límite:

PHP
$inner = Queuety::workflow( 'inner' )
    ->then( InnerStepA::class )
    ->then( InnerStepB::class );

$middle = Queuety::workflow( 'middle' )
    ->then( MiddleStepA::class )
    ->run_workflow( 'inner', $inner )
    ->then( MiddleStepB::class );

Queuety::workflow( 'outer' )
    ->then( OuterStepA::class )
    ->run_workflow( 'middle', $middle )
    ->then( OuterStepB::class )
    ->dispatch( $payload );