
## Workflows i én fil

Et workflow kan være helt selvstændigt i én PHP-fil. Definér trinklasserne og builderen sammen, læg filen i en mappe, og indlæs mappen med `Queuety::load_workflows()` (vist nedenfor). Queuety scanner ikke selv nogen mapper.

```php
// workflows/onboard-user.php
use Queuety\Queuety;

class CreateAccount implements \Queuety\Step {
    public function handle(array $state): array {
        $user = create_user($state['email']);
        return ['user_id' => $user->id, 'user_name' => $user->name];
    }
    public function config(): array {
        return ['max_attempts' => 3];
    }
}

class SendWelcome implements \Queuety\Step {
    public function handle(array $state): array {
        wp_mail($state['email'], 'Welcome ' . $state['user_name'], '...');
        return ['welcomed' => true];
    }
    public function config(): array {
        return [];
    }
}

return Queuety::define_workflow('onboard_user')
    ->then(CreateAccount::class, 'create_account')
    ->then(SendWelcome::class, 'send_welcome');
```

Filen returnerer en `WorkflowBuilder`. Hver trinklasse defineres inline. Når filen indlæses, bliver klasserne tilgængelige, og workflowet registreres som en skabelon.

## Indlæsning af workflows

Indlæs alle workflowfiler fra en mappe:

```php
// Load all .php files from the workflows directory
$count = Queuety::load_workflows(__DIR__ . '/workflows/');
```

Eller indlæs en enkelt fil:

```php
$template = Queuety::load_workflow_file(__DIR__ . '/workflows/onboard-user.php');
```

Send derefter efter navn:

```php
$workflow_id = Queuety::run_workflow('onboard_user', ['email' => 'user@example.com']);
```

## Rekursiv indlæsning

Angiv `true` som det andet argument for at søge i undermapper:

```php
Queuety::load_workflows(__DIR__ . '/workflows/', recursive: true);
```

Det gør det muligt at organisere workflows i mapper:

```
workflows/
├── onboarding/
│   ├── new-user.php
│   └── trial-upgrade.php
├── reports/
│   ├── daily-summary.php
│   └── weekly-digest.php
└── notifications/
    └── digest-email.php
```

## Brug af alle workflowfunktioner

Filbaserede workflows understøtter alt, hvad builderen understøtter, undtagen `idempotency_key()`, som ikke gemmes i skabelonen. Angiv den pr. dispatch med `Queuety::run_workflow( $name, $payload, [ 'idempotency_key' => '...' ] )` i stedet. Forsinkelser, signaler, parallelle trin, betinget forgrening, run-workflows, annulleringshåndterere og tilstandspruning fungerer alle:

```php
// workflows/approval-flow.php
use Queuety\Queuety;

class SubmitRequest implements \Queuety\Step {
    public function handle(array $state): array {
        return ['submitted_at' => date('Y-m-d H:i:s')];
    }
    public function config(): array { return []; }
}

class ProcessApproval implements \Queuety\Step {
    public function handle(array $state): array {
        return [
            'approved_by' => $state['approved_by'],
            'processed' => true,
        ];
    }
    public function config(): array { return []; }
}

class CleanupRequest implements \Queuety\Handler {
    public function handle(array $payload): void {
        delete_pending_request($payload['request_id']);
    }
    public function config(): array { return []; }
}

return Queuety::define_workflow('approval_flow')
    ->then(SubmitRequest::class)
    ->delay(hours: 24)
    ->wait_for_signal('approved')
    ->then(ProcessApproval::class)
    ->on_cancel(CleanupRequest::class)
    ->prune_state_after(2);
```

## Hvornår skal du bruge filbaserede workflows

Filbaserede workflows er ideelle, når:

- En LLM eller kodegenerator opretter workflows programmatisk
- Et workflow er enkelt nok til at være i én fil
- Du vil holde trinnets logik tæt på workflowdefinitionen
- Du laver en prototype og ønsker hurtige gentagelser

For større workflows med delte trinklasser, kompleks middleware eller trin, der genbruges på tværs af flere workflows, er den almindelige tilgang med separate klassefiler og PSR-4-autoloading lettere at vedligeholde.

## Sådan fungerer det

Filbaserede workflows bruger under motorhjelmen præcis samme motor som builderen API. Hvert trin er et separat job i databasen. Tilstanden flyder gennem tabellen `queuety_workflows`. Der er ingen afspilning, intet krav om determinisme og ingen forskel i ydeevne.

Hvert indlæsningskald `require`'er filen (ikke `require_once`), så indlæs hver fil én gang pr. forespørgsel. Hvis den indlæses to gange, deklareres klasserne igen, og det mislykkes. Den returnerede `WorkflowBuilder` konverteres til en `WorkflowTemplate` og gemmes i `WorkflowRegistry`. Dispatch og kørsel fungerer som for alle andre workflows.
