
# Workflow

Workflow rozdělují dlouhotrvající práci na samostatné kroky. Výstup každého kroku se ukládá do společné sady stavových dat v databázi. Pokud PHP během kroku přestane fungovat, worker krok zopakuje se zachováním veškerého předchozího stavu.

## Co jsou workflow?

Workflow je uspořádaná posloupnost kroků. Každý krok je třída PHP, která přijímá nashromážděný stav ze všech předchozích kroků a vrací nová data ke sloučení se stavem. Workflow postupuje po jednom kroku a každý přechod probíhá v atomické transakci MySQL.

```php
use Queuety\Queuety;

$workflow_id = Queuety::workflow( 'generate_report' )
    ->then( FetchDataHandler::class )
    ->then( CallLLMHandler::class )
    ->then( FormatOutputHandler::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

## Shromažďování stavu

Počáteční data, která předáte do `dispatch()`, se stanou výchozím stavem. Vrácené klíče z každého kroku se sloučí se stavem. Klíče začínající na `_` jsou vyhrazené pro řídicí hodnoty, například `_next_step`, a do veřejného stavu se neslučují:

```
dispatch(['user_id' => 42])

Step 0: FetchDataHandler   -> returns ['user_name' => 'Alice']
  state: {user_id: 42, user_name: 'Alice'}

Step 1: CallLLMHandler     -> returns ['llm_response' => '...']
  state: {user_id: 42, user_name: 'Alice', llm_response: '...'}

Step 2: FormatOutputHandler -> returns ['report_url' => '/reports/42.pdf']
  state: {user_id: 42, user_name: 'Alice', llm_response: '...', report_url: '/reports/42.pdf'}
```

Každý krok vidí celý nashromážděný stav. Díky tomu lze snadno předávat data mezi kroky bez externího úložiště.

## Možnost obnovení

Workflow jsou odolná, protože se stav po každém kroku ukládá do databáze. Pokud worker během kroku 1 spadne, workflow se restartuje od kroku 1 a výstup kroku 0 už má ve stavu uložený.

Hranici kroku tvoří jediná transakce MySQL, která atomicky:
1. Aktualizuje stav workflow výstupem kroku
2. Označí úlohu aktuálního kroku jako dokončenou
3. Zařadí do fronty úlohu dalšího kroku

Tím je zajištěno, že se žádný stav neztratí ani při pádech, vypršení časového limitu nebo fatálních chybách PHP.

## Životní cyklus workflow

```
dispatch() -> running -> step 0 -> step 1 -> ... -> step N -> completed
                  |                   |
                  |                   +-> failed -> retry -> running (from failed step)
                  |
                  +-> paused -> resumed -> running
                  |
                  +-> waiting_for_signal -> signal received -> running
                  |
                  +-> waiting_for_workflows -> dependency settles -> running
                  |
                  +-> cancelled (via cancel_workflow)
```

| Stav | Popis |
|---|---|
| `running` | Aktivně zpracovává kroky |
| `completed` | Všechny kroky byly úspěšně dokončeny |
| `failed` | Krok selhal po vyčerpání opakovaných pokusů |
| `paused` | Ručně pozastaveno. Aktuálně probíhající práce může doběhnout, ale další kroky se nezařadí do fronty, dokud workflow neobnovíte |
| `waiting_for_signal` | Čeká na externí signál prostřednictvím `Queuety::signal()` |
| `waiting_for_workflows` | Čeká na dokončení jednoho nebo více dalších workflow prostřednictvím `wait_for_workflow()` nebo `wait_for_workflows()` |
| `cancelled` | Výslovně zrušeno prostřednictvím `Queuety::cancel_workflow()`. Čekající úlohy jsou odloženy a spustí se volitelná obslužná funkce pro úklid. |

## Správa workflow

Zkontrolujte stav:

```php
$state = Queuety::workflow_status( $workflow_id );
echo $state->status->value;   // 'running'
echo $state->current_step;    // 1
echo $state->total_steps;     // 3
print_r( $state->waiting_for ); // ['42'] while waiting on another workflow
print_r( $state->wait_details ); // matched/remaining blockers, result key, correlation info
```

Pozastavení a obnovení:

```php
Queuety::pause_workflow( $workflow_id );
Queuety::resume_workflow( $workflow_id );
```

Opakování neúspěšného workflow od kroku, který selhal:

```php
Queuety::retry_workflow( $workflow_id );
```

Zrušení workflow a spuštění obslužných funkcí pro úklid:

```php
Queuety::cancel_workflow( $workflow_id );
```

Podrobnosti o obslužných funkcích pro úklid a o tom, co se stane při zrušení workflow, najdete v části [Zrušení](https://queuety.inline0.dev/cs/docs/workflows/cancellation).

## Možnosti workflow

Nastavení fronty, priority a chování při opakování pro všechny kroky workflow:

```php
use Queuety\Enums\Priority;

Queuety::workflow( 'important_pipeline' )
    ->on_queue( 'pipelines' )
    ->with_priority( Priority::High )
    ->max_attempts( 5 )
    ->on_cancel( PipelineCleanupHandler::class )
    ->prune_state_after( 3 )
    ->then( StepA::class )
    ->then( StepB::class )
    ->dispatch( $payload );
```

Metoda `on_cancel()` registruje obslužnou funkci pro úklid, která se spustí při zrušení workflow. Viz [Zrušení](https://queuety.inline0.dev/cs/docs/workflows/cancellation).

Metoda `prune_state_after()` zapne automatické odebírání starých výstupů kroků, aby velikost stavu workflow zůstala omezená. Viz [Pročišťování stavu](https://queuety.inline0.dev/cs/docs/features/state-pruning).

Pomocí `compensate_with()` připojíte obslužnou funkci pro kompenzaci ke konkrétnímu kroku. Použijte `compensate_on_failure()`, chcete-li kompenzace dokončených kroků spouštět automaticky po selhání workflow, nejen při výslovném zrušení. Viz [Kompenzace](https://queuety.inline0.dev/cs/docs/workflows/compensation).

Ochranné prvky workflow použijte, když potřebujete bezpečnější dlouhotrvající orchestraci: `version()` označí definici verzí na úrovni aplikace, Queuety navíc ukládá pro každý běh deterministický hash definice, `idempotency_key()` zajišťuje odolnost spouštění při opakovaných pokusech nebo duplicitních požadavcích a `max_transitions()`, `max_for_each_items()` a `max_state_bytes()` ukončí neřízené běhy chybou dřív, než se vymknou kontrole. Viz [Ochranné prvky](https://queuety.inline0.dev/cs/docs/workflows/guardrails).

## Typy kroků

Queuety podporuje v rámci workflow jedenáct typů kroků:

- [Sekvenční řetězce](https://queuety.inline0.dev/cs/docs/workflows/chains) používají `->then()` pro postupné spouštění
- [Paralelní skupiny](https://queuety.inline0.dev/cs/docs/workflows/parallel) používají `->parallel()` pro souběžné spouštění
- [Dynamické iterace](https://queuety.inline0.dev/cs/docs/workflows/for-each) používají `->for_each()` pro práci ve větvích zjištěnou za běhu a výslovné potvrzení dokončení
- [Asynchronní předávání](https://queuety.inline0.dev/cs/docs/workflows/async-handoffs) používají `->start_workflows()` nebo `->start_agents()` ke spuštění nezávislých podřízených workflow z položek zjištěných za běhu
- [Podmíněné větvení](https://queuety.inline0.dev/cs/docs/workflows/conditional) používá pojmenované kroky a `_next_step`
- [Opakování](https://queuety.inline0.dev/cs/docs/workflows/repeats) používá `->repeat_until()` a `->repeat_while()` pro trvalé návraty k dřívějším pojmenovaným krokům
- [Spouštění workflow](https://queuety.inline0.dev/cs/docs/workflows/run-workflows) používá `->run_workflow()` pro vnořené skládání
- [Trvalé prodlevy](https://queuety.inline0.dev/cs/docs/workflows/delays) používají `->delay()` pro časové prodlevy
- [Signály](https://queuety.inline0.dev/cs/docs/workflows/signals) používají `->wait_for_signal()`, `->wait_for_signals()`, `->wait_for_approval()`, `->wait_for_input()` a `->wait_for_decision()` ke spouštění externími událostmi
- [Závislosti workflow](https://queuety.inline0.dev/cs/docs/workflows/dependencies) používají `->wait_for_workflow()`, `->wait_for_workflows()` a `->wait_for_agents()` ke koordinaci mezi workflow
- [Kroky s průběžným výstupem](https://queuety.inline0.dev/cs/docs/workflows/streaming) používají rozhraní `StreamingStep` pro trvalý výstup po částech

## Běžné vzory

Pokud vytváříte autonomní nebo částečně autonomní systémy, začněte částí [Orchestrace agentů](https://queuety.inline0.dev/cs/docs/workflows/agent-orchestration). Ukazuje, jak `for_each()`, `start_agents()`, `wait_for_agents()`, `wait_for_workflow()` a `wait_for_decision()` spolupracují v reálných postupech planner/executor a při lidské kontrole.
