
# 快速入门

## 安装

### 要求

- PHP 8.2 或更高版本，以及 WordPress 6.4 或更高版本
- MySQL 8.0+ 或 MariaDB 10.6+。工作进程使用 `SELECT ... FOR UPDATE SKIP LOCKED` 领取作业和到期计划，较旧的服务器会因语法错误而拒绝该语句。
- `mysqli` 或 `pdo_mysql`（见下文）
- 如果使用 `wp queuety work` 运行专用工作进程，服务器上必须有 WP-CLI
- 如果使用 `--workers` 或 `--min-workers`/`--max-workers` 运行工作进程池，则必须安装 `pcntl` 和 `posix` PHP 扩展

Queuety 要求在加载 WordPress 和 WP-CLI 的 PHP 运行时中安装 `mysqli` 或 `pdo_mysql`。它会自动选择驱动程序：在 WordPress 运行时中优先使用 `mysqli`，同时保留 `pdo_mysql` 供独立或直接运行时使用。

如果你想在没有 WordPress 插件层的情况下使用由数据库支持的运行时，请参阅[独立使用](https://queuety.inline0.dev/zh/docs/features/standalone-use)。该方式使用相同的连接和运行时数据表，但不包含 WordPress 钩子桥接器或 WP-CLI 注册。

### 从发布压缩包安装

每个 [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 管理的 WordPress 安装 Composer

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

然后启用该插件：

```bash
wp plugin activate queuety
```

包类型为 `wordpress-plugin`。只有当项目需要 `composer/installers`，并将该类型映射到安装器路径（如 Bedrock 所做的那样）时，Composer 才会将其放入插件目录；项目还必须加载自己的 `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` 上的任务和工作流提供了无需 shell 的基础方案，前提是 WordPress cron 正常触发。每次运行最多处理一个任务，且不会触发定期计划、恢复过期任务或检查工作流截止时间；这些功能只会在长时间运行的 `wp queuety work` 进程中执行（[#14](https://github.com/inline0/queuety/issues/14)）。对于自定义队列、定期计划、更低延迟或更繁重的工作负载，请改用专用的 `wp queuety work` 进程。

## 配置

所有常量都是可选的。在插件加载前，或在嵌入式主题风格安装中 Queuety 启动前，将它们定义在 `wp-config.php` 中：

| 常量 | 默认值 | 描述 |
|---|---|---|
| `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/zh/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` | Webhook 表名称 |
| `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` 在加载 WordPress 时优先使用 `mysqli`，否则使用 `pdo_mysql`，再否则使用 `mysqli` |

资源准入和自适应池常量（`QUEUETY_RESOURCE_*`、`QUEUETY_WORKER_POOL_*`）列在[工作进程](https://queuety.inline0.dev/zh/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/zh/docs/features/workers#worker-lifecycle)）。

上面的 `SendEmailHandler` 会通过 `config()` 将任务发送到 `emails` 队列，因此运行在 `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/zh/docs/jobs)：完整的派发和处理器指南
- [工作流](https://queuety.inline0.dev/zh/docs/workflows)：任务链、并行步骤、条件分支和运行工作流
- [中间件](https://queuety.inline0.dev/zh/docs/features/middleware)：速率限制、节流和自定义管道逻辑
- [批处理](https://queuety.inline0.dev/zh/docs/features/batching)：派发带回调的任务组
- [流式步骤](https://queuety.inline0.dev/zh/docs/workflows/streaming)：逐块保存流式数据
- [调度](https://queuety.inline0.dev/zh/docs/features/scheduling)：定期任务
- [缓存](https://queuety.inline0.dev/zh/docs/features/caching)：可插拔的缓存层
- [测试](https://queuety.inline0.dev/zh/docs/features/testing)：QueueFake 和测试断言
- [CLI参考](https://queuety.inline0.dev/zh/docs/cli)：所有可用命令
- [PHP API](https://queuety.inline0.dev/zh/docs/api)：以编程方式访问
