
# Workflows uitvoeren

Een workflow kan een onderliggende workflow als een van zijn stappen starten. De bovenliggende workflow wacht totdat de uitvoering van de workflow is voltooid en voegt daarna de uiteindelijke status van de onderliggende workflow samen met die van zichzelf.

## De methode `->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' ] );
```

De methode `run_workflow()` heeft twee argumenten:
1. Een naam voor de workflowuitvoering
2. Een instantie van `WorkflowBuilder` die de stappen van de workflowuitvoering definieert

## Werking

Wanneer de bovenliggende workflow een stap `run_workflow` bereikt:

1. wordt de workflowuitvoering gestart als een onafhankelijke workflow met een eigen ID
2. wordt de bovenliggende workflow gepauzeerd
3. doorloopt de workflowuitvoering de stappen op de normale manier
4. wordt de uiteindelijke status van de workflowuitvoering samengevoegd met de status van de bovenliggende workflow zodra de workflowuitvoering is voltooid
5. wordt de bovenliggende workflow hervat met de volgende stap

## Status van bovenliggende en onderliggende workflows

De workflowuitvoering ontvangt de huidige verzamelde status van de bovenliggende workflow als initiële payload. Dit betekent dat onderliggende stappen toegang hebben tot alle gegevens die door eerdere stappen van de bovenliggende workflow zijn geproduceerd:

```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 [];
    }
}
```

## Status samenvoegen

Wanneer de workflowuitvoering is voltooid, wordt de uiteindelijke status ervan (met uitzondering van interne sleutels zoals `_steps`, `_queue`, `_priority` en `_max_attempts`) samengevoegd met de status van de bovenliggende workflow. De volgende stap van de bovenliggende workflow ziet alle gegevens van zowel eerdere stappen van de bovenliggende workflow als de workflowuitvoering:

```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 [];
    }
}
```

## Opties voor workflowuitvoering

De `on_queue()`-, `with_priority()`- en `max_attempts()`-opties van de builder voor workflowuitvoering gelden voor de onderliggende workflow. Andere opties op workflowniveau van de builder voor de onderliggende workflow, zoals `on_cancel()`, `prune_state_after()`, `must_complete_within()`, `version()`, `idempotency_key()`, de budgetten voor `max_*()` en `compensate_on_failure()`, worden niet overgenomen:

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

## Geneste workflowuitvoeringen

Workflowuitvoeringen kunnen zelf workflowuitvoeringen bevatten, waardoor willekeurige nesting mogelijk is:

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