
# Workflow-Abhängigkeiten

Nutze Wartevorgänge für Workflow-Abhängigkeiten, wenn ein übergeordneter Workflow erst fortgesetzt werden soll, nachdem andere Workflows abgeschlossen sind. So koordinierst du mehrere Workflows, ohne alles in eine einzige riesige Workflow-Definition zu packen.

Diese Wartevorgänge passen besonders gut zu [asynchronen Übergaben](https://queuety.inline0.dev/de/docs/workflows/async-handoffs): Dabei startet ein Workflow zunächst unabhängige untergeordnete Workflows und wartet später auf sie.

Ausführlichere Beispiele für Planer und Ausführer findest du unter [Agenten-Orchestrierung](https://queuety.inline0.dev/de/docs/workflows/agent-orchestration).

Queuety bietet drei Builder-Methoden:

- `wait_for_workflow()` für einen Workflow
- `wait_for_workflows()` für mehrere Workflows mit `all`-, `any`- oder `quorum`-Semantik
- `wait_for_workflow_group()`, wenn die Workflow-IDs aus einer zuvor gestarteten Gruppe stammen

## Auf einen Workflow warten

```php
$research_id = Queuety::workflow( 'research_run' )
    ->then( PlanResearchStep::class )
    ->for_each( 'tasks', ExecuteResearchTask::class, 'results' )
    ->dispatch( [ 'brief_id' => 42 ] );

$editorial_id = Queuety::workflow( 'editorial_run' )
    ->wait_for_workflow( $research_id, 'research' )
    ->then( DraftBriefStep::class )
    ->dispatch();
```

Wenn `research_run` abgeschlossen ist, wird `editorial_run` fortgesetzt. Ist `result_key` festgelegt, wird der Status der abgeschlossenen Abhängigkeit unter diesem Schlüssel gespeichert:

```php
$state['research']; // public state from the completed research workflow
```

Ohne `result_key` wird der öffentliche Status des abhängigen Workflows mit dem Status auf oberster Ebene des wartenden Workflows zusammengeführt.

## Auf mehrere Workflows warten

```php
use Queuety\Enums\WaitMode;

Queuety::workflow( 'synthesis_run' )
    ->wait_for_workflows(
        [ $research_id, $editorial_id, $legal_id ],
        WaitMode::All,
        'dependencies'
    )
    ->then( PublishPacketStep::class )
    ->dispatch();
```

- `WaitMode::All` wird erst fortgesetzt, wenn alle aufgeführten Workflows abgeschlossen sind.
- `WaitMode::Any` wird fortgesetzt, sobald der erste aufgeführte Workflow abgeschlossen ist.
- `WaitMode::Quorum` wird fortgesetzt, sobald die erforderliche Anzahl von Workflows erfolgreich abgeschlossen ist.

```php
Queuety::workflow( 'synthesis_run' )
    ->wait_for_workflows(
        [ $research_id, $editorial_id, $legal_id ],
        WaitMode::Quorum,
        'dependencies',
        quorum: 2,
    )
    ->then( PublishPacketStep::class )
    ->dispatch();
```

Mit `result_key` werden bei Wartevorgängen auf mehrere Workflows die Status abgeschlossener Abhängigkeiten anhand ihrer Workflow-ID gespeichert:

```php
[
    '42' => [ 'summary' => '...' ],
    '43' => [ 'summary' => '...' ],
]
```

Ohne `result_key` wird der Status der abgeschlossenen Abhängigkeiten entsprechend ihrer Reihenfolge mit dem Status auf oberster Ebene des wartenden Workflows zusammengeführt.

## Abhängigkeits-IDs aus dem Workflow-Status ermitteln

Du kannst die Abhängigkeitsliste bis zur Laufzeit aufschieben und die Workflow-IDs aus dem öffentlichen Status auslesen:

```php
Queuety::workflow( 'agent_follow_up' )
    ->wait_for_workflow( 'parent_workflow_id', 'parent' )
    ->then( FinalizeAgentRunStep::class )
    ->dispatch( [ 'parent_workflow_id' => $workflow_id ] );
```

Für mehrere Abhängigkeiten:

```php
Queuety::workflow( 'aggregator' )
    ->wait_for_workflows( 'dependency_ids', WaitMode::Any, 'winner' )
    ->dispatch( [ 'dependency_ids' => [ 12, 18, 22 ] ] );
```

## Auf eine gestartete Workflow-Gruppe warten

Wenn ein vorheriger Schritt `start_workflows()` oder `start_agents()` einen dauerhaften Gruppenschlüssel gespeichert hat, kannst du direkt auf diese Gruppe warten, statt Workflow-IDs selbst über den öffentlichen Status weiterzugeben.

```php
Queuety::workflow( 'brief_research' )
    ->then( PlanTopicsStep::class )
    ->start_agents( 'agent_tasks', $agent_run, group_key: 'researchers' )
    ->wait_for_agent_group( 'researchers', WaitMode::Quorum, 2, 'agent_results' )
    ->then( SynthesizeBriefStep::class )
    ->dispatch();
```

## Was während des Wartens geschieht

Wenn ein Workflow einen dieser Schritte erreicht, wechselt er in den Status `waiting_for_workflows`. Während des Wartens bleibt kein Worker daran gebunden.

```php
$state = Queuety::workflow_status( $workflow_id );
echo $state->status->value; // 'waiting_for_workflows'
echo $state->wait_type;     // 'workflow'
print_r( $state->waiting_for ); // ['42', '43']
```

Ist eine Abhängigkeit bereits abgeschlossen, bevor der Warteschritt erreicht wird, wird der Workflow sofort fortgesetzt.

## Fehlerverhalten

Wartevorgänge für Workflow-Abhängigkeiten sind auf erfolgreiche Abschlüsse ausgelegt:

- `wait_for_workflow()` und `WaitMode::All` schlagen fehl, wenn eine erforderliche Abhängigkeit fehlschlägt oder abgebrochen wird.
- `WaitMode::Any` schlägt nur fehl, wenn alle Abhängigkeiten einen Endstatus erreicht haben und keine davon erfolgreich abgeschlossen wurde.
- `WaitMode::Quorum` schlägt fehl, wenn die verbleibenden aktiven Workflows das erforderliche Quorum nicht mehr erreichen können.

So eignen sich Workflow-Wartevorgänge für Planer-Ausführer-Systeme, in denen ein Workflow die Arbeit aufteilen und ein anderer auf die Ergebnisse von `all` oder auf den ersten erfolgreich abgeschlossenen Zweig warten kann.
