
# Kør workflows

Et workflow kan starte et underordnet workflow som et af sine trin. Det overordnede workflow sættes på pause, indtil kørslen af det underordnede workflow er fuldført. Derefter flettes det underordnede workflows endelige tilstand ind i det overordnede workflows tilstand.

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

Metoden `run_workflow()` tager to argumenter:
1. Et navn til kørslen af workflowet
2. En instans af `WorkflowBuilder`, der definerer trinene i kørslen

## Sådan fungerer det

Når det overordnede workflow når et trin af typen `run_workflow`:

1. Sendes kørslen af workflowet afsted som et uafhængigt workflow med sit eget ID
2. Sættes det overordnede workflow på pause
3. Kører det underordnede workflow sine trin som normalt
4. Når kørslen af workflowet er fuldført, flettes dets endelige tilstand ind i det overordnede workflows tilstand
5. Genoptager det overordnede workflow kørslen med næste trin

## Tilstanden for overordnet og underordnet workflow

Kørslen af det underordnede workflow modtager det overordnede workflows aktuelle akkumulerede tilstand som sin oprindelige nyttelast. Det betyder, at underordnede trin kan tilgå data, der er produceret af tidligere trin i det overordnede workflow:

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

## Sammenfletning af tilstand

Når kørslen af det underordnede workflow er fuldført, flettes dets endelige tilstand (undtagen interne nøgler som `_steps`, `_queue`, `_priority`, `_max_attempts`) ind i det overordnede workflows tilstand. Det næste trin i det overordnede workflow kan se alle data fra både tidligere overordnede trin og kørslen af det underordnede workflow:

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

## Indstillinger for kørsel af workflow

Builderens `on_queue()`, `with_priority()` og `max_attempts()` for kørslen af workflowet gælder det underordnede workflow. Andre workflowindstillinger på den underordnede builder, såsom `on_cancel()`, `prune_state_after()`, `must_complete_within()`, `version()`, `idempotency_key()`, `max_*()`-budgetterne og `compensate_on_failure()`, overføres ikke:

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

## Indlejrede kørsler af workflows

Kørsler af workflows kan selv indeholde kørsler af workflows, så de kan indlejres vilkårligt:

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