mkrmr / emphloyer
使用可插拔后端简化作业处理
Requires
- php: >=7.2.0
- ext-pcntl: *
- ext-posix: *
- psr/log: ^1.0
Requires (Dev)
- doctrine/coding-standard: ^6.0
- phpunit/phpunit: ^8
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方法从计划中删除特定的条目。
贡献
- 将其Fork
- 创建您的功能分支(
git checkout -b my-new-feature
) - 进行更改,请确保尽可能遵守Doctrine编码标准(已包含phpcs配置)
- 提交您的更改(
git commit -am '添加一些功能'
) - 将更改推送到分支(
git push origin my-new-feature
) - 在GitHub上创建一个新的pull request