
# Razporejanje

Queuety ima vgrajeno podporo za ponavljajoča se opravila. Namesto zanašanja na `wp_cron` so urniki shranjeni v podatkovni zbirki, približno enkrat na minuto pa jih ovrednoti dolgotrajno delujoč proces `wp queuety work` (ali nadrejeni proces skupine delavcev). `wp queuety work --once`, `wp queuety flush` in vtičnikov vgrajeni nadomestni mehanizem WP-Cron urnikov ne ovrednotijo ([#14](https://github.com/inline0/queuety/issues/14)); brez dolgotrajno delujočega delavca sami zaženite `wp queuety schedule run`.

## Razporejanje po intervalu

Za preproste urnike, ki temeljijo na intervalu, uporabite `every()`. Izraz je lahko poljuben niz, združljiv z izrazom `DateTimeImmutable::modify()` v 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' );
```

## Razporejanje Cron

Za standardne petpoljne izraze cron uporabite `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 urnika

Gradnik `PendingSchedule` podpira te metode:

| Metoda | Opis |
|---|---|
| `every( string $interval )` | Nastavi intervalni izraz |
| `cron( string $expression )` | Nastavi izraz cron |
| `on_queue( string $queue )` | Nastavi ciljno čakalno vrsto (privzeto: `'default'`) |
| `overlap( OverlapPolicy $policy )` | Nastavi pravilnik za prekrivanje (privzeto: `Allow`) |

Preden se urnik izvede, morate poklicati `every()` ali `cron()`. Če ne nastavite nobenega, se sproži `RuntimeException`.

## Pravilniki za prekrivanje

Pravilnik za prekrivanje določa, kaj se zgodi, če se razporejeno opravilo še vedno izvaja (čaka ali je v obdelavi), ko nastopi naslednji časovni interval. Nastavite ga z metodo `overlap()`:

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

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

Naštevanje `OverlapPolicy` ima tri možnosti:

| Pravilnik | Vrednost | Delovanje |
|---|---|---|
| `OverlapPolicy::Allow` | `allow` | Vedno razpošlje novo opravilo, tudi če je prejšnje izvajanje še aktivno. To je privzeta možnost. |
| `OverlapPolicy::Skip` | `skip` | Preskoči trenutni časovni interval, če ima obravnavalnik čakajoča opravila ali opravila v obdelavi. `next_run` se običajno posodobi, tako da urnik ohrani svoj ritem. |
| `OverlapPolicy::Buffer` | `buffer` | Podobno kot pri možnosti Skip se opravilo ob tem intervalu ne razpošlje, `next_run` pa se pomakne na naslednji redni termin. Za razliko od možnosti Skip se `last_run` ne posodobi. |

### Dovoli (privzeto)

Več primerkov istega obravnavalnika se lahko izvaja sočasno. To uporabite za idempotentne obravnavalnike, pri katerih prekrivanje ni problematično.

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

### Preskoči

Časovni interval se tiho preskoči, če se obravnavalnik še izvaja. To uporabite za obravnavalnike, pri katerih bi bila druga instanca potratna ali bi povzročila spore.

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

### Zadrži

Trenutno deluje enako kot možnost Skip: če ima obravnavalnik še čakajoče opravilo ali opravilo v obdelavi, se opravilo ob tem intervalu ne razpošlje, `next_run` pa se pomakne na naslednji redni termin. Edina razlika je, da možnost Buffer ohrani `last_run` nespremenjen, medtem ko možnost Skip zabeleži preskočeni interval kot zadnji zagon.

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

## Kako deluje

Ob ustvarjanju urnika ga Queuety shrani v tabelo `queuety_schedules` skupaj z izrazom, obravnavalnikom, tovorom in naslednjim izračunanim časom izvajanja.

Ob vsakem taktu razporejevalnika (približno enkrat na minuto pri dolgotrajno delujočem delavcu ali ob zagonu `wp queuety schedule run`) razporejevalnik poišče urnike, pri katerih je potekel `next_run`. Za vsak zapadli urnik razpošlje novo opravilo in posodobi `next_run` na naslednji termin.

## Upravljanje urnikov prek 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
```

## Upravljanje urnikov prek 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();
```

## Tovor

Urniki lahko vključujejo statični tovor, ki se posreduje vsakemu razposlanemu opravilu:

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

Ob vsakem sproženju urnika se razpošlje novo opravilo s tem tovorom.
