跳转到正文

WP-Cron 替代方案

Queuety 可以替代内置的 WordPress cron 系统。启用后,wp_schedule_event() 调用会被拦截,并通过 Queuety 的调度器转发,而不是使用默认的 WP-Cron 机制。事件应由 Queuety 工作进程处理,从而使任务执行不受网站流量影响。

当前限制: 桥接器会创建 Queuety 计划,但工作进程没有处理它们所生成的 __queuety_cron_{hook} 作业的处理程序,因此原始 WordPress 回调永远不会运行。每个作业都会失败、在退避后重试,最终被搁置(#9)。在此问题修复之前,请勿在必须运行 cron 事件的网站上启用该桥接器。

启用替代方案

在插件或主题初始化早期调用 Queuety::replace_wp_cron():

PHP
use Queuety\Queuety;

Queuety::replace_wp_cron();

通常会在插件的主文件中或在 plugins_loaded 钩子中调用此函数。调用时必须已加载 WordPress(插件必须处于启用状态)。

拦截内容

cron 桥接器会挂接到三个 WordPress 过滤器:

WordPress 函数 挂接的过滤器 行为
wp_schedule_event() pre_schedule_event 创建间隔相同的 Queuety 计划
wp_unschedule_event() pre_unschedule_event 移除相应的 Queuety 计划
wp_get_scheduled_event() pre_get_scheduled_event 从 Queuety 返回计划数据

只有重复执行的事件(即具有 schedule 属性,例如 hourly、twicedaily、daily 的事件)会被拦截。使用 wp_schedule_single_event() 计划的一次性事件不会被拦截。

事件映射方式

插件调用 wp_schedule_event() 时,Queuety 会通过 wp_get_schedules() 解析计划名称,创建一个处理程序名称为 __queuety_cron_{hook} 的 Queuety 计划,并将原始 WordPress 钩子名称及参数存储在计划载荷中。

预期的行为是:处理该计划作业的 Queuety 工作进程会使用原始钩子名称和参数调用 do_action(),使现有的 WordPress 回调在 Queuety 的调度下运行。CronBridge::process_cron_event() 实现了这项调用,但目前还没有任何代码调用它(参见上文的限制)。计划也只会由长期运行的 wp queuety work 进程评估,大约每分钟一次(参见调度)。

间隔解析

桥接器会先通过 wp_get_schedules() 解析计划名称,然后回退到内置默认值:

计划名称 间隔
hourly 3,600 秒
twicedaily 43,200 秒
daily 86,400 秒
weekly 604,800 秒

只要 wp_get_schedules() 返回通过 cron_schedules 过滤器注册的自定义计划间隔,就支持这些间隔。

恢复 WP-Cron

要恢复使用默认的 WordPress cron 系统:

PHP
Queuety::restore_wp_cron();

这会移除过滤器钩子,并让 WordPress 再次通过其内置机制处理 cron 事件。请注意,安装桥接器时会将 DISABLE_WP_CRON 定义为 true,且运行时无法取消定义,因此你可能需要从 wp-config.php 中移除该常量,或重启进程。

适用场景

当网站流量较低、需要比 WP-Cron 更可靠的定时机制,或者已经运行 Queuety 工作进程并希望让 cron 执行也纳入同一套运维系统时,替代方案最有用。它也有助于集中监控,因为此时 cron 事件会与其他队列任务一起显示在相同的日志和指标中。

限制

这里有几项重要限制。必须有一个正在运行的 Queuety 工作进程,否则计划事件永远不会运行。只有重复计划会被拦截;使用 wp_schedule_single_event() 创建的一次性事件仍在桥接器之外。replace_wp_cron() 还会为当前 PHP 进程的剩余生命周期定义 DISABLE_WP_CRON,因此 restore_wp_cron() 会移除钩子,但无法取消定义该常量。最后,只有在加载了 WordPress 时桥接器才会工作,因为它依赖 WordPress 过滤器和 do_action()。

示例:完整配置

PHP
use Queuety\Queuety;

// In your plugin's main file.
add_action( 'plugins_loaded', function () {
    Queuety::replace_wp_cron();
} );

此处无需调用 Queuety::init():已启用的 Queuety 插件会根据 WordPress 数据库凭据建立连接,并在 plugins_loaded 时初始化自身。replace_wp_cron() 只负责安装过滤器,因此不依赖上述初始化是否已完成。

完成此操作后,插件通过 wp_schedule_event() 注册的重复事件会作为 Queuety 计划存储。在 #9 修复之前,这些事件的回调不会运行。