
# Spúšťanie pracovných postupov

Pracovný postup môže v jednom zo svojich krokov spustiť podriadený pracovný postup. Nadradený postup sa pozastaví, kým sa vnorený pracovný postup nedokončí, a potom zlúči jeho konečný stav so svojím stavom.

## Metóda `->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' ] );
```

Metóda `run_workflow()` prijíma dva argumenty:
1. Názov vnoreného pracovného postupu
2. Inštanciu `WorkflowBuilder`, ktorá definuje jeho kroky

## Ako to funguje

Keď nadradený pracovný postup dosiahne krok `run_workflow`:

1. Vnorený pracovný postup sa spustí ako nezávislý pracovný postup s vlastným ID
2. Nadradený pracovný postup sa pozastaví
3. Vnorený pracovný postup bežne vykoná svoje kroky
4. Po dokončení vnoreného pracovného postupu sa jeho konečný stav zlúči so stavom nadradeného postupu
5. Nadradený pracovný postup pokračuje ďalším krokom

## Stav nadradeného a podriadeného postupu

Vnorený pracovný postup dostane aktuálny nahromadený stav nadradeného postupu ako počiatočné údaje. Podriadené kroky tak môžu pristupovať k údajom vytvoreným v predchádzajúcich krokoch nadradeného postupu:

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

## Zlučovanie stavu

Po dokončení vnoreného pracovného postupu sa jeho konečný stav (okrem interných kľúčov, ako sú `_steps`, `_queue`, `_priority`, `_max_attempts`) zlúči so stavom nadradeného postupu. Nasledujúci krok nadradeného postupu tak vidí všetky údaje z predchádzajúcich nadradených krokov aj z vnoreného postupu:

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

## Možnosti vnoreného pracovného postupu

Nastavenia `on_queue()`, `with_priority()` a `max_attempts()` v nástroji na zostavovanie pracovných postupov run-workflow sa uplatňujú na podriadený pracovný postup. Ostatné možnosti na úrovni pracovného postupu v nástroji na zostavovanie podriadeného postupu, ako napríklad `on_cancel()`, `prune_state_after()`, `must_complete_within()`, `version()`, `idempotency_key()`, limity `max_*()` a `compensate_on_failure()`, sa neprenášajú:

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

## Vnorené pracovné postupy

Vnorené pracovné postupy môžu samy obsahovať ďalšie vnorené pracovné postupy, čo umožňuje ľubovoľnú úroveň vnorenia:

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