mkrmr/emphloyer

使用可插拔后端简化作业处理

v0.6.0 2019-05-08 10:02 UTC

This package is auto-updated.

Last update: 2024-09-11 21:33:02 UTC


README

在PHP应用的生命周期中,总有那么一个时刻,异步作业处理成为了一个必需。如果你想要一个灵活的解决方案,可以轻松地适应你的应用程序基础设施,那么Emphloyer可能正是你所需要的。

安装

您可以通过Composer安装Emphloyer:

composer require mkrmr/emphloyer

用法

使用Emphloyer非常简单,在你的应用程序代码中,你可以将作业排队,然后运行Emphloyer的命令行程序来处理队列。

在您开始使用Emphloyer之前,您需要:

  • 在实现\Emphloyer\Job接口的类中定义自己的作业,如果您愿意,可以扩展\Emphloyer\AbstractJob。
  • 将Emphloyer与后端连接起来以管理作业排队。

此外,您还可以使用Emphloyer来安排作业,就像在crontab中一样,为此,您需要将调度器与后端连接起来。

定义自己的作业

以下是一个作业实现的愚蠢示例

use Emphloyer\AbstractJob

class NameEchoJob extends AbstractJob 
{
   public function setName(string $name) : void 
   {
      $this->attributes['name'] = $name;
   }

   public function perform() : void 
   {
      echo "Hi, my name is {$this->attributes['name']}.\n";
   }
}

当作业排队时,属性数组中的任何内容都将被序列化。请注意,'className'和'type'键是保留的,不应在您自己的作业实现中使用。

perform方法是当Emphloyer运行作业时执行的,如果这引发异常,则作业将失败。

当作业失败时,mayTryAgain方法确定它是否可以再次尝试。例如,您可以在作业的内部属性中跟踪重试次数来实现重试行为。请注意,在perform方法中更改属性将不会将它们持久化到后端,因为perform方法在分叉进程中执行,并且永远不会与主进程通信,相反,在您的作业实例中实现beforeFail钩子,并让该钩子更新主进程中的作业实例的属性。

您可以根据作业的类型控制作业的进程数。当您从\Emphloyer\AbstractJob类继承时,默认情况下类型将设置为'job',您可以在入队之前使用setType方法为实例设置特定类型,或者您可以在类中覆盖$type实例变量来设置另一个默认值。

连接后端

Emphloyer通过其管道管理其作业,为了将作业喂入管道并从中获取作业,您需要将其与后端连接起来。您可以使用已构建的后端(例如Emphloyer-PDO)或实现自己的。要构建自己的后端,您必须实现\Emphloyer\Pipeline\Backend接口。

要启用Emphloyer使用您选择的后端运行,您需要创建一个在运行时引用的配置文件,以下是一个带注释的示例:

<?php
// $pipelineBackend defines the pipeline backend to use
$pipelineBackend = new \Emphloyer\Pdo\PipelineBackend('mysql:dbname=emphloyer_example;host=localhost', 'user', 'password');
// $employees determines the number of concurrent jobs, each job is forked off using pcntl_fork. Each entry is used, so if you specify duplicates that will simply add more employees for those types.
$employees = [
   ['exclude' => ['reports'], 'employees' => 2], // fork up to two processes for jobs of any type except 'reports'
   ['only' => ['reports', 'stuff'], 'employees' => 1], // fork up to one process for jobs of the types 'reports' and 'stuff'
   ['employees' => 4], // fork up to four processes for jobs of any type
];

设置您的配置文件后,您可以像这样让Emphloyer处理作业:

/path/to/project/vendor/bin/emphloyer -c /path/to/config_file.php

如果您想清除Pipeline中的作业,可以在上述命令中添加--clear。

要在应用程序代码中入队作业,您需要使用适当的后端实例化Pipeline,就像在配置文件中做的那样,然后您可以通过将实例传递给enqueue方法来简单地入队作业。

$pipelineBackend = new \Emphloyer\Pdo\PipelineBackend('mysql:dbname=emphloyer_example;host=localhost', 'user', 'password');
$pipeline = new \Emphloyer\Pipeline($pipelineBackend);
$queuedJob = $pipeline->enqueue($job);

如您从上述代码片段中看到的,enqueue方法返回一个作业对象,这是一个由后端enqueue方法返回的属性加载的新实例。后端应包含一个唯一id属性,可以用于识别作业(例如,Employer-PDO后端就是这样做的),如果您想轮询是否已完成的作业,这可能很有用。

AbstractJob类假定此属性存储在attributes数组中的id字段中,并提供了getId方法来访问它。要检查作业,可以使用带有作业id的Pipeline的find方法来加载它,根据后端,完成的作业可能不再存储,在这种情况下,该方法将返回null(例如,Employer-PDO后端将从数据库中删除完成的作业)。

除了使用pipeline外,您还可以使用scheduler以设置的时间间隔运行特定的作业,就像在crontab中一样。要这样做,您必须将scheduler连接到配置文件中设置pipeline相同的后端

// $schedulerBackend defines the scheduler backend to use
$schedulerBackend = new \Emphloyer\Pdo\SchedulerBackend('mysql:dbname=emphloyer_example;host=localhost', 'user', 'password');

与Pipeline一样,您可以使用他人构建的后端
已经构建好的(例如 Emphloyer-PDO,它很快将为Scheduler提供后端)或实现自己的。要构建自己的后端,您必须实现\Emphloyer\Scheduler\Backend接口。

如果您已跟随此README文件并之前启动了Emphloyer,您必须停止并重新启动它才能开始使用scheduler。

要安排作业,您需要使用配置文件中的适当后端实例化一个Scheduler,然后您可以通过将作业实例传递给schedule方法来安排作业

$schedulerBackend = new \Emphloyer\Pdo\SchedulerBackend('mysql:dbname=emphloyer_example;host=localhost', 'user', 'password');
$scheduler = new \Emphloyer\Scheduler($schedulerBackend);
// Arguments after the job follow the crontab syntax: minute, hour, day of month, month, day of week
$scheduler->schedule($job, 30, 12); // Schedules the job to be enqueued every day at 12:30

您可以使用Scheduler的allEntries方法来深入了解计划,它返回一个返回ScheduleEntry对象的迭代器。此外,您可以使用delete方法从计划中删除特定的条目。

贡献

  1. 将其Fork
  2. 创建您的功能分支(git checkout -b my-new-feature
  3. 进行更改,请确保尽可能遵守Doctrine编码标准(已包含phpcs配置)
  4. 提交您的更改(git commit -am '添加一些功能'
  5. 将更改推送到分支(git push origin my-new-feature
  6. 在GitHub上创建一个新的pull request