
# Măsuri de protecție pentru fluxuri de lucru

Fluxurile de lucru de tip agent sunt flexibile, dar facilitează și crearea de execuții duplicate sau generarea unei cantități de lucru mai mari decât cea planificată. Queuety oferă măsuri de protecție simple la nivelul fluxului de lucru, astfel încât să păstrați această flexibilitate fără să pierdeți controlul.

Pentru modelul mai amplu de resurse, care acoperă admiterea lucrătorilor și metadatele privind costul fiecărei sarcini, consultați [Gestionarea resurselor](https://queuety.inline0.dev/ro/docs/features/resource-management).

## Versionarea unei definiții de flux de lucru

Folosiți `version()` pentru a atașa o etichetă de versiune la nivelul aplicației unei definiții de flux de lucru:

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

Versiunea este stocată împreună cu starea fluxului de lucru, expusă prin `workflow_status()`, afișată de `wp queuety workflow status` și inclusă în exporturile fluxului de lucru.

Queuety stochează și o `definition_hash` deterministă pentru fiecare execuție a fluxului de lucru. Hashul este derivat din definiția serializată a fluxului de lucru și este util când trebuie să identificați exact forma fluxului de lucru executat de o rulare în curs după o implementare.

## Faceți expedierea idempotentă

Folosiți `idempotency_key()` când apelanții pot reîncerca aceeași solicitare:

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

Dacă un flux de lucru este expediat din nou cu o cheie deja utilizată, Queuety returnează ID-ul original al fluxului de lucru în loc să creeze o execuție duplicată. Cheile sunt globale pentru toate numele fluxurilor de lucru, așadar includeți numele fluxului în cheie când fluxuri diferite ar putea folosi aceeași cheie.

Acest lucru este deosebit de util pentru:

- endpointuri API care pot fi reîncercate de clienți sau gateway-uri
- consumatori de webhook-uri care pot primi livrări duplicate
- pași de planificare care ar trebui să creeze o singură execuție de orchestrare pentru fiecare entitate externă

Cheile de idempotență sunt stocate în tabelul `queuety_workflow_dispatch_keys`.

## Setarea bugetelor fluxului de lucru

Folosiți bugetele fluxului de lucru pentru a opri execuțiile care depășesc limitele planificate:

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

Limitează numărul de pași ai fluxului de lucru care se pot finaliza înainte ca execuția să eșueze. Este utilă pentru protejarea fluxurilor de lucru cu ramuri dinamice sau care pot reveni în aceeași zonă prin `_next_step`.

### `max_for_each_items()`

Limitează numărul de elemente descoperite în timpul execuției pe care le poate extinde un singur pas `for_each()`. Este utilă pentru sistemele planificator/executor în care un agent ar putea descoperi mult mai multe ramuri de lucru decât s-a intenționat.

### `max_state_bytes()`

Limitează dimensiunea codificată a stării publice a fluxului de lucru. Astfel, fluxurile de lucru de lungă durată nu cresc până ajung blocuri mari, greu de inspectat, exportat sau reîncercat.

### `max_cost_units()`

Limitează unitățile de cost totale consumate de pașii finalizați. Unitățile de cost provin din metadatele pasului sau sarcinii pe care Queuety le rezolvă la adăugarea lucrului în coadă. Lucrul obișnuit al utilizatorului are valoarea implicită `1`, elementele substitutive de orchestrare, precum întârzierile și așteptările, folosesc `0`, iar gestionarele pot seta o valoare pozitivă mai mare prin `config()` sau proprietățile sarcinii. Numai `cost_units` dintr-o definiție de pas poate seta valoarea `0`.

Este util când un flux de lucru poate reveni în aceeași zonă sau poate crea lucrări for-each costisitoare din motive care nu sunt reflectate doar de numărul pașilor. Un planificator care reexecută în mod repetat un apel costisitor către model poate rămâne în limita `max_transitions()`, dar totuși să depășească bugetul de costuri planificat.

### `max_started_workflows()`

Limitează numărul de fluxuri de lucru de nivel superior pe care o execuție le poate porni prin `start_workflows()` sau `start_agents()`. Limita este verificată înainte de expedierea fluxurilor de lucru copil, astfel încât fluxul părinte eșuează fără să creeze parțial un grup care depășește deja bugetul.

Când un buget este depășit, Queuety oprește imediat fluxul de lucru în loc să reîncerce pasul. Există o excepție: când `Queuety::signal()` încheie o așteptare, iar tranziția rezultată depășește un buget, excepția este transmisă apelantului lui `signal()`, inserarea semnalului este anulată, iar fluxul de lucru continuă să aștepte.

## Monitorizarea măsurilor de protecție

Starea fluxului de lucru expune:

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

Payloadul `budget` include limitele configurate și utilizarea curentă, inclusiv dimensiunea actuală, în octeți, a stării publice.

Exemplu:

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