
# Aan de slag

## Installatie

### Vereisten

- PHP 8.2 of hoger en WordPress 6.4 of hoger
- MySQL 8.0+ of MariaDB 10.6+. Workers claimen taken en vervallen schema's met `SELECT ... FOR UPDATE SKIP LOCKED`, wat oudere servers met een syntaxisfout afwijzen.
- `mysqli` of `pdo_mysql` (zie hieronder)
- WP-CLI op de server als u speciale workers met `wp queuety work` uitvoert
- De extensies `pcntl` en `posix` PHP als u workerpools uitvoert met `--workers` of `--min-workers`/`--max-workers`

Queuety vereist `mysqli` of `pdo_mysql` in de runtime van PHP die WordPress en WP-CLI laadt. Het kiest automatisch de driver: bij voorkeur `mysqli` voor runtimes van WordPress, terwijl `pdo_mysql` beschikbaar blijft voor zelfstandig of rechtstreeks runtimegebruik.

Zie [Zelfstandig gebruik](https://queuety.inline0.dev/nl/docs/features/standalone-use) als u de op een database gebaseerde runtime zonder de pluginlaag van WordPress wilt gebruiken. Dit pad gebruikt dezelfde verbinding en runtimetabellen, maar bevat geen WordPress-hookbridges of WP-CLI-registratie.

### Vanuit het release-zipbestand

Elke [GitHub-release](https://github.com/inline0/queuety/releases) bevat een `queuety.zip`-bestand: de plugin met de afhankelijkheden van Composer al geïnstalleerd. Installeer de nieuwste versie met WP-CLI:

```bash
wp plugin install https://github.com/inline0/queuety/releases/latest/download/queuety.zip --activate
```

U kunt het zipbestand ook downloaden en uploaden via Plugins > Nieuwe plugin toevoegen > Plugin uploaden. Dit is de eenvoudigste manier voor een gewone WordPress-site.

### Via Composer voor door Composer beheerde WordPress

```bash
composer require queuety/queuety
```

Activeer vervolgens de plugin:

```bash
wp plugin activate queuety
```

Het pakkettype is `wordpress-plugin`. Composer plaatst het alleen in uw pluginmap als het project `composer/installers` vereist en dat type aan een installatiepad koppelt, zoals Bedrock doet. Het project moet ook zijn eigen `vendor/autoload.php` laden (Bedrock doet dat eveneens). Zonder `composer/installers` installeert Composer het in `vendor/queuety/queuety`, waar WordPress het niet kan vinden. Gebruik daarom het release-zipbestand voor een gewone WordPress-installatie.

### Vanuit de broncode tijdens de ontwikkeling

Plaats de repository in `wp-content/plugins/queuety` en installeer vervolgens de afhankelijkheden van PHP:

```bash
composer install
wp plugin activate queuety
```

Bij activatie maakt Queuety de databasetabellen aan (`queuety_jobs`, `queuety_workflows`, `queuety_logs`, `queuety_schedules`, `queuety_queue_states`, `queuety_webhooks`, `queuety_locks`, `queuety_signals`, `queuety_workflow_dependencies`, `queuety_workflow_dispatch_keys`, `queuety_batches`, `queuety_chunks`, `queuety_workflow_events`, `queuety_artifacts`, `queuety_state_machines`, `queuety_state_machine_events`), zodat workers taken rechtstreeks uit MySQL kunnen claimen.

Standaard plant de plugin ook elke minuut via WordPress cron een eenmalige worker in voor de `default`-wachtrij. Zo hebt u een basisoplossing zonder shell voor taken en workflows die op `default` blijven, zolang WordPress cron wordt uitgevoerd. Elke run verwerkt maximaal één taak. Terugkerende schema's worden niet uitgevoerd, verouderde taken worden niet hersteld en workflowdeadlines worden niet gecontroleerd; dat gebeurt alleen binnen een langlopend `wp queuety work`-proces ([#14](https://github.com/inline0/queuety/issues/14)). Gebruik speciale `wp queuety work`-processen voor aangepaste wachtrijen, terugkerende schema's, lagere latentie of zwaardere workloads.

## Configuratie

Alle constanten zijn optioneel. Definieer ze in `wp-config.php` voordat de plugin wordt geladen, of voordat Queuety wordt gestart bij een installatie waarin deze in een thema is ingebed:

| Constante | Standaardwaarde | Beschrijving |
|---|---|---|
| `QUEUETY_RETENTION_DAYS` | `7` | Standaardleeftijd in dagen voor `wp queuety purge` en `Queuety::purge()`. Er wordt niets automatisch opgeschoond |
| `QUEUETY_LOG_RETENTION_DAYS` | `0` | Wordt gelezen door `Config::log_retention_days()`, maar nog niet gebruikt; logs worden bewaard totdat u `Queuety::purge_logs()` aanroept ([#15](https://github.com/inline0/queuety/issues/15)) |
| `QUEUETY_MAX_EXECUTION_TIME` | `300` | Maximumaantal seconden per taak voordat de time-out ingaat (nog niet afgedwongen, zie [Taken](https://queuety.inline0.dev/nl/docs/jobs#timeout)) |
| `QUEUETY_WORKER_SLEEP` | `1` | Aantal seconden slaapstand wanneer de wachtrij leeg is |
| `QUEUETY_WORKER_MAX_JOBS` | `1000` | Maximumaantal taken voordat de worker opnieuw wordt gestart |
| `QUEUETY_WORKER_MAX_MEMORY` | `128` | Maximumaantal MB voordat de worker opnieuw wordt gestart |
| `QUEUETY_RETRY_BACKOFF` | `exponential` | Herhaalstrategie: `exponential`, `linear` of `fixed` |
| `QUEUETY_STALE_TIMEOUT` | `600` | Aantal seconden voordat vastgelopen taken worden hersteld |
| `QUEUETY_CACHE_TTL` | `5` | Standaardcache-TTL in seconden |
| `QUEUETY_DEBUG` | `false` | Uitgebreide logging voor workers inschakelen |
| `QUEUETY_CLI_COMMAND` | `queuety` | Naam van het hoofdcommando van WP-CLI |
| `QUEUETY_TABLE_PREFIX` | `queuety_` | Gedeelde basisnaam voor alle Queuety-tabellen na het WordPress-databaseprefix |
| `QUEUETY_TABLE_JOBS` | `queuety_jobs` | Naam van de takentabel |
| `QUEUETY_TABLE_WORKFLOWS` | `queuety_workflows` | Naam van de workflowtabel |
| `QUEUETY_TABLE_LOGS` | `queuety_logs` | Naam van de logtabel |
| `QUEUETY_TABLE_SCHEDULES` | `queuety_schedules` | Naam van de schematabel |
| `QUEUETY_TABLE_SIGNALS` | `queuety_signals` | Naam van de signaaltabel |
| `QUEUETY_TABLE_WORKFLOW_DEPENDENCIES` | `queuety_workflow_dependencies` | Naam van de tabel met workflowafhankelijkheidswachttijden |
| `QUEUETY_TABLE_WORKFLOW_DISPATCH_KEYS` | `queuety_workflow_dispatch_keys` | Tabelnaam voor idempotentie van duurzame workflows |
| `QUEUETY_TABLE_CHUNKS` | `queuety_chunks` | Naam van de tabel met streamingchunks |
| `QUEUETY_TABLE_QUEUE_STATES` | `queuety_queue_states` | Naam van de tabel met wachtrijstatussen |
| `QUEUETY_TABLE_WEBHOOKS` | `queuety_webhooks` | Naam van de webhooktabel |
| `QUEUETY_TABLE_LOCKS` | `queuety_locks` | Naam van de vergrendelingstabel |
| `QUEUETY_TABLE_BATCHES` | `queuety_batches` | Naam van de batchtabel |
| `QUEUETY_TABLE_WORKFLOW_EVENTS` | `queuety_workflow_events` | Naam van de workflowgebeurtenislogtabel |
| `QUEUETY_TABLE_ARTIFACTS` | `queuety_artifacts` | Naam van de workflowartefactentabel |
| `QUEUETY_TABLE_STATE_MACHINES` | `queuety_state_machines` | Naam van de statemachinetabel |
| `QUEUETY_TABLE_STATE_MACHINE_EVENTS` | `queuety_state_machine_events` | Naam van de gebeurtenislogtabel voor statemachines |
| `QUEUETY_DB_DRIVER` | `auto` | Driver voor MySQL: `auto`, `mysqli` of `pdo`. `auto` geeft de voorkeur aan `mysqli` wanneer WordPress is geladen; anders aan `pdo_mysql` en vervolgens aan `mysqli` |

Resourcebeheer en constanten voor adaptieve pools (`QUEUETY_RESOURCE_*`, `QUEUETY_WORKER_POOL_*`) staan op de pagina [Workers](https://queuety.inline0.dev/nl/docs/features/workers).

`QUEUETY_TABLE_PREFIX` wijzigt alleen het Queuety-gedeelte van de tabelnamen. Het databaseprefix van WordPress blijft ervoor staan, dus `$wpdb->prefix = 'wp_'` en `QUEUETY_TABLE_PREFIX = 'themequeue_'` leveren tabellen op zoals `wp_themequeue_jobs`. Expliciete constanten van `QUEUETY_TABLE_*` hebben voor afzonderlijke tabellen nog steeds voorrang.

Zelfstandige verbindingen kunnen ook per verbinding het tabelprefix van Queuety instellen:

```php
$conn = new Connection(
    host: '127.0.0.1:3306',
    dbname: 'wordpress',
    user: 'root',
    password: 'secret',
    prefix: 'wp_',
    table_prefix: 'themequeue_',
);
```

Zo blijft het databaseprefix van WordPress intact en wordt alleen het Queuety-tabelgedeelte gewijzigd.

## Uw eerste taak

Maak een handlerklasse die de interface `Handler` implementeert:

```php
use Queuety\Handler;

class SendEmailHandler implements Handler {
    public function handle( array $payload ): void {
        wp_mail( $payload['to'], $payload['subject'], $payload['body'] );
    }

    public function config(): array {
        return [
            'queue'           => 'emails',
            'max_attempts'    => 5,
        ];
    }
}
```

Registreer de handler en verstuur een taak:

```php
use Queuety\Queuety;

Queuety::register( 'send_email', SendEmailHandler::class );

Queuety::dispatch( 'send_email', [
    'to'      => 'user@example.com',
    'subject' => 'Welcome',
    'body'    => 'Hello from Queuety!',
] );
```

Of gebruik de moderne dispatchbare taakkklasse:

```php
use Queuety\Contracts\Job;
use Queuety\Dispatchable;

readonly class SendEmailJob implements Job {
    use Dispatchable;

    public function __construct(
        public string $to,
        public string $subject,
        public string $body,
    ) {}

    public function handle(): void {
        wp_mail( $this->to, $this->subject, $this->body );
    }
}

SendEmailJob::dispatch( 'user@example.com', 'Welcome', 'Hello from Queuety!' );
```

## Uw eerste workflow

Definieer staphandlers die de interface `Step` implementeren:

```php
use Queuety\Step;

class FetchDataHandler implements Step {
    public function handle( array $state ): array {
        $user = get_user_by( 'ID', $state['user_id'] );
        return [ 'user_name' => $user->display_name ];
    }

    public function config(): array {
        return [];
    }
}

class CallLLMHandler implements Step {
    public function handle( array $state ): array {
        $response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [
            'body' => json_encode( [ 'prompt' => "Generate report for {$state['user_name']}" ] ),
        ] );
        return [ 'llm_response' => wp_remote_retrieve_body( $response ) ];
    }

    public function config(): array {
        return [ 'max_attempts' => 5 ];
    }
}

class FormatOutputHandler implements Step {
    public function handle( array $state ): array {
        $url = save_report( $state['user_name'], $state['llm_response'] );
        return [ 'report_url' => $url ];
    }

    public function config(): array {
        return [];
    }
}
```

Verstuur de workflow:

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

## Een worker starten

```bash
wp queuety work
```

De worker zoekt naar openstaande taken, voert ze uit, zet workflows voort en wacht wanneer de wachtrij leeg is. Druk op `Ctrl+C` om te stoppen; het proces wordt dan onmiddellijk beëindigd, zelfs midden in een taak (zie [Workers](https://queuety.inline0.dev/nl/docs/features/workers#worker-lifecycle)).

De `SendEmailHandler` hierboven stuurt taken via `config()` naar de wachtrij `emails`, dus een worker voor `default` pakt ze niet op. Geef elke wachtrij die u gebruikt een naam:

```bash
wp queuety work --queue=emails,default
```

Als u geen speciale worker uitvoert, heeft Queuety nog steeds de hierboven beschreven standaardfallback: eenmaal per minuut via WordPress cron, beperkt tot de wachtrij `default` en één taak per run. De speciale worker biedt een hogere verwerkingscapaciteit en lagere latentie.

Voer voor productie meerdere workers uit:

```bash
wp queuety work --workers=4
```

Verwerk meerdere wachtrijen op volgorde van prioriteit:

```bash
wp queuety work --queue=high,default,low
```

## Wat nu?

- [Taken](https://queuety.inline0.dev/nl/docs/jobs) voor de complete gids voor het versturen van taken en handlers
- [Workflows](https://queuety.inline0.dev/nl/docs/workflows) voor ketens, parallelle stappen, vertakkingen op basis van voorwaarden en run-workflows
- [Middleware](https://queuety.inline0.dev/nl/docs/features/middleware) voor snelheidslimieten, throttling en aangepaste pijplijnlogica
- [Batchverwerking](https://queuety.inline0.dev/nl/docs/features/batching) voor het versturen van groepen taken met callbacks
- [Streamingstappen](https://queuety.inline0.dev/nl/docs/workflows/streaming) voor het opslaan van gestreamde gegevens, chunk voor chunk
- [Planning](https://queuety.inline0.dev/nl/docs/features/scheduling) voor terugkerende taken
- [Caching](https://queuety.inline0.dev/nl/docs/features/caching) voor de uitbreidbare cachelaag
- [Testen](https://queuety.inline0.dev/nl/docs/features/testing) voor QueueFake en testasserties
- [CLI naslag](https://queuety.inline0.dev/nl/docs/cli) voor alle beschikbare commando's
- [PHP API](https://queuety.inline0.dev/nl/docs/api) voor programmatische toegang
