deliciousbrains / wp-background-processing
WP Background Processing 可以用来发起非阻塞的异步请求或作为后台处理工具,允许您排队任务。
Requires
- php: >=7.0
Requires (Dev)
- phpcompatibility/phpcompatibility-wp: *
- phpunit/phpunit: ^8.0
- spryker/code-sniffer: ^0.17.18
- wp-coding-standards/wpcs: ^2.3
- yoast/phpunit-polyfills: ^1.0
Suggests
- coenjacobs/mozart: Easily wrap this library with your own prefix, to prevent collisions when multiple plugins use this library
This package is auto-updated.
Last update: 2024-08-26 09:11:57 UTC
README
WP Background Processing 可以用来发起非阻塞的异步请求或作为后台处理工具,允许您排队任务。查看 示例插件 或阅读 相关文章。
灵感来源于 TechCrunch WP Asynchronous Tasks。
需要 PHP 5.6+
安装
在您的项目中安装此库的推荐方式是通过 Composer 加载
composer require deliciousbrains/wp-background-processing
强烈建议使用 Mozart 包 前缀包装库类文件,以防止与其他使用此库的项目冲突。
使用
异步请求
异步请求对于将缓慢的一次性任务(如发送邮件)推送到后台进程非常有用。一旦请求被派遣,它将立即在后台处理。
扩展 WP_Async_Request
类
class WP_Example_Request extends WP_Async_Request { /** * @var string */ protected $prefix = 'my_plugin'; /** * @var string */ protected $action = 'example_request'; /** * Handle a dispatched request. * * Override this method to perform any actions required * during the async request. */ protected function handle() { // Actions to perform. } }
protected $prefix
应设置为与您的插件、主题或网站的自定义函数前缀相关联的唯一前缀。
protected $action
应设置为唯一名称。
protected function handle()
应包含在非阻塞请求期间执行的任何逻辑。传递给请求的数据将通过 $_POST
可访问。
派遣请求
实例化您的请求
$this->example_request = new WP_Example_Request();
如果需要,向请求中添加数据
$this->example_request->data( array( 'value1' => $value1, 'value2' => $value2 ) );
发起请求
$this->example_request->dispatch();
也支持链式操作
$this->example_request->data( array( 'data' => $data ) )->dispatch();
后台进程
后台进程与异步请求的工作方式类似,但它们允许您排队任务。推送到队列的项目将在队列保存并派遣后后台处理。队列也将根据可用的服务器资源进行扩展,因此高端服务器将每批处理更多项目。一旦一批完成,下一批将立即开始。
默认情况下,每5分钟运行一次健康检查,以确保当队列中存在待处理项时队列正在运行。如果队列失败,它将重新启动。
队列按先进先出的原则工作,这允许在队列已处理时推送更多项目到队列。当另一个后台处理实例已经在运行时保存新的队列项并派遣,将导致派遣短路,现有实例最终将拾取新项目并在其轮到时进行处理。
扩展 WP_Background_Process
类
class WP_Example_Process extends WP_Background_Process { /** * @var string */ protected $prefix = 'my_plugin'; /** * @var string */ protected $action = 'example_process'; /** * Perform task with queued item. * * Override this method to perform any actions required on each * queue item. Return the modified item for further processing * in the next pass through. Or, return false to remove the * item from the queue. * * @param mixed $item Queue item to iterate over. * * @return mixed */ protected function task( $item ) { // Actions to perform. return false; } /** * Complete processing. * * Override if applicable, but ensure that the below actions are * performed, or, call parent::complete(). */ protected function complete() { parent::complete(); // Show notice to user or perform some other arbitrary task... } }
protected $prefix
应设置为与您的插件、主题或网站的自定义函数前缀相关联的唯一前缀。
protected $action
应设置为唯一名称。
protected function task( $item )
应包含对队列项执行的任何逻辑。返回 false
以从队列中删除项目或返回 $item
以将其推回队列进行进一步处理。如果项目已被修改并推回队列,则在退出批处理之前将保存当前状态。
protected function complete()
可选地包含在队列完成后执行的任何逻辑。
派遣进程
实例化您的进程
$this->example_process = new WP_Example_Process();
注意:您必须无条件地实例化您的进程。所有请求都应该这样做,即使队列中没有推送任何内容。
向队列中推入项目
foreach ( $items as $item ) { $this->example_process->push_to_queue( $item ); }
项目可以是任何有效的PHP值,如字符串、整数、数组或对象。如果需要,当写入数据库时,$item将被序列化。
保存并派发队列
$this->example_process->save()->dispatch();
处理队列项目中的序列化对象
包含非标量值的队列项目在存储到数据库时将被序列化。为了避免在unserialize期间出现潜在的安全问题,此库提供在调用unserialize()时设置allowed_classes
选项的功能,这限制了可以实例化的类。它作为受保护的$allowed_batch_data_classes
属性内部保留。
为了保持向下兼容性,默认值是true
,这意味着任何序列化的对象都将被实例化。请注意,这种默认行为可能会在未来的一次主要版本更新中更改。
我们鼓励所有使用此库的用户利用设置严格值$allowed_batch_data_classes
的优势。如果可能,将值设置为false
以禁止实例化任何对象,或者一个非常有限的类名列表,下面有示例。
不允许实例化的序列化字符串中的对象将获得类类型__PHP_Incomplete_Class
。
覆盖默认的$allowed_batch_data_classes
可以通过将允许的类数组传递给构造函数来覆盖默认行为
$allowed_batch_data_classes = array( MyCustomItem::class, MyItemHelper::class ); $this->example_process = new WP_Example_Process( $allowed_batch_data_classes );
或者,将其值设置为false
$this->example_process = new WP_Example_Process( false );
另一种更改默认值的方法是在您的进程类中覆盖$allowed_batch_data_classes
属性
class WP_Example_Process extends WP_Background_Process { /** * @var string */ protected $prefix = 'my_plugin'; /** * @var string */ protected $action = 'example_process'; /** * * @var bool|array */ protected $allowed_batch_data_classes = array( MyCustomItem::class, MyItemHelper::class ); ...
后台进程状态
后台进程可以是排队、处理、暂停、取消或上述都不是(未启动或已完成)。
排队
要检查后台进程是否有排队项,请使用is_queued()
。
if ( $this->example_process->is_queued() ) { // Do something because background process has queued items, e.g. add notice in admin UI. }
处理中
要检查后台进程是否正在处理队列项,请使用is_processing()
。
if ( $this->example_process->is_processing() ) { // Do something because background process is running, e.g. add notice in admin UI. }
暂停
您可以使用pause()
暂停后台进程。
$this->example_process->pause();
当前正在处理的批次将继续,直到它完成或达到时间或内存限制。在此之后,它将解锁进程,并在队列为空的情况下完成批次,或者执行一个派发操作,这将导致处理器删除健康检查cron并触发“暂停”动作。
要检查后台进程是否当前已暂停,请使用is_paused()
。
if ( $this->example_process->is_paused() ) { // Do something because background process is paused, e.g. add notice in admin UI. }
您可以通过处理后台进程标识符($prefix + $action)的“暂停”动作来对后台处理被暂停作出响应。
add_action( 'my_plugin_example_process_paused', function() { // Do something because background process is paused, e.g. add notice in admin UI. });
您可以使用resume()
恢复后台进程。
$this->example_process->resume();
您可以通过处理后台进程标识符($prefix + $action)的“恢复”动作来对后台处理被恢复作出响应。
add_action( 'my_plugin_example_process_resumed', function() { // Do something because background process is resumed, e.g. add notice in admin UI. });
已取消
您可以使用cancel()
取消后台进程。
$this->example_process->cancel();
当前正在处理的批次将继续,直到它完成或达到时间或内存限制。在此之后,它将解锁进程,并在队列为空的情况下完成批次,或者执行一个派发操作,这将导致处理器删除健康检查cron,删除所有排队项的批次并触发“已取消”动作。
要检查后台进程是否当前已取消,请使用is_cancelled()
。
if ( $this->example_process->is_cancelled() ) { // Do something because background process is cancelled, e.g. add notice in admin UI. }
您可以通过处理后台进程标识符($prefix + $action)的“已取消”动作来对后台处理被取消作出响应。
add_action( 'my_plugin_example_process_cancelled', function() { // Do something because background process is paused, e.g. add notice in admin UI. });
“已取消”动作在队列被清除并移除取消状态后触发。之后,is_cancelled()
将不再为真,因为后台进程现在是休眠的。
活动
要检查后台进程是否有排队项、正在处理、已暂停或正在取消,请使用is_active()
。
if ( $this->example_process->is_active() ) { // Do something because background process is active, e.g. add notice in admin UI. }
如果后台进程不活跃,那么它要么还没有任何待处理任务,要么已经处理完所有队列中的任务。
基本认证
如果你的网站在基本认证之后,异步请求和后台进程都将无法完成。这是因为WP后台处理依赖于WordPress HTTP API,它需要你在请求中附加基本认证凭据。最简单的方法是使用以下过滤器
function wpbp_http_request_args( $r, $url ) { $r['headers']['Authorization'] = 'Basic ' . base64_encode( USERNAME . ':' . PASSWORD ); return $r; } add_filter( 'http_request_args', 'wpbp_http_request_args', 10, 2);
贡献
我们欢迎通过拉取请求进行贡献,但请在开始任何工作之前先提出一个问题,以便讨论更改,如果还没有问题的话。如果您想解决的问题已经获得批准,请在该问题上发表评论,让大家知道您将尝试解决它,以免重复工作造成浪费。
单元测试和风格测试
在编写库时,请将单元测试添加到tests
目录中适当的文件中,以涵盖您的更改。
设置
我们使用标准的WordPress测试库来运行单元测试。
请运行以下命令来设置库
bin/install-wp-tests.sh db_name db_user db_pass
请根据需要替换db_name
、db_user
和db_pass
。
请注意,运行单元测试是一种破坏性操作,数据库表将被清空,因此请使用专用于运行单元测试的数据库名称。WordPress社区通常使用的标准数据库名称是wordpress_test
,例如
bin/install-wp-tests.sh wordpress_test root root
如果您遇到任何问题,请参阅WordPress手册中插件集成测试部分的本地初始化测试环境。
运行单元测试
要运行单元测试,只需运行
make test-unit
如果composer
依赖项尚未就绪,它们将被自动安装。
运行风格测试
确保库中的代码使用一致的风格对于快速理解它以及避免一些常见问题很重要。PHP_Code_Sniffer
主要使用标准的WordPress规则来帮助检查一致性。
要运行风格测试,只需运行
make test-style
如果composer
依赖项尚未就绪,它们将被自动安装。
运行所有测试
要使事情变得超级简单,只需运行以下命令来运行所有测试
make
如果composer
依赖项尚未就绪,它们将被自动安装。
创建PR
在创建PR时,请确保在描述的顶部提及要解决的GitHub问题,例如
解决 #123
单元测试和风格测试将自动运行,除非通过,否则PR将无法合并,并且分支必须与master
保持最新。