快速入门
安装
要求
- 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和posixPHP 扩展
Queuety 要求在加载 WordPress 和 WP-CLI 的 PHP 运行时中安装 mysqli 或 pdo_mysql。它会自动选择驱动程序:在 WordPress 运行时中优先使用 mysqli,同时保留 pdo_mysql 供独立或直接运行时使用。
如果你想在没有 WordPress 插件层的情况下使用由数据库支持的运行时,请参阅独立使用。该方式使用相同的连接和运行时数据表,但不包含 WordPress 钩子桥接器或 WP-CLI 注册。
从发布压缩包安装
每个 GitHub 版本都包含一个 queuety.zip 资源文件:插件及其 Composer 依赖项均已预先安装。使用 WP-CLI 安装最新版本:
wp plugin install https://github.com/inline0/queuety/releases/latest/download/queuety.zip --activate
也可以下载 zip 文件,然后在“插件 > 安装插件 > 上传插件”下上传。这是常规 WordPress 网站最简单的安装方式。
通过 Composer 管理的 WordPress 安装 Composer
composer require queuety/queuety
然后启用该插件:
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 依赖项:
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)。对于自定义队列、定期计划、更低延迟或更繁重的工作负载,请改用专用的 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) |
QUEUETY_MAX_EXECUTION_TIME |
300 |
每个任务超时前的最长秒数(目前尚未强制执行,参见 任务) |
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_*)列在工作进程页面上。
QUEUETY_TABLE_PREFIX 只会更改表名中的 Queuety 部分。WordPress 数据库前缀仍会添加在结果前,因此 $wpdb->prefix = 'wp_' 和 QUEUETY_TABLE_PREFIX = 'themequeue_' 会生成类似 wp_themequeue_jobs 的表。单个表的显式 QUEUETY_TABLE_* 常量仍具有优先级。
独立连接也可以为每个连接设置 Queuety 表前缀:
$conn = new Connection(
host: '127.0.0.1:3306',
dbname: 'wordpress',
user: 'root',
password: 'secret',
prefix: 'wp_',
table_prefix: 'themequeue_',
);
这样会保留 WordPress 数据库前缀,只更改 Queuety 表段。
你的第一个任务
创建一个实现 Handler 接口的处理器类:
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,
];
}
}
注册并派发:
use Queuety\Queuety;
Queuety::register( 'send_email', SendEmailHandler::class );
Queuety::dispatch( 'send_email', [
'to' => 'user@example.com',
'subject' => 'Welcome',
'body' => 'Hello from Queuety!',
] );
或者使用现代的可派发任务类:
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 接口的步骤处理器:
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 [];
}
}
派发工作流:
$workflow_id = Queuety::workflow( 'generate_report' )
->then( FetchDataHandler::class )
->then( CallLLMHandler::class )
->then( FormatOutputHandler::class )
->dispatch( [ 'user_id' => 42 ] );
启动工作进程
wp queuety work
工作进程会轮询待处理任务、执行任务、推进工作流,并在队列为空时休眠。按 Ctrl+C 停止;这会立即结束进程,即使当前任务尚未完成(参见工作进程)。
上面的 SendEmailHandler 会通过 config() 将任务发送到 emails 队列,因此运行在 default 上的工作进程不会获取这些任务。请为你使用的每个队列指定名称:
wp queuety work --queue=emails,default
如果你不运行专用工作进程,Queuety 仍会使用上文所述的默认每分钟一次的 WordPress cron 后备机制,但仅限 default 队列,且每次运行只处理一个任务。专用工作进程的吞吐量更高、延迟更低。
在生产环境中,运行多个工作进程:
wp queuety work --workers=4
按优先级顺序处理多个队列:
wp queuety work --queue=high,default,low