
# Työnkulun suojaukset

Agenttimaiset työnkulut ovat joustavia, mutta niissä on myös helpompi luoda päällekkäisiä suorituksia tai antaa suunnittelijan tuottaa suunniteltua enemmän työtä. Queuety tarjoaa kevyitä työnkulkutason suojauksia, joiden avulla voit säilyttää joustavuuden menettämättä hallintaa.

Työntekijöiden hyväksyntää ja työkohtaisia kustannusmetatietoja koskeva laajempi resurssimalli on kuvattu kohdassa [Resurssien hallinta](https://queuety.inline0.dev/fi/docs/features/resource-management).

## Työnkulun määrityksen versiointi

Käytä toimintoa `version()` liittääksesi työnkulun määritykseen sovellustason version tunnisteen:

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

Versio tallennetaan työnkulun tilan yhteyteen, se on saatavilla toiminnon `workflow_status()` kautta, tulostetaan toiminnolla `wp queuety workflow status` ja sisällytetään työnkulun vientitiedostoihin.

Queuety tallentaa myös jokaiselle työnkulun suoritukselle deterministisen arvon `definition_hash`. Tiiviste muodostetaan sarjallistetusta työnkulun määrityksestä, ja sen avulla voi tunnistaa tarkasti, mitä työnkulun rakennetta käynnissä oleva suoritus käyttää käyttöönoton jälkeen.

## Lähetyksen tekeminen idempotentiksi

Käytä toimintoa `idempotency_key()`, kun kutsuja saattaa yrittää samaa pyyntöä uudelleen:

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

Jos työnkulku lähetetään uudelleen avaimella, jota on jo käytetty, Queuety palauttaa alkuperäisen työnkulun tunnuksen uuden suorituksen luomisen sijaan. Avaimet ovat yleisiä kaikille työnkulkujen nimille, joten sisällytä työnkulun nimi avaimeen, jos eri työnkuluilla voi olla sama avain.

Tämä on erityisen hyödyllistä seuraaville:

- API-päätepisteet, joiden pyyntöjä asiakkaat tai yhdyskäytävät voivat yrittää uudelleen
- webhook-kuluttajat, jotka voivat vastaanottaa kaksoistoimituksia
- suunnittelijavaiheet, joiden pitäisi luoda vain yksi orkestrointisuoritus ulkoista kohdetta kohti

Idempotenssiavaimet tallennetaan tauluun `queuety_workflow_dispatch_keys`.

## Työnkulun budjettien asettaminen

Käytä työnkulun budjetteja epäonnistuaksesi suoritukset, jotka ylittävät niille suunnitellut rajat:

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

Rajoittaa, kuinka monta työnkulun vaihetta voi valmistua ennen suorituksen epäonnistumista. Tästä on hyötyä suojattaessa työnkulkuja, jotka haarautuvat dynaamisesti tai voivat palata samaan kohtaan toiminnon `_next_step` kautta.

### `max_for_each_items()`

Rajoittaa, kuinka moneksi ajonaikaisesti löydetyksi kohteeksi yksittäinen `for_each()`-vaihe voi laajentua. Tämä on hyödyllistä suunnittelija/suorittaja-järjestelmissä, joissa agentti saattaa löytää huomattavasti suunniteltua enemmän haaratyötä.

### `max_state_bytes()`

Rajoittaa julkisen työnkulun tilan koodattua kokoa. Tämä auttaa estämään pitkäkestoisia työnkulkuja kasvamasta suuriksi kokonaisuuksiksi, joiden tarkastelu, vienti tai uudelleenyritys on hidasta.

### `max_cost_units()`

Rajoittaa valmistuneiden vaiheiden kuluttamien kustannusyksiköiden kokonaismäärää. Kustannusyksiköt saadaan vaiheen tai työn metatiedoista, jotka Queuety ratkaisee lisätessään työn jonoon. Tavallinen käyttäjätyö käyttää oletusarvoa `1`, orkestroinnin paikkamerkit, kuten viiveet ja odotukset, käyttävät arvoa `0`, ja käsittelijät voivat asettaa suuremman positiivisen arvon toiminnolla `config()` tai työn ominaisuuksissa. Vain vaihemäärityksen `cost_units` voi asettaa arvon `0`.

Tästä on hyötyä, kun työnkulku voi palata samaan kohtaan tai laajentaa for-each-vaiheen töiksi, joiden kustannukset eivät käy ilmi pelkästä vaiheiden määrästä. Kalliita mallikutsuja jatkuvasti toistava suunnittelija voi pysyä rajan `max_transitions()` sisällä ja silti ylittää tarkoitetun kustannusrajan.

### `max_started_workflows()`

Rajoittaa ylätason työnkulkujen määrää, jonka suoritus voi käynnistää toiminnon `start_workflows()` tai `start_agents()` kautta. Raja tarkistetaan ennen alityönkulkujen lähettämistä, joten ylätason työnkulku epäonnistuu luomatta osittain ryhmää, joka ylittää budjetin.

Kun budjetti ylittyy, Queuety epäonnistuttaa työnkulun heti vaiheen uudelleenyrityksen sijaan. Poikkeus: kun `Queuety::signal()` päättää odotuksen ja siitä seuraava siirtymä ylittää budjetin, poikkeus välitetään toiminnon `signal()` kutsujalle, signaalin lisäys perutaan ja työnkulku jää odottamaan.

## Suojausten seuranta

Työnkulun tila sisältää:

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

`budget`-hyötykuorma sisältää määritetyt rajat ja nykyisen käytön, mukaan lukien julkisen tilan nykyisen koon tavuina.

Esimerkki:

```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, ... ]
```
