
# Pierwsze kroki

## Instalacja

### Wymagania

- PHP w wersji 8.2 lub nowszej oraz WordPress w wersji 6.4 lub nowszej
- MySQL 8.0+ lub MariaDB 10.6+. Procesy robocze pobierają zadania i należne harmonogramy za pomocą `SELECT ... FOR UPDATE SKIP LOCKED`, którego starsze serwery odrzucają z powodu błędu składni.
- `mysqli` lub `pdo_mysql` (zob. poniżej)
- WP-CLI na serwerze, jeśli uruchamiasz dedykowane procesy robocze za pomocą `wp queuety work`
- Rozszerzenia `pcntl` i `posix` PHP, jeśli uruchamiasz pule procesów roboczych z `--workers` lub `--min-workers`/`--max-workers`

Queuety wymaga środowiska uruchomieniowego PHP, które ładuje WordPress i WP-CLI, oraz jednego z elementów: `mysqli` lub `pdo_mysql`. Sterownik jest wybierany automatycznie; w środowiskach uruchomieniowych WordPress preferowane jest `mysqli`, a `pdo_mysql` pozostaje dostępne do samodzielnego lub bezpośredniego użycia środowiska.

Jeśli potrzebujesz środowiska uruchomieniowego opartego na bazie danych bez warstwy wtyczki WordPress, zobacz sekcję [Samodzielne użycie](https://queuety.inline0.dev/pl/docs/features/standalone-use). Ta ścieżka korzysta z tego samego połączenia i tabel środowiska uruchomieniowego, ale nie obejmuje mostów zaczepów WordPress ani rejestracji WP-CLI.

### Z archiwum ZIP wydania

Każde [GitHub wydanie](https://github.com/inline0/queuety/releases) zawiera zasób `queuety.zip`: wtyczkę z zainstalowanymi już zależnościami Composer. Zainstaluj najnowszą wersję za pomocą WP-CLI:

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

Możesz też pobrać archiwum ZIP i przesłać je w sekcji Wtyczki > Dodaj nową > Prześlij wtyczkę. To najprostsze rozwiązanie dla standardowej witryny WordPress.

### Za pomocą Composer dla zarządzanych przez Composer WordPress

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

Następnie aktywuj wtyczkę:

```bash
wp plugin activate queuety
```

Typ pakietu to `wordpress-plugin`. Composer umieszcza go w katalogu wtyczek tylko wtedy, gdy projekt wymaga `composer/installers` i mapuje ten typ na ścieżkę instalatora, tak jak robi to Bedrock, a projekt musi załadować własny `vendor/autoload.php` (Bedrock również to robi). Bez `composer/installers` Composer instaluje go w `vendor/queuety/queuety`, gdzie WordPress go nie znajdzie, dlatego przy zwykłej instalacji WordPress użyj archiwum zip z wydania.

### Ze źródeł podczas programowania

Umieść repozytorium w `wp-content/plugins/queuety`, a następnie zainstaluj zależności PHP:

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

Podczas aktywacji Queuety tworzy tabele bazy danych (`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`), aby procesy robocze mogły pobierać zadania bezpośrednio z MySQL.

Domyślnie wtyczka planuje też jednorazowy proces roboczy za pośrednictwem WordPress cron co minutę dla kolejki `default`. Zapewnia to podstawową obsługę zadań i przepływów pracy bez powłoki, działających w `default`, pod warunkiem że uruchamia się WordPress cron. Każde uruchomienie przetwarza najwyżej jedno zadanie i nie uruchamia harmonogramów cyklicznych, nie odzyskuje nieaktualnych zadań ani nie sprawdza terminów przepływów pracy; te funkcje działają wyłącznie w długotrwałym procesie `wp queuety work` ([#14](https://github.com/inline0/queuety/issues/14)). W przypadku własnych kolejek, harmonogramów cyklicznych, mniejszych opóźnień lub większego obciążenia przejdź na dedykowane procesy `wp queuety work`.

## Konfiguracja

Wszystkie stałe są opcjonalne. Zdefiniuj je w `wp-config.php` przed załadowaniem wtyczki albo przed uruchomieniem Queuety w instalacji osadzonej w motywie:

| Stała | Wartość domyślna | Opis |
|---|---|---|
| `QUEUETY_RETENTION_DAYS` | `7` | Domyślny wiek w dniach dla `wp queuety purge` i `Queuety::purge()`. Nic nie jest usuwane automatycznie |
| `QUEUETY_LOG_RETENTION_DAYS` | `0` | Odczytywana przez `Config::log_retention_days()`, ale jeszcze nieużywana; dzienniki są przechowywane do wywołania `Queuety::purge_logs()` ([#15](https://github.com/inline0/queuety/issues/15)) |
| `QUEUETY_MAX_EXECUTION_TIME` | `300` | Maksymalna liczba sekund na zadanie przed przekroczeniem limitu czasu (jeszcze nieegzekwowana, zob. [Zadania](https://queuety.inline0.dev/pl/docs/jobs#timeout)) |
| `QUEUETY_WORKER_SLEEP` | `1` | Liczba sekund oczekiwania, gdy kolejka jest pusta |
| `QUEUETY_WORKER_MAX_JOBS` | `1000` | Maksymalna liczba zadań przed ponownym uruchomieniem procesu roboczego |
| `QUEUETY_WORKER_MAX_MEMORY` | `128` | Maksymalna liczba MB przed ponownym uruchomieniem procesu roboczego |
| `QUEUETY_RETRY_BACKOFF` | `exponential` | Strategia ponawiania: `exponential`, `linear` lub `fixed` |
| `QUEUETY_STALE_TIMEOUT` | `600` | Liczba sekund do odzyskania zablokowanych zadań |
| `QUEUETY_CACHE_TTL` | `5` | Domyślny czas życia wpisu w pamięci podręcznej (TTL) w sekundach |
| `QUEUETY_DEBUG` | `false` | Włącza szczegółowe logowanie procesu roboczego |
| `QUEUETY_CLI_COMMAND` | `queuety` | Nazwa głównego polecenia WP-CLI |
| `QUEUETY_TABLE_PREFIX` | `queuety_` | Wspólna nazwa bazowa wszystkich tabel Queuety po prefiksie bazy danych WordPress |
| `QUEUETY_TABLE_JOBS` | `queuety_jobs` | Nazwa tabeli zadań |
| `QUEUETY_TABLE_WORKFLOWS` | `queuety_workflows` | Nazwa tabeli przepływów pracy |
| `QUEUETY_TABLE_LOGS` | `queuety_logs` | Nazwa tabeli dzienników |
| `QUEUETY_TABLE_SCHEDULES` | `queuety_schedules` | Nazwa tabeli harmonogramów |
| `QUEUETY_TABLE_SIGNALS` | `queuety_signals` | Nazwa tabeli sygnałów |
| `QUEUETY_TABLE_WORKFLOW_DEPENDENCIES` | `queuety_workflow_dependencies` | Nazwa tabeli oczekiwania na zależności przepływów pracy |
| `QUEUETY_TABLE_WORKFLOW_DISPATCH_KEYS` | `queuety_workflow_dispatch_keys` | Nazwa tabeli kluczy idempotencji trwałych przepływów pracy |
| `QUEUETY_TABLE_CHUNKS` | `queuety_chunks` | Nazwa tabeli fragmentów strumienia |
| `QUEUETY_TABLE_QUEUE_STATES` | `queuety_queue_states` | Nazwa tabeli stanów kolejek |
| `QUEUETY_TABLE_WEBHOOKS` | `queuety_webhooks` | Nazwa tabeli webhooków |
| `QUEUETY_TABLE_LOCKS` | `queuety_locks` | Nazwa tabeli blokad |
| `QUEUETY_TABLE_BATCHES` | `queuety_batches` | Nazwa tabeli partii |
| `QUEUETY_TABLE_WORKFLOW_EVENTS` | `queuety_workflow_events` | Nazwa tabeli dziennika zdarzeń przepływu pracy |
| `QUEUETY_TABLE_ARTIFACTS` | `queuety_artifacts` | Nazwa tabeli artefaktów przepływu pracy |
| `QUEUETY_TABLE_STATE_MACHINES` | `queuety_state_machines` | Nazwa tabeli maszyn stanów |
| `QUEUETY_TABLE_STATE_MACHINE_EVENTS` | `queuety_state_machine_events` | Nazwa tabeli dziennika zdarzeń maszyny stanów |
| `QUEUETY_DB_DRIVER` | `auto` | Sterownik MySQL: `auto`, `mysqli` lub `pdo`. `auto` preferuje `mysqli`, gdy załadowano WordPress; w przeciwnym razie `pdo_mysql`, a następnie `mysqli` |

Stałe dotyczące przyjmowania zasobów i adaptacyjnej puli (`QUEUETY_RESOURCE_*`, `QUEUETY_WORKER_POOL_*`) opisano na stronie [Procesy robocze](https://queuety.inline0.dev/pl/docs/features/workers).

`QUEUETY_TABLE_PREFIX` zmienia tylko część nazw tabel Queuety. Prefiks bazy danych WordPress nadal jest dodawany do wyniku, więc `$wpdb->prefix = 'wp_'` i `QUEUETY_TABLE_PREFIX = 'themequeue_'` tworzą tabele takie jak `wp_themequeue_jobs`. Jawnie określone stałe `QUEUETY_TABLE_*` nadal mają pierwszeństwo w przypadku poszczególnych tabel.

Samodzielne połączenia mogą też ustawiać prefiks tabel Queuety dla każdego połączenia:

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

Dzięki temu prefiks bazy danych WordPress pozostaje bez zmian, a zmienia się tylko segment tabeli Queuety.

## Pierwsze zadanie

Utwórz klasę obsługi, która implementuje interfejs `Handler`:

```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,
        ];
    }
}
```

Zarejestruj ją i zleć zadanie:

```php
use Queuety\Queuety;

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

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

Możesz też użyć nowoczesnej klasy zadania, którą można zlecić:

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

## Pierwszy przepływ pracy

Zdefiniuj procedury obsługi kroków, które implementują interfejs `Step`:

```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 [];
    }
}
```

Zleć przepływ pracy:

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

## Uruchamianie procesu roboczego

```bash
wp queuety work
```

Proces roboczy odpytuje kolejkę o oczekujące zadania, wykonuje je, przesuwa przepływy pracy do kolejnych etapów i czeka, gdy kolejka jest pusta. Naciśnij `Ctrl+C`, aby go zatrzymać; proces kończy się natychmiast, nawet w trakcie zadania (zob. [Procesy robocze](https://queuety.inline0.dev/pl/docs/features/workers#worker-lifecycle)).

Powyższy `SendEmailHandler` wysyła swoje zadania do kolejki `emails` za pośrednictwem `config()`, dlatego proces roboczy działający na `default` ich nie pobierze. Wymień wszystkie używane kolejki:

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

Jeśli nie uruchamiasz dedykowanego procesu roboczego, Queuety nadal korzysta z opisanego wyżej domyślnego mechanizmu awaryjnego WordPress cron uruchamianego raz na minutę; obsługuje on wyłącznie kolejkę `default` i jedno zadanie na uruchomienie. Dedykowany proces roboczy zapewnia większą przepustowość i mniejsze opóźnienia.

W środowisku produkcyjnym uruchom wiele procesów roboczych:

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

Przetwarzaj wiele kolejek z zachowaniem kolejności priorytetów:

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

## Co dalej

- [Zadania](https://queuety.inline0.dev/pl/docs/jobs) — kompletny przewodnik po zlecaniu i obsłudze zadań
- [Przepływy pracy](https://queuety.inline0.dev/pl/docs/workflows) — łańcuchy, kroki równoległe, rozgałęzianie warunkowe i uruchamianie przepływów pracy
- [Oprogramowanie pośredniczące](https://queuety.inline0.dev/pl/docs/features/middleware) — ograniczanie liczby żądań, przepustowości i własna logika potoku
- [Przetwarzanie partiami](https://queuety.inline0.dev/pl/docs/features/batching) — zlecanie grup zadań z funkcjami zwrotnymi
- [Kroki strumieniowe](https://queuety.inline0.dev/pl/docs/workflows/streaming) — zapisywanie przesyłanych danych fragment po fragmencie
- [Planowanie](https://queuety.inline0.dev/pl/docs/features/scheduling) — zadania cykliczne
- [Buforowanie](https://queuety.inline0.dev/pl/docs/features/caching) — rozszerzalna warstwa pamięci podręcznej
- [Testowanie](https://queuety.inline0.dev/pl/docs/features/testing) — QueueFake i asercje testowe
- [CLI Dokumentacja referencyjna ](https://queuety.inline0.dev/pl/docs/cli) — wszystkie dostępne polecenia
- [PHP API](https://queuety.inline0.dev/pl/docs/api) — dostęp programowy
