
# Workflows

Workflows opdeler langvarigt arbejde i afgrænsede trin. Hvert trin gemmer sit output i en fælles tilstandsbeholder i databasen. Hvis PHP dør midt i et trin, prøver workerprocessen trinnet igen med al tidligere tilstand intakt.

## Hvad er workflows?

Et workflow er en ordnet sekvens af trin. Hvert trin er en klasse af typen PHP, der modtager den samlede tilstand fra alle foregående trin og returnerer nye data, som flettes ind i tilstanden. Workflowet går frem ét trin ad gangen, og hver overgang er omsluttet af en atomisk transaktion af typen MySQL.

```php
use Queuety\Queuety;

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

## Akkumulering af tilstand

Den oprindelige nyttelast, du sender til `dispatch()`, bliver starttilstanden. Nøglerne, som hvert trin returnerer, flettes ind i tilstanden. Nøgler, der begynder med `_`, er reserveret til kontrolværdier som `_next_step` og flettes ikke ind i den offentlige tilstand:

```
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'}
```

Hvert trin ser hele den akkumulerede tilstand. Det gør det nemt at overføre data mellem trin uden ekstern lagring.

## Mulighed for genoptagelse

Workflows er holdbare, fordi tilstanden gemmes i databasen efter hvert trin. Hvis workerprocessen går ned under trin 1, starter workflowet igen fra trin 1, mens outputtet fra trin 0 allerede er i tilstanden.

Grænsen mellem trinene er en enkelt transaktion af typen MySQL, der atomisk:
1. Opdaterer workflowtilstanden med trinnets output
2. Markerer jobbet for det aktuelle trin som fuldført
3. Sætter jobbet for næste trin i kø

Det sikrer, at ingen tilstand går tabt, heller ikke ved nedbrud, timeout eller fatale fejl af typen PHP.

## Workflowets livscyklus

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

| Status | Beskrivelse |
|---|---|
| `running` | Behandler trin aktivt |
| `completed` | Alle trin er fuldført korrekt |
| `failed` | Et trin fejlede, efter at alle forsøg var brugt |
| `paused` | Sat på pause manuelt. Igangværende arbejde kan blive fuldført, men senere trin sættes ikke i kø, før workflowet genoptages |
| `waiting_for_signal` | Venter på et eksternt signal via `Queuety::signal()` |
| `waiting_for_workflows` | Venter på, at et eller flere andre workflows fuldføres via `wait_for_workflow()` eller `wait_for_workflows()` |
| `cancelled` | Annulleret eksplicit via `Queuety::cancel_workflow()`. Ventende jobs begraves, og en valgfri oprydningsbehandler køres. |

## Administration af workflows

Kontrollér status:

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

Sæt på pause, og genoptag:

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

Prøv et fejlet workflow igen fra det fejlede trin:

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

Annullér et workflow, og kør oprydningsbehandlere:

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

Se [Annullering](https://queuety.inline0.dev/da/docs/workflows/cancellation) for detaljer om oprydningsbehandlere, og hvad der sker, når et workflow annulleres.

## Workflowindstillinger

Angiv kø, prioritet og politik for nye forsøg for alle trin i et 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 );
```

Metoden `on_cancel()` registrerer en oprydningsbehandler, der køres, når workflowet annulleres. Se [Annullering](https://queuety.inline0.dev/da/docs/workflows/cancellation).

Metoden `prune_state_after()` aktiverer automatisk fjernelse af gamle trinoutputs for at holde workflowtilstanden begrænset. Se [Tilstandsbeskæring](https://queuety.inline0.dev/da/docs/features/state-pruning).

Brug `compensate_with()` til at knytte en kompenseringsbehandler til et enkelt trin. Brug `compensate_on_failure()`, når kompenseringer for fuldførte trin automatisk skal køres efter en workflowfejl, ikke kun ved eksplicit annullering. Se [Kompensering](https://queuety.inline0.dev/da/docs/workflows/compensation).

Brug workflowværn, når du har brug for sikrere orkestrering over længere tid: `version()` knytter en applikationsversion til en definition, Queuety gemmer også en deterministisk definitionens hash for hver kørsel, `idempotency_key()` gør afsendelse holdbar på tværs af nye forsøg eller dublerede anmodninger, og `max_transitions()`, `max_for_each_items()` og `max_state_bytes()` får løbske kørsler til at fejle, før de løber løbsk. Se [Værn](https://queuety.inline0.dev/da/docs/workflows/guardrails).

## Trintyper

Queuety understøtter elleve typer trin i et workflow:

- [Sekventielle kæder](https://queuety.inline0.dev/da/docs/workflows/chains) med `->then()` til udførelse ét ad gangen
- [Parallelle grupper](https://queuety.inline0.dev/da/docs/workflows/parallel) med `->parallel()` til samtidig udførelse
- [Dynamisk for-each](https://queuety.inline0.dev/da/docs/workflows/for-each) med `->for_each()` til forgreningsarbejde, der opdages under kørslen, og eksplicitte regler for fuldførelse
- [Asynkrone overleveringer](https://queuety.inline0.dev/da/docs/workflows/async-handoffs) med `->start_workflows()` eller `->start_agents()` til at sende uafhængige underordnede workflows afsted for elementer, der opdages under kørslen
- [Betinget forgrening](https://queuety.inline0.dev/da/docs/workflows/conditional) med navngivne trin og `_next_step`
- [Gentagelser](https://queuety.inline0.dev/da/docs/workflows/repeats) med `->repeat_until()` og `->repeat_while()` til holdbare tilbagekanter til tidligere navngivne trin
- [Kør workflows](https://queuety.inline0.dev/da/docs/workflows/run-workflows) med `->run_workflow()` til indlejret sammensætning
- [Holdbare forsinkelser](https://queuety.inline0.dev/da/docs/workflows/delays) med `->delay()` til tidsbaserede forsinkelser
- [Signaler](https://queuety.inline0.dev/da/docs/workflows/signals) med `->wait_for_signal()`, `->wait_for_signals()`, `->wait_for_approval()`, `->wait_for_input()` og `->wait_for_decision()` til eksterne hændelsesudløsere
- [Workflowafhængigheder](https://queuety.inline0.dev/da/docs/workflows/dependencies) med `->wait_for_workflow()`, `->wait_for_workflows()` og `->wait_for_agents()` til koordinering på tværs af workflows
- [Streamende trin](https://queuety.inline0.dev/da/docs/workflows/streaming) med grænsefladen `StreamingStep` til holdbart chunkbaseret output

## Almindelige mønstre

Hvis du bygger autonome eller delvist autonome systemer, så start med [Agentorkestrering](https://queuety.inline0.dev/da/docs/workflows/agent-orchestration). Her vises, hvordan `for_each()`, `start_agents()`, `wait_for_agents()`, `wait_for_workflow()` og `wait_for_decision()` fungerer sammen i faktiske planner/executor- og menneskelige evalueringsforløb.
