
# Schemaläggning

Queuety har inbyggt stöd för återkommande jobb. I stället för att förlita sig på `wp_cron` lagras scheman i databasen och utvärderas ungefär en gång i minuten av en långkörande `wp queuety work`-process (eller av arbetarpoolens överordnade process). `wp queuety work --once`, `wp queuety flush` och pluginets inbyggda reservlösning med WP-Cron utvärderar inte scheman ([#14](https://github.com/inline0/queuety/issues/14)). Utan en långkörande arbetare kör du `wp queuety schedule run` själv.

## Intervallschemaläggning

Använd `every()` för enkla intervallbaserade scheman. Uttrycket är en valfri sträng som är kompatibel med PHPs `DateTimeImmutable::modify()`:

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

## Schemaläggning med Cron

Använd `cron()` för vanliga cron-uttryck med fem fält:

```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 * * * *' );
```

## Schemaalternativ

Byggaren `PendingSchedule` stöder följande metoder:

| Metod | Beskrivning |
|---|---|
| `every( string $interval )` | Anger ett intervalluttryck |
| `cron( string $expression )` | Anger ett cron-uttryck |
| `on_queue( string $queue )` | Anger målkön (standard: `'default'`) |
| `overlap( OverlapPolicy $policy )` | Anger överlappningsregeln (standard: `Allow`) |

Du måste anropa antingen `every()` eller `cron()` innan schemat skickar iväg ett jobb. Om ingen av dem anges kastas ett `RuntimeException`.

## Överlappningsregler

Om ett schemalagt jobb fortfarande körs (väntar eller bearbetas) när nästa tidsintervall infaller avgör överlappningsregeln vad som händer. Ange den med metoden `overlap()`:

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

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

Enumen `OverlapPolicy` har tre alternativ:

| Regel | Värde | Beteende |
|---|---|---|
| `OverlapPolicy::Allow` | `allow` | Skickar alltid iväg ett nytt jobb, även om föregående körning fortfarande pågår. Detta är standardinställningen. |
| `OverlapPolicy::Skip` | `skip` | Hoppar över det aktuella tidsintervallet om handläggaren har jobb som väntar eller bearbetas. `next_run` uppdateras som vanligt så att schemat behåller sin takt. |
| `OverlapPolicy::Buffer` | `buffer` | Precis som med Skip skickas inget jobb iväg och `next_run` går vidare till nästa ordinarie tillfälle. Till skillnad från Skip uppdateras inte `last_run`. |

### Tillåt (standard)

Flera instanser av samma handläggare kan köras samtidigt. Använd detta för idempotenta handläggare där överlappning inte gör någon skada.

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

### Hoppa över

Tidsintervallet hoppas tyst över om handläggaren fortfarande körs. Använd detta för handläggare där det vore slöseri eller skulle orsaka konflikter att köra en andra instans.

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

### Buffra

Fungerar för närvarande som Hoppa över: om ett jobb från handläggaren fortfarande väntar eller bearbetas skickas inget jobb iväg och `next_run` går vidare till nästa ordinarie tillfälle. Den enda skillnaden är att Buffra lämnar `last_run` oförändrat, medan Hoppa över registrerar det överhoppade intervallet som den senaste körningen.

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

## Så fungerar det

När ett schema skapas lagrar Queuety det i tabellen `queuety_schedules` tillsammans med uttrycket, handläggaren, nyttolasten och den beräknade tiden för nästa körning.

Vid varje schemaläggartick (ungefär en gång i minuten i en långkörande arbetare, eller när du kör `wp queuety schedule run`) söker schemaläggaren efter scheman där `next_run` har passerat. För varje schema som ska köras skickar den iväg ett nytt jobb och uppdaterar `next_run` till nästa förekomst.

## Hantera scheman 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
```

## Hantera scheman 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();
```

## Nyttolast

Scheman kan innehålla en statisk nyttolast som skickas med varje jobb:

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

Varje gång schemat körs skickas ett nytt jobb iväg med den här nyttolasten.
