
# Rularea fluxurilor de lucru

Un flux de lucru poate porni un flux de lucru copil ca unul dintre pașii săi. Părintele se suspendă până când fluxul de lucru rulat se încheie, apoi îmbină starea finală a copilului cu starea părintelui.

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

Metoda `run_workflow()` acceptă două argumente:
1. Un nume pentru fluxul de lucru rulat
2. O instanță `WorkflowBuilder` care definește pașii fluxului de lucru rulat

## Cum funcționează

Când fluxul de lucru părinte ajunge la un pas `run_workflow`:

1. Fluxul de lucru rulat este lansat ca flux de lucru independent, cu propriul ID
2. Fluxul de lucru părinte se suspendă
3. Fluxul de lucru rulat parcurge pașii în mod normal
4. Când fluxul de lucru rulat se încheie, starea sa finală este îmbinată cu starea părintelui
5. Fluxul de lucru părinte continuă cu pasul următor

## Starea părinte/copil

Fluxul de lucru rulat primește starea acumulată curentă a părintelui ca date inițiale. Astfel, pașii copilului pot accesa orice date produse de pașii anteriori ai părintelui:

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

## Îmbinarea stării

Când fluxul de lucru rulat se încheie, starea sa finală (cu excepția cheilor interne precum `_steps`, `_queue`, `_priority`, `_max_attempts`) este îmbinată cu starea părintelui. Pasul următor al părintelui vede toate datele din pașii anteriori ai părintelui și din fluxul de lucru rulat:

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

## Opțiunile fluxului de lucru rulat

Opțiunile `on_queue()`, `with_priority()` și `max_attempts()` ale constructorului fluxului de lucru rulat se aplică fluxului de lucru copil. Alte opțiuni la nivel de flux de lucru din constructorul copil, precum `on_cancel()`, `prune_state_after()`, `must_complete_within()`, `version()`, `idempotency_key()`, limitele `max_*()` și `compensate_on_failure()`, nu sunt preluate:

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

## Fluxuri de lucru rulate imbricate

Fluxurile de lucru rulate pot conține la rândul lor fluxuri de lucru rulate, permițând imbricarea arbitrară:

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