
# Párhuzamos lépések

Előfordul, hogy több lépés egyszerre is futhat. A `->parallel()` metódus egy kezelőcsoportot indít el egyidejűleg. A munkafolyamat csak akkor halad tovább, ha az összes párhuzamos kezelő befejeződött.

## A `->parallel()` metódus

```php
use Queuety\Queuety;

Queuety::workflow( 'enrich_profile' )
    ->then( FetchUserHandler::class )
    ->parallel( [
        FetchSocialProfileHandler::class,
        FetchPaymentHistoryHandler::class,
        FetchActivityLogHandler::class,
    ] )
    ->then( MergeAndSaveHandler::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

Ebben a példában:
1. Először a `FetchUserHandler` fut le (sorosan)
2. Három kezelő fut egyidejűleg (párhuzamosan)
3. A `MergeAndSaveHandler` csak mindhárom befejezése után fut le (sorosan)

## Működés

Amikor a rendszer egy párhuzamos lépéshez ér, a Queuety minden kezelőhöz külön feladatot indít a csoportban. Minden feladat megkapja az aktuális munkafolyamat-állapotot, és önállóan fut. A munkafolyamat nyomon követi a még futó párhuzamos feladatok számát, és csak akkor lép tovább, amikor mindegyik befejeződött.

Minden párhuzamos kezelő visszatérési értéke egyesül a munkafolyamat állapotával. Ha több kezelő ugyanazt a kulcsot adja vissza, az utoljára befejeződő értéke érvényesül.

## Állapotok egyesítése

Minden párhuzamos kezelő olyan adatokat ad vissza, amelyek egyesülnek a munkafolyamat közös állapotával:

```php
class FetchSocialProfileHandler implements Step {
    public function handle( array $state ): array {
        $profile = fetch_social_api( $state['user_id'] );
        return [ 'social_profile' => $profile ];
    }

    public function config(): array {
        return [];
    }
}

class FetchPaymentHistoryHandler implements Step {
    public function handle( array $state ): array {
        $payments = fetch_payment_api( $state['user_id'] );
        return [ 'payment_history' => $payments ];
    }

    public function config(): array {
        return [];
    }
}
```

A párhuzamos lépés befejeződése után az állapot a `social_profile` és a `payment_history` értékét is tartalmazza, a következő soros lépés pedig mindkettőhöz hozzáfér.

## Soros és párhuzamos lépések vegyesen

Szabadon vegyítheti a `->then()` és a `->parallel()` hívásokat:

```php
Queuety::workflow( 'complex_pipeline' )
    ->then( SetupHandler::class )               // sequential
    ->parallel( [ TaskA::class, TaskB::class ] ) // parallel
    ->then( IntermediateHandler::class )         // sequential
    ->parallel( [ TaskC::class, TaskD::class ] ) // parallel
    ->then( FinalizeHandler::class )             // sequential
    ->dispatch( $payload );
```

## Hibakezelés

Ha egy párhuzamos csoport bármelyik kezelője meghiúsul, a munkafolyamat az adott kezelőre vonatkozó szokásos újrapróbálkozási logikát követi. A többi, már befejeződött párhuzamos kezelő nem fut le újra. A sikertelen kezelő sikeres futása után a munkafolyamat továbbhalad. Ha az újrapróbálkozások kimerítése után is sikertelen, a feladat parkoltatásra kerül, a munkafolyamat pedig sikertelenként lesz megjelölve, a fennmaradó ágak feladatai pedig szintén parkoltatásra kerülnek; a sikertelen lépés újbóli futtatásához használja a `retry_workflow()` lehetőséget.
