
# Προγραμματισμός

Το Queuety διαθέτει ενσωματωμένη υποστήριξη για επαναλαμβανόμενες εργασίες. Αντί να βασίζεται στο `wp_cron`, αποθηκεύει τα προγράμματα στη βάση δεδομένων και τα αξιολογεί περίπου μία φορά το λεπτό μια διεργασία `wp queuety work` μεγάλης διάρκειας (ή η γονική διεργασία μιας δεξαμενής worker). Τα `wp queuety work --once`, `wp queuety flush` και η ενσωματωμένη εφεδρική επιλογή WP-Cron του πρόσθετου δεν αξιολογούν προγράμματα ([#14](https://github.com/inline0/queuety/issues/14)). Χωρίς worker μεγάλης διάρκειας, εκτελέστε μόνοι σας το `wp queuety schedule run`.

## Προγραμματισμός με διαστήματα

Χρησιμοποιήστε το `every()` για απλά προγράμματα που βασίζονται σε διαστήματα. Η έκφραση μπορεί να είναι οποιαδήποτε συμβατή συμβολοσειρά με το `DateTimeImmutable::modify()` του 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

Χρησιμοποιήστε το `cron()` για τυπικές εκφράσεις cron 5 πεδίων:

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

## Επιλογές προγράμματος

Ο builder `PendingSchedule` υποστηρίζει τις εξής μεθόδους:

| Μέθοδος | Περιγραφή |
|---|---|
| `every( string $interval )` | Ορίζει μια έκφραση διαστήματος |
| `cron( string $expression )` | Ορίζει μια έκφραση cron |
| `on_queue( string $queue )` | Ορίζει την ουρά προορισμού (προεπιλογή: `'default'`) |
| `overlap( OverlapPolicy $policy )` | Ορίζει την πολιτική επικάλυψης (προεπιλογή: `Allow`) |

Πρέπει να καλέσετε είτε το `every()` είτε το `cron()` πριν από την αποστολή του προγράμματος. Αν δεν οριστεί κανένα από τα δύο, προκύπτει `RuntimeException`.

## Πολιτικές επικάλυψης

Όταν μια προγραμματισμένη εργασία εξακολουθεί να εκτελείται (σε εκκρεμότητα ή υπό επεξεργασία) τη στιγμή που ενεργοποιείται το επόμενο χρονικό βήμα, η πολιτική επικάλυψης καθορίζει τι θα συμβεί. Ορίστε την με τη μέθοδο `overlap()`:

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

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

Το enum `OverlapPolicy` έχει τρεις περιπτώσεις:

| Πολιτική | Τιμή | Συμπεριφορά |
|---|---|---|
| `OverlapPolicy::Allow` | `allow` | Αποστέλλει πάντα μια νέα εργασία, ακόμη κι αν η προηγούμενη εκτέλεση είναι ακόμη ενεργή. Αυτή είναι η προεπιλογή. |
| `OverlapPolicy::Skip` | `skip` | Παραλείπει το τρέχον χρονικό βήμα αν ο χειριστής έχει εργασίες σε εκκρεμότητα ή υπό επεξεργασία. Το `next_run` ενημερώνεται κανονικά, ώστε το πρόγραμμα να διατηρεί τον ρυθμό του. |
| `OverlapPolicy::Buffer` | `buffer` | Όπως και με το Skip, το χρονικό βήμα δεν αποστέλλεται και το `next_run` μεταβαίνει στην επόμενη τακτική εκτέλεση. Σε αντίθεση με το Skip, το `last_run` δεν ενημερώνεται. |

### Allow (προεπιλογή)

Πολλαπλές παρουσίες του ίδιου χειριστή μπορούν να εκτελούνται ταυτόχρονα. Χρησιμοποιήστε αυτή την επιλογή για idempotent χειριστές, όπου η επικάλυψη δεν προκαλεί πρόβλημα.

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

### Παράλειψη

Το χρονικό βήμα παραλείπεται σιωπηρά αν ο χειριστής εξακολουθεί να εκτελείται. Χρησιμοποιήστε αυτή την επιλογή για χειριστές όπου η εκτέλεση δεύτερης παρουσίας θα ήταν άσκοπη ή θα προκαλούσε διενέξεις.

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

### Προσωρινή αποθήκευση

Σήμερα συμπεριφέρεται όπως το Skip: όταν ο χειριστής έχει ακόμη εργασία σε εκκρεμότητα ή υπό επεξεργασία, το χρονικό βήμα δεν αποστέλλεται και το `next_run` μεταβαίνει στην επόμενη τακτική εκτέλεση. Η μόνη διαφορά είναι ότι το Buffer αφήνει το `last_run` αμετάβλητο, ενώ το Skip καταγράφει το χρονικό βήμα που παραλείφθηκε ως τελευταία εκτέλεση.

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

## Πώς λειτουργεί

Κατά τη δημιουργία ενός προγράμματος, το Queuety το αποθηκεύει στον πίνακα `queuety_schedules` μαζί με την έκφραση, τον χειριστή, το payload και την επόμενη υπολογισμένη ώρα εκτέλεσης.

Σε κάθε χρονικό βήμα του scheduler (περίπου μία φορά το λεπτό σε worker μεγάλης διάρκειας ή όταν εκτελείτε το `wp queuety schedule run`), ο scheduler ελέγχει για προγράμματα των οποίων το `next_run` έχει παρέλθει. Για κάθε πρόγραμμα που έχει φτάσει η ώρα του, αποστέλλει μια νέα εργασία και ενημερώνει το `next_run` για την επόμενη εκτέλεση.

## Διαχείριση προγραμμάτων μέσω 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
```

## Διαχείριση προγραμμάτων μέσω 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 που περνά σε κάθε εργασία που αποστέλλεται:

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

Κάθε φορά που ενεργοποιείται το πρόγραμμα, αποστέλλεται μια νέα εργασία με αυτό το payload.
