
# Planning

Queuety biedt ingebouwde ondersteuning voor terugkerende taken. In plaats van te vertrouwen op `wp_cron` worden planningen opgeslagen in de database en ongeveer één keer per minuut geëvalueerd door een langlopend `wp queuety work`-proces (of het bovenliggende proces van een workerpool). `wp queuety work --once`, `wp queuety flush` en de ingebouwde WP-Cron-fallback van de plugin evalueren geen planningen ([#14](https://github.com/inline0/queuety/issues/14)); voer `wp queuety schedule run` zelf uit als er geen langlopende worker actief is.

## Planning op basis van intervallen

Gebruik `every()` voor eenvoudige planningen op basis van intervallen. De expressie is elke tekenreeks die compatibel is met de `DateTimeImmutable::modify()` van PHP:

```php
use Queuety\Queuety;

Queuety::schedule( 'cleanup_handler' )
    ->every( '1 hour' )
    ->on_queue( 'maintenance' );

Queuety::schedule( 'sync_inventory' )
    ->every( '30 minutes' )
    ->on_queue( 'sync' );

Queuety::schedule( 'daily_report', [ 'type' => 'summary' ] )
    ->every( '1 day' );
```

## Cron-planning

Gebruik `cron()` voor standaardexpressies van cron met 5 velden:

```php
// Every day at 3am
Queuety::schedule( 'nightly_cleanup' )
    ->cron( '0 3 * * *' );

// Every Monday at 9am
Queuety::schedule( 'weekly_digest' )
    ->cron( '0 9 * * 1' )
    ->on_queue( 'emails' );

// Every 15 minutes
Queuety::schedule( 'health_check' )
    ->cron( '*/15 * * * *' );
```

## Opties voor planningen

De `PendingSchedule`-builder ondersteunt deze methoden:

| Methode | Beschrijving |
|---|---|
| `every( string $interval )` | Een intervalexpressie instellen |
| `cron( string $expression )` | Een cron-expressie instellen |
| `on_queue( string $queue )` | De doelwachtrij instellen (standaard: `'default'`) |
| `overlap( OverlapPolicy $policy )` | Het beleid voor overlappende taken instellen (standaard: `Allow`) |

U moet `every()` of `cron()` aanroepen voordat de planning taken verstuurt. Als geen van beide is ingesteld, wordt er een `RuntimeException` gegenereerd.

## Beleid voor overlappende taken

Wanneer een geplande taak nog wordt uitgevoerd (in afwachting of in verwerking) op het moment dat de volgende cyclus ingaat, bepaalt het beleid voor overlappende taken wat er gebeurt. Stel dit in met de methode `overlap()`:

```php
use Queuety\Queuety;
use Queuety\Enums\OverlapPolicy;

Queuety::schedule( 'sync_inventory' )
    ->every( '5 minutes' )
    ->overlap( OverlapPolicy::Skip )
    ->on_queue( 'sync' );
```

De enum `OverlapPolicy` heeft drie gevallen:

| Beleid | Waarde | Gedrag |
|---|---|---|
| `OverlapPolicy::Allow` | `allow` | Verstuur altijd een nieuwe taak, zelfs als de vorige uitvoering nog actief is. Dit is de standaardinstelling. |
| `OverlapPolicy::Skip` | `skip` | Sla de huidige cyclus over als de handler taken in afwachting of in verwerking heeft. `next_run` wordt normaal bijgewerkt, zodat de planning het vaste ritme behoudt. |
| `OverlapPolicy::Buffer` | `buffer` | Net als bij Skip wordt de cyclus niet verstuurd en gaat `next_run` door naar de volgende reguliere uitvoering. Anders dan bij Skip wordt `last_run` niet bijgewerkt. |

### Toestaan (standaard)

Meerdere instanties van dezelfde handler kunnen gelijktijdig worden uitgevoerd. Gebruik dit voor idempotente handlers waarbij overlap geen kwaad kan.

```php
Queuety::schedule( 'send_heartbeat_ping' )
    ->every( '1 minute' )
    ->overlap( OverlapPolicy::Allow );
```

### Overslaan

De cyclus wordt stilzwijgend overgeslagen als de handler nog actief is. Gebruik dit voor handlers waarbij een tweede instantie onnodig werk zou zijn of conflicten kan veroorzaken.

```php
Queuety::schedule( 'rebuild_search_index' )
    ->every( '10 minutes' )
    ->overlap( OverlapPolicy::Skip );
```

### Bufferen

Werkt momenteel hetzelfde als Skip: als de handler nog een taak in afwachting of in verwerking heeft, wordt de cyclus niet verstuurd en gaat `next_run` door naar de volgende reguliere uitvoering. Het enige verschil is dat Buffer `last_run` ongewijzigd laat, terwijl Skip de overgeslagen cyclus als laatste uitvoering registreert.

```php
Queuety::schedule( 'sync_inventory' )
    ->every( '5 minutes' )
    ->overlap( OverlapPolicy::Buffer );
```

## Werking

Wanneer een planning wordt aangemaakt, slaat Queuety deze op in de tabel `queuety_schedules`, met de expressie, handler, payload en de volgende berekende uitvoeringstijd.

Bij elke cyclus van de planner (ongeveer één keer per minuut in een langlopende worker, of wanneer u `wp queuety schedule run` uitvoert) controleert de planner op planningen waarvan `next_run` is verstreken. Voor elke vervallen planning wordt een nieuwe taak verstuurd en wordt `next_run` bijgewerkt naar de volgende uitvoering.

## Planningen beheren via CLI

```bash
# List all schedules
wp queuety schedule list

# Add a recurring schedule
wp queuety schedule add cleanup_handler --every="1 hour"
wp queuety schedule add nightly_report --cron="0 3 * * *" --queue=reports

# Remove a schedule
wp queuety schedule remove cleanup_handler

# Manually trigger the scheduler
wp queuety schedule run
```

## Planningen beheren via PHP

```php
// Get the scheduler instance
$scheduler = Queuety::scheduler();

// List all schedules
$schedules = $scheduler->list();

// Remove a schedule by handler name
$scheduler->remove( 'cleanup_handler' );

// Manually trigger a tick
$count = $scheduler->tick();
```

## Payload

Planningen kunnen een statische payload bevatten die aan elke verstuurde taak wordt meegegeven:

```php
Queuety::schedule( 'generate_report', [ 'type' => 'daily', 'format' => 'pdf' ] )
    ->every( '1 day' )
    ->on_queue( 'reports' );
```

Elke keer dat de planning wordt uitgevoerd, wordt een nieuwe taak met deze payload verstuurd.
