moderntribe/square1-queues

为square one提供队列服务

4.2.0 2022-10-25 16:44 UTC

README

队列库提供了一个用于处理可能缓慢、耗时或网络依赖的任务的实用程序。

使用MySQL后端配置队列

Queue_DefinerQueue_SubscriberMysql_Backend_DefinerMysql_Backend_Subscriber包含在您的Core.php中,确保在队列提供者之后添加MySQL提供者项。

运行以下命令创建队列数据库表

wp s1 queues add-table

获取队列对象

尽管可以(并且在极少数情况下是合适的)有多个队列,但大多数情况下,项目将使用单个默认队列。使用DI容器,您的类构造函数应接收一个\Tribe\Libs\Queues\Contracts\Queue。自动装配应负责其余部分,为您提供适当的队列类的实例,具有配置的后端。

class Example_Class {
  private $queue;
  public function __construct( \Tribe\Libs\Queues\Contracts\Queue $queue ) {
    $this->queue = $queue;
  }
}

创建任务处理器

如果您要将事物放入队列,那么您很可能需要创建一个自定义任务处理器。要创建Task类,实现Tribe\Project\Queues\Contracts\Task

必须实现handle(array $args)方法,并在成功时返回true(任务被标记为完成并从队列中删除),在失败时返回false(任务被添加回队列以再次尝试)。

任务处理器实例在隔离状态下运行,但仍支持自动装配和依赖注入。

示例任务

<?php declare(strict_types=1);

namespace Tribe\Project\Queues\Tasks;

use Tribe\Libs\Queues\Contracts\Task;
use Tribe\Project\Posts\Post_Fetcher;

/**
 * An example of Queue Task using dependency injection
 */
class Cache_Slow_Query implements Task {

	public const OPTION = 'tribe_latest_post_cache';

	/**
	 * Example dependency injection: This object will be
	 * the service responsible for handling complex logic
	 * for this task. Moving the logic to a service object
	 * allows that functionality to be shared outside
	 * this task in case something else needs to consume
	 * it.
	 */
	private Post_Fetcher $post_fetcher;

	/**
	 * @param \Tribe\Project\Posts\Post_Fetcher $post_fetcher This is a concrete class. PHP-DI knows to automatically
	 *                                                        inject the instance without any needed configuration.
	 */
	public function __construct( Post_Fetcher $post_fetcher ) {
		$this->post_fetcher = $post_fetcher;
	}

	/**
	 * @param array $args This variable populated with the dynamic data you set
	 *                    when the Queue Task is dispatched.
	 *
	 * @example          $queue->dispatch( Tribe\Project\Queues\Tasks\Cache_Slow_Query::class, [ 'my_custom_post_type' ] );
	 *
	 * @return bool
	 */
	public function handle( array $args ): bool {
		// Create the $post_type variable via unpacking of $args[0]
		[ $post_type ] = $args;

		/**
		 * Fetch the posts from some very long and intensive query.
		 *
		 * @var \WP_Query $query
		 */
		$query = $this->post_fetcher->get_latest_posts( $post_type );

		/*
		 * There are no posts, so return true to avoid placing this back in the queue to run
		 * again until posts are found.
		 *
		 * In this scenario, we'd rather just check that the next time this task is dispatched
		 * to the queue.
		 */
		if ( empty( $query->posts ) ) {
			return true;
		}

		/*
		 * If for some reason our option update doesn't work, it'll automatically be placed back in the
		 * queue to try again.
		 *
		 * Some other service will query this option to display the posts instead of running the
		 * massive query above in real time.
		 */
		return update_option( self::OPTION, $query->posts, false );
	}

}

将任务添加到队列

您将任务调度到队列以指示处理任务的类以及传递给handle()方法的参数数组。例如,如果您的任务需要Post ID来完成其处理,您可以在调度时填充$args变量,并将静态值保存到队列中,以便在任务处理时使用。

add_action( 'save_post', function ( $post_id ): void {
	$queue->dispatch( My_Task::class, [
		(int) $post_id,
	] );
}, 10, 1 );

处理队列

使用WP-CLI wp s1 queues process <queue-name>。这将处理队列中的所有项目。

使用系统crontab,设置一个每5分钟运行一次的任务来启动队列处理。此任务将运行大约五分钟,每秒检查队列中是否有要执行的任务(如果没有任何任务,则空闲)。在五分钟时间限制后,进程将优雅地终止。

您可以使用--timelimit=<time in seconds>选项自定义时间限制,例如,将默认的300秒更改为500

wp s1 queues process default --timelimit=500

除了处理队列的cron,还应设置一个cron来清理队列中的旧数据。wp s1 queues cleanup <queue-name>

如果WP CLI不可用(例如在较旧的WP Engine堆栈上),则可以在WP Cron中处理队列。Cron支持默认情况下是禁用的,但可以通过将WP_DISABLE_CRON设置为false来启用。**这不是使用队列的首选方法,但可以在系统级CLI访问不可用的情况下使用**。

Cron任务

队列应在cronjob上运行与timelimit一样长的时间。

# Run for the default 300 seconds/5 minutes
*/5 * * * * wp --path=/path/to/wordpress s1 queues process default

# Clean up old queue tasks every 30 minutes
*/30 * * * * wp --path=/path/to/wordpress s1 queues cleanup default

创建额外的队列

通过扩展Tribe\Project\Queues\Contracts\Queue类来添加队列。

队列类只需要get_name()方法。类DefaultQueue是一个很好的例子。

要创建一个Queue对象,注入后端对象。当使用自动装配时,DI容器将自动注入全局后端。但是如果你使用额外的队列,可能是因为你想与不同的后端进行通信。

内置任务

Noop

这是一个测试队列是否功能正常的良好任务,Noop通常会第一次正确处理任务。你可以在$args['fake']中添加任何你想要的消息,例如:$queue->dispatch( Noop::class, [ 'fake' => '自定义消息' ] );

电子邮件

内置了一个用于wp_mail()的任务。要使用它,你需要在你的WP配置中添加以下内容:define( 'QUEUE_MAIL', true );你也可以选择性地使用QUEUE_MAIL_QUEUE_NAME定义一个默认队列名称。如果没有设置此值,它将默认为default。要使用WP-CLI处理队列中的邮件项,请运行wp s1 queues process <queue-name>

其他CLI命令

wp s1 queues add-tasks [--count=0] 如果你需要测试队列/后端是否已注册并正常工作。默认情况下,这将创建一个随机(1-50)的Noop任务。Noop大约有10%的时间会失败,所以你也可以验证ack/nack是否按预期工作。

wp s1 queues list 列出已注册的队列和相应的后端。