WP-Cron 替代方案
Queuety 可以替代内置的 WordPress cron 系统。启用后,wp_schedule_event() 调用会被拦截,并通过 Queuety 的调度器转发,而不是使用默认的 WP-Cron 机制。事件应由 Queuety 工作进程处理,从而使任务执行不受网站流量影响。
当前限制: 桥接器会创建 Queuety 计划,但工作进程没有处理它们所生成的
__queuety_cron_{hook}作业的处理程序,因此原始 WordPress 回调永远不会运行。每个作业都会失败、在退避后重试,最终被搁置(#9)。在此问题修复之前,请勿在必须运行 cron 事件的网站上启用该桥接器。
启用替代方案
在插件或主题初始化早期调用 Queuety::replace_wp_cron():
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 系统:
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()。
示例:完整配置
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 修复之前,这些事件的回调不会运行。