
# Aloitus

## Asennus

### Vaatimukset

- PHP 8.2 tai uudempi ja WordPress 6.4 tai uudempi
- MySQL 8.0+ tai MariaDB 10.6+. Työntekijät varaavat työt ja erääntyneet ajastukset käyttämällä `SELECT ... FOR UPDATE SKIP LOCKED`-toimintoa, jonka vanhemmat palvelimet hylkäävät syntaksivirheellä.
- `mysqli` tai `pdo_mysql` (katso alla)
- Palvelimella on oltava WP-CLI, jos suoritat erillisiä työntekijöitä komennolla `wp queuety work`
- `pcntl`- ja `posix`-laajennusten PHP on oltava käytössä, jos suoritat työntekijäpooleja asetuksilla `--workers` tai `--min-workers`/`--max-workers`

Queuety tarvitsee joko `mysqli`- tai `pdo_mysql`-ajurin PHP-suoritusympäristössä, joka lataa WordPressn ja WP-CLIn. Se valitsee ajurin automaattisesti: WordPress-suoritusympäristöissä suositaan `mysqli`ta, kun taas `pdo_mysql` säilyy käytettävissä itsenäiseen tai suoraan suoritusympäristön käyttöön.

Jos haluat tietokantapohjaisen suoritusympäristön ilman WordPress-lisäosakerrosta, katso kohta [Itsenäinen käyttö](https://queuety.inline0.dev/fi/docs/features/standalone-use). Tässä ratkaisussa käytetään samoja yhteys- ja suoritusympäristötauluja, mutta se ei sisällä WordPress-koukkusiltoja tai WP-CLI-rekisteröintiä.

### Julkaisuarkistosta

Jokaisessa [GitHubn julkaisussa](https://github.com/inline0/queuety/releases) on `queuety.zip`-paketti: lisäosa, jonka Composer-riippuvuudet on jo asennettu. Asenna uusin versio komennolla WP-CLI:

```bash
wp plugin install https://github.com/inline0/queuety/releases/latest/download/queuety.zip --activate
```

Voit myös ladata zip-tiedoston ja lähettää sen kohdassa Plugins > Add New > Upload Plugin. Tämä on yksinkertaisin vaihtoehto tavalliselle WordPress-sivustolle.

### Composern kautta Composer-hallittuihin WordPress-ympäristöihin

```bash
composer require queuety/queuety
```

Aktivoi sitten lisäosa:

```bash
wp plugin activate queuety
```

Pakettityyppi on `wordpress-plugin`. Composer sijoittaa sen lisäosahakemistoon vain, jos projekti edellyttää `composer/installers`a ja määrittää tämän pakettityypin asennuspolkuun, kuten Bedrock tekee. Projektin on myös ladattava oma `vendor/autoload.php`nsa, minkä Bedrockkin tekee. Ilman `composer/installers`ta Composer asentaa paketin kohteeseen `vendor/queuety/queuety`, josta WordPress ei löydä sitä, joten käytä julkaisuarkiston zip-tiedostoa tavallisessa WordPress-asennuksessa.

### Lähdekoodista kehityksen aikana

Sijoita repositorio kohteeseen `wp-content/plugins/queuety` ja asenna sitten PHP-riippuvuudet:

```bash
composer install
wp plugin activate queuety
```

Aktivoinnin yhteydessä Queuety luo tietokantataulunsa (`queuety_jobs`, `queuety_workflows`, `queuety_logs`, `queuety_schedules`, `queuety_queue_states`, `queuety_webhooks`, `queuety_locks`, `queuety_signals`, `queuety_workflow_dependencies`, `queuety_workflow_dispatch_keys`, `queuety_batches`, `queuety_chunks`, `queuety_workflow_events`, `queuety_artifacts`, `queuety_state_machines`, `queuety_state_machine_events`), jotta työntekijät voivat varata töitä suoraan kohteesta MySQL.

Oletusarvoisesti lisäosa ajastaa myös kertaluonteisen työntekijän suorituksen joka minuutti käyttämällä WordPressn cron-toimintoa jonolle `default`. Näin saat komentoriviä käyttämättömän perustason töille ja työnkuluille, jotka toimivat kohteessa `default`, kunhan WordPressn cron toimii. Kukin suoritus käsittelee enintään yhden työn. Se ei suorita toistuvia ajastuksia, palauta vanhentuneita töitä tai tarkista työnkulkujen määräaikoja; nämä tehtävät suoritetaan vain pitkään käynnissä olevassa `wp queuety work`-prosessissa ([#14](https://github.com/inline0/queuety/issues/14)). Siirry erillisiin `wp queuety work`-prosesseihin, jos käytät mukautettuja jonoja tai toistuvia ajastuksia, tarvitset pienemmän viiveen tai käsittelet raskaita työkuormia.

## Määritykset

Kaikki vakiot ovat valinnaisia. Määritä ne kohteessa `wp-config.php` ennen lisäosan lataamista tai ennen kuin Queuety käynnistyy upotetussa teematyyppisessä asennuksessa:

| Vakio | Oletus | Kuvaus |
|---|---|---|
| `QUEUETY_RETENTION_DAYS` | `7` | Oletusikä päivinä kohteille `wp queuety purge` ja `Queuety::purge()`. Mitään ei poisteta automaattisesti |
| `QUEUETY_LOG_RETENTION_DAYS` | `0` | `Config::log_retention_days()` lukee tämän, mutta sitä ei vielä käytetä; lokit säilyvät, kunnes kutsut `Queuety::purge_logs()` ([#15](https://github.com/inline0/queuety/issues/15)) |
| `QUEUETY_MAX_EXECUTION_TIME` | `300` | Työn enimmäiskesto sekunteina ennen aikakatkaisua (ei vielä käytössä, katso [Työt](https://queuety.inline0.dev/fi/docs/jobs#timeout)) |
| `QUEUETY_WORKER_SLEEP` | `1` | Jonon ollessa tyhjä nukuttavien sekuntien määrä |
| `QUEUETY_WORKER_MAX_JOBS` | `1000` | Töiden enimmäismäärä ennen työntekijän uudelleenkäynnistystä |
| `QUEUETY_WORKER_MAX_MEMORY` | `128` | Enimmäismäärä megatavuina ennen työntekijän uudelleenkäynnistystä |
| `QUEUETY_RETRY_BACKOFF` | `exponential` | Viiveen strategia: `exponential`, `linear` tai `fixed` |
| `QUEUETY_STALE_TIMEOUT` | `600` | Sekuntimäärä ennen jumittuneiden töiden palautusta |
| `QUEUETY_CACHE_TTL` | `5` | Välimuistin oletusarvoinen TTL sekunteina |
| `QUEUETY_DEBUG` | `false` | Ota käyttöön työntekijän yksityiskohtainen lokikirjaus |
| `QUEUETY_CLI_COMMAND` | `queuety` | Juuren WP-CLI-komennon nimi |
| `QUEUETY_TABLE_PREFIX` | `queuety_` | Kaikkien Queuety-taulujen yhteinen perusnimi WordPress-tietokannan etuliitteen jälkeen |
| `QUEUETY_TABLE_JOBS` | `queuety_jobs` | Töiden taulun nimi |
| `QUEUETY_TABLE_WORKFLOWS` | `queuety_workflows` | Työnkulkujen taulun nimi |
| `QUEUETY_TABLE_LOGS` | `queuety_logs` | Lokien taulun nimi |
| `QUEUETY_TABLE_SCHEDULES` | `queuety_schedules` | Aikataulujen taulun nimi |
| `QUEUETY_TABLE_SIGNALS` | `queuety_signals` | Signaalien taulun nimi |
| `QUEUETY_TABLE_WORKFLOW_DEPENDENCIES` | `queuety_workflow_dependencies` | Työnkulkujen riippuvuusodotusten taulun nimi |
| `QUEUETY_TABLE_WORKFLOW_DISPATCH_KEYS` | `queuety_workflow_dispatch_keys` | Pysyvien työnkulkujen idempotenssitaulun nimi |
| `QUEUETY_TABLE_CHUNKS` | `queuety_chunks` | Suoratoiston osien taulun nimi |
| `QUEUETY_TABLE_QUEUE_STATES` | `queuety_queue_states` | Jonotilojen taulun nimi |
| `QUEUETY_TABLE_WEBHOOKS` | `queuety_webhooks` | Webhookien taulun nimi |
| `QUEUETY_TABLE_LOCKS` | `queuety_locks` | Lukitusten taulun nimi |
| `QUEUETY_TABLE_BATCHES` | `queuety_batches` | Erien taulun nimi |
| `QUEUETY_TABLE_WORKFLOW_EVENTS` | `queuety_workflow_events` | Työnkulun tapahtumalokin taulun nimi |
| `QUEUETY_TABLE_ARTIFACTS` | `queuety_artifacts` | Työnkulun artefaktien taulun nimi |
| `QUEUETY_TABLE_STATE_MACHINES` | `queuety_state_machines` | Tilakoneiden taulun nimi |
| `QUEUETY_TABLE_STATE_MACHINE_EVENTS` | `queuety_state_machine_events` | Tilakoneen tapahtumalokin taulun nimi |
| `QUEUETY_DB_DRIVER` | `auto` | MySQL-ajuri: `auto`, `mysqli` tai `pdo`. `auto` suosii arvoa `mysqli`, kun WordPress on ladattu; muussa tapauksessa arvoa `pdo_mysql` ja sitten `mysqli` |

Resurssien hyväksyntään ja mukautuvaan pooliin liittyvät vakiot (`QUEUETY_RESOURCE_*`, `QUEUETY_WORKER_POOL_*`) on lueteltu [Workers](https://queuety.inline0.dev/fi/docs/features/workers)-sivulla.

`QUEUETY_TABLE_PREFIX` muuttaa vain taulujen nimien Queuety-osaa. WordPress-tietokannan etuliite ympäröi tuloksen edelleen, joten `$wpdb->prefix = 'wp_'` ja `QUEUETY_TABLE_PREFIX = 'themequeue_'` tuottavat esimerkiksi tauluja kuten `wp_themequeue_jobs`. Yksittäisten taulujen eksplisiittiset `QUEUETY_TABLE_*`-vakiot ovat silti etusijalla.

Myös erilliset yhteydet voivat määrittää taulujen Queuety-etuliitteen yhteyskohtaisesti:

```php
$conn = new Connection(
    host: '127.0.0.1:3306',
    dbname: 'wordpress',
    user: 'root',
    password: 'secret',
    prefix: 'wp_',
    table_prefix: 'themequeue_',
);
```

Näin WordPress-tietokannan etuliite säilyy ennallaan ja vain taulun Queuety-osa muuttuu.

## Ensimmäinen työsi

Luo käsittelijäluokka, joka toteuttaa `Handler`-rajapinnan:

```php
use Queuety\Handler;

class SendEmailHandler implements Handler {
    public function handle( array $payload ): void {
        wp_mail( $payload['to'], $payload['subject'], $payload['body'] );
    }

    public function config(): array {
        return [
            'queue'           => 'emails',
            'max_attempts'    => 5,
        ];
    }
}
```

Rekisteröi se ja lähetä työ suoritettavaksi:

```php
use Queuety\Queuety;

Queuety::register( 'send_email', SendEmailHandler::class );

Queuety::dispatch( 'send_email', [
    'to'      => 'user@example.com',
    'subject' => 'Welcome',
    'body'    => 'Hello from Queuety!',
] );
```

Tai käytä nykyaikaista lähetettävää työluokkaa:

```php
use Queuety\Contracts\Job;
use Queuety\Dispatchable;

readonly class SendEmailJob implements Job {
    use Dispatchable;

    public function __construct(
        public string $to,
        public string $subject,
        public string $body,
    ) {}

    public function handle(): void {
        wp_mail( $this->to, $this->subject, $this->body );
    }
}

SendEmailJob::dispatch( 'user@example.com', 'Welcome', 'Hello from Queuety!' );
```

## Ensimmäinen työnkulkusi

Määritä vaihekäsittelijät, jotka toteuttavat `Step`-rajapinnan:

```php
use Queuety\Step;

class FetchDataHandler implements Step {
    public function handle( array $state ): array {
        $user = get_user_by( 'ID', $state['user_id'] );
        return [ 'user_name' => $user->display_name ];
    }

    public function config(): array {
        return [];
    }
}

class CallLLMHandler implements Step {
    public function handle( array $state ): array {
        $response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', [
            'body' => json_encode( [ 'prompt' => "Generate report for {$state['user_name']}" ] ),
        ] );
        return [ 'llm_response' => wp_remote_retrieve_body( $response ) ];
    }

    public function config(): array {
        return [ 'max_attempts' => 5 ];
    }
}

class FormatOutputHandler implements Step {
    public function handle( array $state ): array {
        $url = save_report( $state['user_name'], $state['llm_response'] );
        return [ 'report_url' => $url ];
    }

    public function config(): array {
        return [];
    }
}
```

Lähetä työnkulku suoritettavaksi:

```php
$workflow_id = Queuety::workflow( 'generate_report' )
    ->then( FetchDataHandler::class )
    ->then( CallLLMHandler::class )
    ->then( FormatOutputHandler::class )
    ->dispatch( [ 'user_id' => 42 ] );
```

## Käynnistä työntekijä

```bash
wp queuety work
```

Työntekijä hakee odottavia töitä, suorittaa ne, vie työnkulkuja eteenpäin ja odottaa, kun jono on tyhjä. Pysäytä painamalla `Ctrl+C`; tämä päättää prosessin heti, myös kesken työn (katso [Workers](https://queuety.inline0.dev/fi/docs/features/workers#worker-lifecycle)).

Edellä kuvattu `SendEmailHandler` lähettää työnsä `emails`-jonoon käyttäen `config()`, joten jonossa `default` toimiva työntekijä ei poimi niitä. Nimeä kaikki käyttämäsi jonot:

```bash
wp queuety work --queue=emails,default
```

Jos et suorita erillistä työntekijää, Queuety käyttää silti edellä kuvattua oletusarvoista kerran minuutissa toimivaa WordPress cron -vararatkaisua, joka on rajattu `default`-jonoon ja yhteen työhön suorituskertaa kohden. Erillinen työntekijä tarjoaa suuremman läpimenon ja pienemmän viiveen.

Suorita tuotantoympäristössä useita työntekijöitä:

```bash
wp queuety work --workers=4
```

Käsittele useita jonoja prioriteettijärjestyksessä:

```bash
wp queuety work --queue=high,default,low
```

## Seuraavaksi

- [Työt](https://queuety.inline0.dev/fi/docs/jobs): täydellinen opas töiden lähettämiseen ja käsittelijöihin
- [Työnkulut](https://queuety.inline0.dev/fi/docs/workflows): ketjut, rinnakkaiset vaiheet, ehdollinen haarautuminen ja työnkulkujen suorittaminen
- [Väliohjelmistot](https://queuety.inline0.dev/fi/docs/features/middleware): nopeusrajoitus, rajoittaminen ja mukautettu putkilogiikka
- [Eräkäsittely](https://queuety.inline0.dev/fi/docs/features/batching): työryhmien lähettäminen takaisinkutsujen kanssa
- [Suoratoistovaiheet](https://queuety.inline0.dev/fi/docs/workflows/streaming): suoratoistettujen tietojen tallentaminen pala palalta
- [Aikataulutus](https://queuety.inline0.dev/fi/docs/features/scheduling): toistuvat työt
- [Välimuistitus](https://queuety.inline0.dev/fi/docs/features/caching): liitettävä välimuistikerros
- [Testaus](https://queuety.inline0.dev/fi/docs/features/testing): QueueFake ja testiväittämät
- [CLI Viite](https://queuety.inline0.dev/fi/docs/cli): kaikki käytettävissä olevat komennot
- [PHP API](https://queuety.inline0.dev/fi/docs/api): ohjelmallinen käyttö
