
# Esegui flussi di lavoro

Un flusso di lavoro può avviare un flusso di lavoro figlio come uno dei suoi passaggi. Il flusso principale resta in pausa finché l'esecuzione del flusso figlio non termina, poi unisce lo stato finale di quest'ultimo al proprio stato.

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

Il metodo `run_workflow()` accetta due argomenti:
1. Un nome per il flusso di lavoro eseguito
2. Un'istanza `WorkflowBuilder` che definisce i passaggi del flusso di lavoro eseguito

## Come funziona

Quando il flusso di lavoro principale raggiunge un passaggio `run_workflow`:

1. Il flusso di lavoro eseguito viene avviato come flusso indipendente con un ID proprio
2. Il flusso di lavoro principale viene messo in pausa
3. Il flusso di lavoro eseguito completa normalmente i propri passaggi
4. Al completamento del flusso di lavoro eseguito, il suo stato finale viene unito allo stato del flusso principale
5. Il flusso di lavoro principale riprende dal passaggio successivo

## Stato del flusso principale e del flusso figlio

Il flusso di lavoro eseguito riceve lo stato accumulato corrente del flusso principale come payload iniziale. Ciò significa che i passaggi del flusso figlio possono accedere a tutti i dati prodotti dai passaggi precedenti del flusso principale:

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

## Unione dello stato

Al completamento del flusso di lavoro eseguito, il suo stato finale (escluse le chiavi interne come `_steps`, `_queue`, `_priority` e `_max_attempts`) viene unito allo stato del flusso principale. Il passaggio successivo del flusso principale può accedere a tutti i dati dei passaggi precedenti del flusso principale e del flusso di lavoro eseguito:

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

## Opzioni del flusso di lavoro eseguito

Le opzioni `on_queue()`, `with_priority()` e `max_attempts()` del builder del flusso di lavoro eseguito si applicano al flusso figlio. Le altre opzioni a livello di flusso sul builder del figlio, come `on_cancel()`, `prune_state_after()`, `must_complete_within()`, `version()`, `idempotency_key()`, i limiti `max_*()` e `compensate_on_failure()`, non vengono trasferite:

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

## Flussi di lavoro eseguiti annidati

I flussi di lavoro eseguiti possono contenere a loro volta altri flussi di lavoro eseguiti, consentendo un annidamento arbitrario:

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