
# Початок роботи

## Встановлення

### Вимоги

- PHP 8.2 або новіша версія та WordPress 6.4 або новіша версія
- MySQL 8.0+ або MariaDB 10.6+. Воркери отримують завдання та прострочені розклади за допомогою `SELECT ... FOR UPDATE SKIP LOCKED`, яку старіші сервери відхиляють із синтаксичною помилкою.
- `mysqli` або `pdo_mysql` (див. нижче)
- WP-CLI на сервері, якщо ви запускаєте виділені воркери з `wp queuety work`
- Розширення `pcntl` і `posix` PHP, якщо ви запускаєте пули воркерів з `--workers` або `--min-workers`/`--max-workers`

Queuety потребує або `mysqli`, або `pdo_mysql` у середовищі виконання PHP, що завантажує WordPress і WP-CLI. Драйвер вибирається автоматично: для середовищ виконання WordPress пріоритет має `mysqli`, а `pdo_mysql` доступний для автономного або прямого використання середовища виконання.

Якщо потрібне середовище виконання з базою даних без рівня плагіна WordPress, див. [Автономне використання](https://queuety.inline0.dev/uk/docs/features/standalone-use). У цьому режимі використовуються ті самі з’єднання й таблиці середовища виконання, але немає мостів хуків WordPress і реєстрації WP-CLI.

### З архіву випуску

Кожен випуск [GitHub має `queuety.zip`-архів ](https://github.com/inline0/queuety/releases): плагін із уже встановленими залежностями Composer. Установіть найновіший за допомогою WP-CLI:

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

Або завантажте zip-архів і вивантажте його в розділі Plugins > Add New > Upload Plugin. Це найпростіший спосіб для звичайного сайту WordPress.

### Через Composer для Composer-керованого WordPress

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

Потім активуйте плагін:

```bash
wp plugin activate queuety
```

Тип пакета — `wordpress-plugin`. Composer розміщує його в каталозі плагінів, лише якщо проєкт потребує `composer/installers` і зіставляє цей тип зі шляхом встановлення, як це робить Bedrock; також проєкт має завантажувати власний `vendor/autoload.php` (це теж робить Bedrock). Без `composer/installers` команда Composer встановлює пакет у `vendor/queuety/queuety`, де WordPress його не знаходить, тож на звичайній інсталяції WordPress використовуйте zip-архів випуску.

### З вихідного коду під час розробки

Розмістіть репозиторій у `wp-content/plugins/queuety`, а потім установіть залежності PHP:

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

Під час активації Queuety створює таблиці бази даних (`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`), щоб воркери могли отримувати завдання безпосередньо з MySQL.

За замовчуванням плагін також планує одноразовий запуск воркера через WordPress cron щохвилини для черги `default`. Це дає змогу виконувати завдання й робочі процеси без оболонки, які залишаються на `default`, за умови, що спрацьовує WordPress cron. Кожен запуск обробляє щонайбільше одне завдання; він не запускає повторювані розклади, не відновлює застарілі завдання й не перевіряє дедлайни робочих процесів. Усе це працює лише в довготривалому процесі `wp queuety work` ([#14](https://github.com/inline0/queuety/issues/14)). Для власних черг, повторюваних розкладів, меншої затримки або інтенсивніших навантажень перейдіть на виділені процеси `wp queuety work`.

## Конфігурація

Усі константи необов’язкові. Визначте їх у `wp-config.php` до завантаження плагіна або до запуску Queuety у вбудованій інсталяції в стилі теми:

| Константа | За замовчуванням | Опис |
|---|---|---|
| `QUEUETY_RETENTION_DAYS` | `7` | Стандартний вік у днях для `wp queuety purge` і `Queuety::purge()`. Автоматичне очищення не виконується |
| `QUEUETY_LOG_RETENTION_DAYS` | `0` | Зчитується `Config::log_retention_days()`, але поки не використовується; журнали зберігаються, доки ви не викличете `Queuety::purge_logs()` ([#15](https://github.com/inline0/queuety/issues/15)) |
| `QUEUETY_MAX_EXECUTION_TIME` | `300` | Максимальна кількість секунд на завдання до тайм-ауту (поки не застосовується, див. [Завдання](https://queuety.inline0.dev/uk/docs/jobs#timeout)) |
| `QUEUETY_WORKER_SLEEP` | `1` | Кількість секунд очікування, коли черга порожня |
| `QUEUETY_WORKER_MAX_JOBS` | `1000` | Максимальна кількість завдань до перезапуску воркера |
| `QUEUETY_WORKER_MAX_MEMORY` | `128` | Максимальний обсяг пам’яті в MB до перезапуску воркера |
| `QUEUETY_RETRY_BACKOFF` | `exponential` | Стратегія збільшення інтервалу: `exponential`, `linear` або `fixed` |
| `QUEUETY_STALE_TIMEOUT` | `600` | Кількість секунд до відновлення завислих завдань |
| `QUEUETY_CACHE_TTL` | `5` | Стандартний TTL кешу в секундах |
| `QUEUETY_DEBUG` | `false` | Увімкнути докладне журналювання воркера |
| `QUEUETY_CLI_COMMAND` | `queuety` | Назва кореневої команди WP-CLI |
| `QUEUETY_TABLE_PREFIX` | `queuety_` | Спільна базова назва всіх таблиць Queuety після префікса бази даних WordPress |
| `QUEUETY_TABLE_JOBS` | `queuety_jobs` | Назва таблиці завдань |
| `QUEUETY_TABLE_WORKFLOWS` | `queuety_workflows` | Назва таблиці робочих процесів |
| `QUEUETY_TABLE_LOGS` | `queuety_logs` | Назва таблиці журналів |
| `QUEUETY_TABLE_SCHEDULES` | `queuety_schedules` | Назва таблиці розкладів |
| `QUEUETY_TABLE_SIGNALS` | `queuety_signals` | Назва таблиці сигналів |
| `QUEUETY_TABLE_WORKFLOW_DEPENDENCIES` | `queuety_workflow_dependencies` | Назва таблиці очікування залежностей робочих процесів |
| `QUEUETY_TABLE_WORKFLOW_DISPATCH_KEYS` | `queuety_workflow_dispatch_keys` | Назва таблиці ключів ідемпотентності довготривалих робочих процесів |
| `QUEUETY_TABLE_CHUNKS` | `queuety_chunks` | Назва таблиці фрагментів потокових даних |
| `QUEUETY_TABLE_QUEUE_STATES` | `queuety_queue_states` | Назва таблиці станів черг |
| `QUEUETY_TABLE_WEBHOOKS` | `queuety_webhooks` | Назва таблиці вебхуків |
| `QUEUETY_TABLE_LOCKS` | `queuety_locks` | Назва таблиці блокувань |
| `QUEUETY_TABLE_BATCHES` | `queuety_batches` | Назва таблиці пакетів |
| `QUEUETY_TABLE_WORKFLOW_EVENTS` | `queuety_workflow_events` | Назва таблиці журналу подій робочих процесів |
| `QUEUETY_TABLE_ARTIFACTS` | `queuety_artifacts` | Назва таблиці артефактів робочих процесів |
| `QUEUETY_TABLE_STATE_MACHINES` | `queuety_state_machines` | Назва таблиці автоматів станів |
| `QUEUETY_TABLE_STATE_MACHINE_EVENTS` | `queuety_state_machine_events` | Назва таблиці журналу подій автоматів станів |
| `QUEUETY_DB_DRIVER` | `auto` | Драйвер MySQL: `auto`, `mysqli` або `pdo`. `auto` надає перевагу `mysqli`, якщо завантажено WordPress, інакше — `pdo_mysql`, а потім `mysqli` |

Константи для допуску ресурсів та адаптивних пулів (`QUEUETY_RESOURCE_*`, `QUEUETY_WORKER_POOL_*`) наведено на сторінці [Воркери](https://queuety.inline0.dev/uk/docs/features/workers).

`QUEUETY_TABLE_PREFIX` змінює лише сегмент Queuety у назвах таблиць. Префікс бази даних WordPress усе одно додається до результату, тож `$wpdb->prefix = 'wp_'` і `QUEUETY_TABLE_PREFIX = 'themequeue_'` створюють таблиці на кшталт `wp_themequeue_jobs`. Для окремих таблиць пріоритет мають явно задані константи `QUEUETY_TABLE_*`.

Автономні з’єднання також можуть задавати префікс таблиць Queuety для кожного з’єднання:

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

Так префікс бази даних WordPress залишається незмінним, а змінюється лише сегмент
таблиці Queuety.

## Ваше перше завдання

Створіть клас обробника, що реалізує інтерфейс `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,
        ];
    }
}
```

Зареєструйте його та поставте завдання в чергу:

```php
use Queuety\Queuety;

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

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

Або скористайтеся сучасним класом завдання з методом dispatch:

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

## Ваш перший робочий процес

Створіть обробники кроків, що реалізують інтерфейс `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 [];
    }
}
```

Поставте робочий процес у чергу:

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

## Запустіть воркер

```bash
wp queuety work
```

Воркер перевіряє наявність завдань, виконує їх, просуває робочі процеси далі й очікує, коли черга порожня. Натисніть `Ctrl+C`, щоб зупинити його; процес завершиться негайно, навіть посеред виконання завдання (див. [Воркери](https://queuety.inline0.dev/uk/docs/features/workers#worker-lifecycle)).

Наведений вище `SendEmailHandler` надсилає завдання до черги `emails` через `config()`, тому воркер для `default` їх не отримає. Указуйте назви всіх черг, якими користуєтеся:

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

Якщо ви не запускаєте окремий воркер, Queuety і далі використовує стандартний резервний варіант: WordPress cron запускається раз на хвилину, обробляє лише чергу `default` та одне завдання за запуск. Окремий воркер забезпечує більшу пропускну здатність і меншу затримку.

Для робочого середовища запустіть кілька воркерів:

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

Обробляйте кілька черг у порядку пріоритету:

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

## Що далі

- [Завдання](https://queuety.inline0.dev/uk/docs/jobs) — повний посібник із постановки завдань у чергу та обробників
- [Робочі процеси](https://queuety.inline0.dev/uk/docs/workflows) — ланцюжки, паралельні кроки, розгалуження за умовами та запуск робочих процесів
- [Проміжне ПЗ](https://queuety.inline0.dev/uk/docs/features/middleware) — обмеження частоти, уповільнення та логіка власного конвеєра
- [Пакетна обробка](https://queuety.inline0.dev/uk/docs/features/batching) — постановка груп завдань у чергу зі зворотними викликами
- [Потокові кроки](https://queuety.inline0.dev/uk/docs/workflows/streaming) — збереження потокових даних фрагмент за фрагментом
- [Планування](https://queuety.inline0.dev/uk/docs/features/scheduling) — повторювані завдання
- [Кешування](https://queuety.inline0.dev/uk/docs/features/caching) — підключний рівень кешування
- [Тестування](https://queuety.inline0.dev/uk/docs/features/testing) — QueueFake і твердження для тестів
- [CLI Довідник](https://queuety.inline0.dev/uk/docs/cli) — усі доступні команди
- [PHP API](https://queuety.inline0.dev/uk/docs/api) — програмний доступ
