
# Plánování

Queuety má vestavěnou podporu opakovaných úloh. Namísto spoléhání na `wp_cron` se plány ukládají do databáze a přibližně jednou za minutu je vyhodnocuje dlouho běžící proces `wp queuety work` (nebo nadřazený proces poolu workerů). `wp queuety work --once`, `wp queuety flush` ani vestavěný záložní mechanismus WP-Cron pluginu plány nevyhodnocují ([#14](https://github.com/inline0/queuety/issues/14)); bez dlouho běžícího workeru spusťte `wp queuety schedule run` sami.

## Plánování podle intervalu

Pro jednoduché plánování podle intervalu použijte `every()`. Výraz může být libovolný řetězec kompatibilní s `DateTimeImmutable::modify()` z 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' );
```

## Plánování pomocí Cron

Pro standardní pětisložkové výrazy cron použijte `cron()`:

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

## Možnosti plánu

Tvůrce `PendingSchedule` podporuje tyto metody:

| Metoda | Popis |
|---|---|
| `every( string $interval )` | Nastaví intervalový výraz |
| `cron( string $expression )` | Nastaví výraz cron |
| `on_queue( string $queue )` | Nastaví cílovou frontu (výchozí: `'default'`) |
| `overlap( OverlapPolicy $policy )` | Nastaví zásadu překrývání (výchozí: `Allow`) |

Před odesláním podle plánu musíte zavolat buď `every()`, nebo `cron()`. Pokud není nastaveno ani jedno, vyvolá se `RuntimeException`.

## Zásady při překrývání

Když naplánovaná úloha při dalším spuštění plánu stále běží (čeká nebo se zpracovává), zásada při překrývání určí, co se stane. Nastavte ji metodou `overlap()`:

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

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

Výčet `OverlapPolicy` má tři možnosti:

| Zásada | Hodnota | Chování |
|---|---|---|
| `OverlapPolicy::Allow` | `allow` | Vždy odešle novou úlohu, i když předchozí běh stále probíhá. Jde o výchozí možnost. |
| `OverlapPolicy::Skip` | `skip` | Přeskočí aktuální spuštění plánu, pokud handler čeká nebo zpracovává nějakou úlohu. `next_run` se běžně aktualizuje, takže plán zachová svou kadenci. |
| `OverlapPolicy::Buffer` | `buffer` | Podobně jako u Skip se úloha neodešle a `next_run` se posune k dalšímu pravidelnému spuštění. Na rozdíl od Skip se `last_run` neaktualizuje. |

### Povolit (výchozí)

Současně může běžet více instancí stejného handleru. Použijte tuto možnost pro idempotentní handlery, u kterých překrývání nevadí.

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

### Přeskočit

Pokud handler stále běží, spuštění plánu se tiše přeskočí. Použijte tuto možnost pro handlery, u kterých by spuštění druhé instance bylo zbytečné nebo způsobilo konflikt.

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

### Uložit do fronty

V současnosti se chová stejně jako Skip: pokud handler stále čeká na úlohu nebo ji zpracovává, úloha se neodešle a `next_run` se posune k dalšímu pravidelnému spuštění. Jediný rozdíl je, že Buffer ponechá `last_run` beze změny, zatímco Skip zaznamená přeskočené spuštění jako poslední běh.

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

## Jak to funguje

Při vytvoření plánu jej Queuety uloží do tabulky `queuety_schedules` spolu s výrazem, handlerem, obsahem a vypočteným časem dalšího spuštění.

Při každém spuštění plánovače (přibližně jednou za minutu v dlouho běžícím workeru nebo při spuštění `wp queuety schedule run`) plánovač zkontroluje plány, jejichž čas `next_run` již uplynul. U každého splatného plánu odešle novou úlohu a aktualizuje `next_run` na čas dalšího spuštění.

## Správa plánů přes 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
```

## Správa plánů přes 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();
```

## Obsah úlohy

Plány mohou obsahovat statický obsah, který se předá každé odeslané úloze:

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

Při každém spuštění plánu se odešle nová úloha s tímto obsahem.
