
# Skyddsräcken för arbetsflöden

Agentliknande arbetsflöden är flexibla, men gör det också lättare att skapa duplicerade körningar eller låta en planerare skapa mer arbete än avsett. Queuety tillhandahåller enkla skyddsräcken på arbetsflödesnivå, så att du kan behålla flexibiliteten utan att förlora kontrollen.

Information om den bredare resursmodellen för att godkänna arbetare och metadata om kostnad per jobb finns i [Resurshantering](https://queuety.inline0.dev/sv/docs/features/resource-management).

## Versionshantera en arbetsflödesdefinition

Använd `version()` för att koppla en versionsetikett på applikationsnivå till en arbetsflödesdefinition:

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

Versionen lagras med arbetsflödets tillstånd, visas via `workflow_status()`, skrivs ut av `wp queuety workflow status` och inkluderas i arbetsflödesexporter.

Queuety lagrar också ett deterministiskt `definition_hash` för varje arbetsflödeskörning. Hashen härleds från den serialiserade arbetsflödesdefinitionen och är användbar när du efter en driftsättning behöver identifiera exakt vilken arbetsflödesstruktur en pågående körning använder.

## Gör dispatch idempotent

Använd `idempotency_key()` när anropare kan försöka skicka samma begäran igen:

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

Om ett arbetsflöde skickas igen med en nyckel som redan har använts returnerar Queuety det ursprungliga arbetsflödets ID i stället för att skapa en duplicerad körning. Nycklar är globala över arbetsflödesnamn, så inkludera arbetsflödets namn i nyckeln när olika arbetsflöden kan dela samma nyckel.

Detta är särskilt användbart för:

- Slutpunkter med API som klienter eller gateways kan försöka anropa igen
- webhook-konsumenter som kan ta emot dubbla leveranser
- planeringssteg som bara ska skapa en orkestreringskörning per extern entitet

Idempotensnycklar lagras i tabellen `queuety_workflow_dispatch_keys`.

## Ange arbetsflödesbudgetar

Använd arbetsflödesbudgetar för att avbryta körningar som överskrider de planerade gränserna:

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

Begränsar hur många arbetsflödessteg som får slutföras innan körningen avbryts. Detta skyddar arbetsflöden som skapar grenar dynamiskt eller kan återvända till samma område via `_next_step`.

### `max_for_each_items()`

Begränsar hur många objekt som upptäcks vid körning och som ett enskilt `for_each()`-steg får expandera. Detta är användbart för system med planerare och exekverare, där en agent kan upptäcka betydligt mer grenarbete än avsett.

### `max_state_bytes()`

Begränsar den kodade storleken på det publika arbetsflödestillståndet. Det hindrar långvariga arbetsflöden från att växa till stora datamängder som är långsamma att granska, exportera eller försöka igen.

### `max_cost_units()`

Begränsar det totala antalet kostnadsenheter som förbrukas av slutförda steg. Kostnadsenheterna hämtas från steg- eller jobbmetadata som Queuety läser in när det köar arbete. Vanligt användararbete har standardvärdet `1`, orkestreringsplatshållare som fördröjningar och väntetider använder `0`, och hanterare kan ange ett högre positivt värde via `config()` eller jobbegenskaper. Endast en stegdefinitions `cost_units` kan ange värdet `0`.

Detta är användbart när ett arbetsflöde kan återvända till samma område eller förgrena sig till arbete som är dyrt på sätt som inte fångas av enbart antalet steg. En planerare som upprepade gånger gör ett kostsamt modellanrop kan hålla sig inom `max_transitions()` men ändå överskrida den avsedda kostnadsbudgeten.

### `max_started_workflows()`

Begränsar hur många arbetsflöden på toppnivå en körning får starta via `start_workflows()` eller `start_agents()`. Gränsen kontrolleras innan underordnade arbetsflöden skickas, så att det överordnade arbetsflödet misslyckas utan att delvis skapa en grupp som redan överskrider budgeten.

När en budget överskrids avbryter Queuety arbetsflödet omedelbart i stället för att göra omförsök med steget. Ett undantag: när `Queuety::signal()` slutför en väntan och den efterföljande övergången överskrider en budget kastas undantaget till anroparen av `signal()`, signalinfogningen återställs och arbetsflödet fortsätter att vänta.

## Övervaka skyddsräcken

Arbetsflödets status visar:

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

Nyttolasten `budget` innehåller konfigurerade gränser och aktuell användning, inklusive storleken i byte på det aktuella publika tillståndet.

Exempel:

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