跳转到正文

快速入门

安装

要求

  • 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 插件层的情况下使用由数据库支持的运行时,请参阅独立使用。该方式使用相同的连接和运行时数据表,但不包含 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 表前缀:

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 ] );

启动工作进程

命令行
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

接下来