
# Първи стъпки

## Инсталиране

### Изисквания

- 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. Автоматично избира драйвера, като предпочита `mysqli` за среди за изпълнение WordPress и запазва `pdo_mysql` за самостоятелно или директно използване на средата за изпълнение.

Ако искате среда за изпълнение, която използва базата данни, без слоя на плъгина WordPress, вижте [Самостоятелно използване](https://queuety.inline0.dev/bg/docs/features/standalone-use). Този подход използва същата връзка и таблици на средата за изпълнение, но не включва мостовете за хукове WordPress или регистрацията WP-CLI.

### От ZIP архива на изданието

Всяко [издание на GitHub](https://github.com/inline0/queuety/releases) съдържа ресурс `queuety.zip`: плъгина с вече инсталирани зависимости Composer. Инсталирайте най-новата версия с WP-CLI:

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

Можете също да изтеглите ZIP архива и да го качите от Разширения > Добавяне на ново > Качване на разширение. Това е най-лесният начин за стандартен сайт 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/bg/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 след DB префикса 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/bg/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!',
] );
```

Или използвайте съвременния клас на задача за разпределяне:

```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/bg/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/bg/docs/jobs) за пълното ръководство за разпределяне и обработчици
- [Работни процеси](https://queuety.inline0.dev/bg/docs/workflows) за вериги, паралелни стъпки, условно разклоняване и изпълнение на работни процеси
- [Междинен софтуер](https://queuety.inline0.dev/bg/docs/features/middleware) за ограничаване на честотата, регулиране на натоварването и персонализирана логика на конвейера
- [Пакетна обработка](https://queuety.inline0.dev/bg/docs/features/batching) за разпределяне на групи задачи с обратни извиквания
- [Поточни стъпки](https://queuety.inline0.dev/bg/docs/workflows/streaming) за запазване на поточните данни на части
- [Планиране](https://queuety.inline0.dev/bg/docs/features/scheduling) за повтарящи се задачи
- [Кеширане](https://queuety.inline0.dev/bg/docs/features/caching) за разширяемия слой на кеша
- [Тестване](https://queuety.inline0.dev/bg/docs/features/testing) за QueueFake и твърденията при тестване
- [Справочник CLI](https://queuety.inline0.dev/bg/docs/cli) за всички налични команди
- [PHP API](https://queuety.inline0.dev/bg/docs/api) за програмен достъп
