
# Ochranné mechanizmy workflowov

Workflowy v štýle agentov sú flexibilné, no zároveň uľahčujú vytváranie duplicitných spustení alebo situácií, keď plánovač vytvorí viac práce, než sa zamýšľalo. Queuety poskytuje jednoduché ochranné mechanizmy na úrovni workflowu, vďaka ktorým si zachováte túto flexibilitu bez straty kontroly.

Informácie o širšom modeli zdrojov pre prijímanie úloh pracovníkmi a metadáta o nákladoch jednotlivých úloh nájdete v časti [Správa zdrojov](https://queuety.inline0.dev/sk/docs/features/resource-management).

## Verzovanie definície workflowu

Pomocou `version()` priraďte k definícii workflowu štítok verzie na úrovni aplikácie:

```php
Queuety::workflow( 'research_run' )
    ->version( 'research.v2' )
    ->then( PlanResearchStep::class )
    ->then( DraftResearchSummaryStep::class )
    ->dispatch();
```

Verzia sa ukladá spolu so stavom workflowu, sprístupňuje sa cez `workflow_status()`, vypisuje sa pomocou `wp queuety workflow status` a uvádza sa v exportoch workflowu.

Queuety tiež ukladá deterministický `definition_hash` pre každý beh workflowu. Hash sa odvodzuje zo serializovanej definície workflowu a pomáha presne určiť, aký tvar workflowu vykonáva rozbehnutý beh po nasadení novej verzie.

## Zabezpečenie idempotentného spúšťania

Použite `idempotency_key()`, keď volajúci môžu opakovať tú istú požiadavku:

```php
Queuety::workflow( 'research_run' )
    ->idempotency_key( 'brief:42:research' )
    ->then( PlanResearchStep::class )
    ->dispatch( [ 'brief_id' => 42 ] );
```

Ak sa workflow spustí znova s kľúčom, ktorý už bol použitý, Queuety vráti ID pôvodného workflowu namiesto vytvorenia duplicitného behu. Kľúče sú globálne naprieč názvami workflowov, preto do kľúča zahrňte názov workflowu, ak by ho mohli zdieľať rôzne workflowy.

Je to užitočné najmä pre:

- Koncové body API, pri ktorých klienti alebo brány môžu opakovať požiadavky
- spracovateľov webhookov, ktorí môžu dostať duplicitné doručenia
- plánovacie kroky, ktoré majú pre každú externú entitu vytvoriť iba jedno spustenie orchestrácie

Idempotentné kľúče sa ukladajú do tabuľky `queuety_workflow_dispatch_keys`.

## Nastavenie rozpočtov workflowu

Pomocou rozpočtov workflowu zlyhajú behy, ktoré prekročia stanovené limity:

```php
Queuety::workflow( 'research_run' )
    ->max_transitions( 20 )
    ->max_for_each_items( 12 )
    ->max_state_bytes( 32768 )
    ->max_cost_units( 40 )
    ->max_started_workflows( 8 )
    ->then( PlanResearchStep::class )
    ->for_each( 'tasks', ExecuteResearchTask::class, 'results' )
    ->dispatch();
```

### `max_transitions()`

Obmedzuje počet krokov workflowu, ktoré sa môžu dokončiť pred zlyhaním behu. Je to užitočné na ochranu workflowov, ktoré sa dynamicky vetvia alebo sa môžu vracať do tej istej časti cez `_next_step`.

### `max_for_each_items()`

Obmedzuje počet položiek zistených počas behu, na ktoré sa môže rozšíriť jeden krok `for_each()`. Je to užitočné v systémoch plánovač/vykonávač, v ktorých môže agent objaviť oveľa viac práce pre vetvy, než sa zamýšľalo.

### `max_state_bytes()`

Obmedzuje kódovanú veľkosť verejného stavu workflowu. Pomáha predchádzať tomu, aby sa dlhotrvajúce workflowy rozrástli na veľké objekty, ktorých kontrola, export alebo opakovanie sú pomalé.

### `max_cost_units()`

Obmedzuje celkové nákladové jednotky spotrebované dokončenými krokmi. Nákladové jednotky pochádzajú z metadát kroku alebo úlohy, ktoré Queuety načíta pri zaraďovaní práce do frontu. Bežná práca používateľa má predvolene hodnotu `1`, koordinačné zástupné prvky, napríklad oneskorenia a čakania, používajú `0` a obslužné rutiny môžu nastaviť vyššiu kladnú hodnotu pomocou `config()` alebo vlastností úlohy. Hodnotu `0` môže nastaviť iba `cost_units` definície kroku.

Je to užitočné, keď sa workflow môže vracať do tej istej časti alebo opakovane rozširovať na prácu, ktorej náklady sa nezachytia iba počtom krokov. Plánovač, ktorý opakovane volá drahý model, sa môže zmestiť do limitu `max_transitions()`, no aj tak prekročiť plánovaný rozpočet nákladov.

### `max_started_workflows()`

Obmedzuje počet workflowov najvyššej úrovne, ktoré môže beh spustiť cez `start_workflows()` alebo `start_agents()`. Limit sa kontroluje ešte pred spustením podriadených workflowov, takže nadradený workflow zlyhá bez čiastočného vytvorenia skupiny, ktorá už prekračuje rozpočet.

Pri prekročení rozpočtu Queuety okamžite ukončí workflow ako neúspešný namiesto opakovania kroku. Výnimkou je situácia, keď `Queuety::signal()` ukončí čakanie a výsledný prechod prekročí rozpočet: výnimka sa odovzdá volajúcemu `signal()`, vloženie signálu sa vráti späť a workflow bude naďalej čakať.

## Sledovanie ochranných mechanizmov

Stav workflowu poskytuje:

- `definition_version`
- `definition_hash`
- `idempotency_key`
- `budget`

Údaje `budget` obsahujú nastavené limity aj aktuálne využitie vrátane veľkosti verejného stavu v bajtoch.

Príklad:

```php
$state = Queuety::workflow_status( $workflow_id );

$state->definition_version; // 'research.v2'
$state->definition_hash;    // '4c7a...'
$state->idempotency_key;    // 'brief:42:research'
$state->budget;             // [ 'max_transitions' => 20, ... ]
```
