spatie / laravel-long-running-tasks
处理Laravel应用中的长时间运行的任务
Requires
- php: ^8.2
- illuminate/contracts: ^10.0|^11.0
- spatie/laravel-package-tools: ^1.14.0
- spatie/test-time: ^1.3
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^7.0|^8.1
- orchestra/testbench: ^8.8|^9.0
- pestphp/pest: ^2.20
- pestphp/pest-plugin-arch: ^2.5
- pestphp/pest-plugin-laravel: ^2.0
- spatie/laravel-ray: ^1.26
README
一些服务,如AWS Rekognition,允许你在它们那边启动任务。任务完成时,不是发送webhook,而是服务期望你定期轮询以了解任务何时完成(或获取更新的状态)。
此包可以帮助您监视这些在外部执行的长运行任务。
您可以通过创建以下类型的任务来实现。
use Spatie\LongRunningTasks\LongRunningTask; use Spatie\LongRunningTasks\Enums\TaskResult; use Spatie\LongRunningTasks\LongRunningTask; class MyTask extends LongRunningTask { public function check(LongRunningTaskLogItem $logItem): TaskResult { // get some information about this task $meta = $logItem->meta // do some work here $allWorkIsDone = /* ... */ // return wheter we should continue the task in a new run return $allWorkIsDone ? TaskResult::StopChecking : TaskResult::ContinueChecking } }
当返回TaskResult::ContinueChecking
时,此check
函数将在10秒后再次被调用(如配置文件中的default_check_frequency_in_seconds
定义的那样)。
创建您的任务后,您可以像这样启动它。
MyTask::make()->meta($anArray)->start();
直到返回TaskResult::StopChecking
,MyTask
的check
方法将每10秒被调用一次。
安装
您可以通过composer安装此包
composer require spatie/laravel-long-running-tasks
您可以使用以下命令发布和运行迁移
php artisan vendor:publish --tag="long-running-tasks-migrations"
php artisan migrate
您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="long-running-tasks-config"
这是已发布配置文件的内容
return [ /* * Behind the scenes, this packages use a queue to call tasks. * Here you can choose the queue that should be used by default. */ 'queue' => 'default', /* * If a task determines that it should be continued, it will * be called again after this amount of time */ 'default_check_frequency_in_seconds' => 10, /* * The default class that implements a strategy for determining the check frequency in seconds. * - `DefaultCheckStrategy` will check the task every `LongRunningTaskLogItem::check_frequency_in_seconds` seconds. * - `StandardBackoffCheckStrategy` will check the task every `LongRunningTaskLogItem::check_frequency_in_seconds` seconds, * but will increase the frequency with the multipliers 1, 6, 12, 30, 60, with the maximum being 60 times the original frequency. * With the default check frequency, this translates to 10, 60, 120, 300, and 600 seconds between checks. * - `LinearBackoffCheckStrategy` will check the task every `LongRunningTaskLogItem::check_frequency_in_seconds` seconds, * but will increase the frequency linearly with each attempt, up to a maximum multiple of 6 times the original frequency. * - `ExponentialBackoffCheckStrategy` will check the task every `LongRunningTaskLogItem::check_frequency_in_seconds` seconds, * but will increase the frequency exponentially with each attempt, up to a maximum of 6 times the original frequency. */ 'default_check_strategy_class' => Spatie\LongRunningTasks\Strategies\DefaultCheckStrategy::class, /* * When a task is not completed in this amount of time, * it will not run again, and marked as `didNotComplete`. */ 'keep_checking_for_in_seconds' => 60 * 5, /* * The model that will be used by default to track * the status of all tasks. */ 'log_model' => Spatie\LongRunningTasks\Models\LongRunningTaskLogItem::class, /* * The job responsible for calling tasks. */ 'task_job' => Spatie\LongRunningTasks\Jobs\RunLongRunningTaskJob::class, ];
此包使用队列在一段时间后再次调用任务。确保您已在Laravel应用中设置了队列。
用法
为了监视外部服务上的长时间运行任务,您应该定义一个任务类。它应该扩展由包提供的Spatie\LongRunningTasks\LongRunningTask
。
它的check
函数应执行您需要的操作并返回一个TaskResult
。当返回TaskResult::StopChecking
时,任务将不再被调用。当返回TaskResult::ContinueChecking
时,它将默认在10秒后被再次调用。
use Spatie\LongRunningTasks\LongRunningTask; use Spatie\LongRunningTasks\Enums\TaskResult; class MyTask extends LongRunningTask { public function check(LongRunningTaskLogItem $logItem): TaskResult { // get some information about this task $meta = $logItem->meta // returns an array // do some work here $allWorkIsDone = /* ... */ // return wheter we should continue the task in a new run return $allWorkIsDone ? TaskResult::StopChecking : TaskResult::ContinueChecking } }
要启动上述任务,您可以调用start
方法。
MyTask::make()->start();
这将在long_running_task_log_items
表中创建一个记录,跟踪此任务的进度。直到返回TaskResult::StopChecking
,MyTask
的check
方法将每10秒被调用一次。
添加元数据
在大多数情况下,您可能希望给任务一些特定的数据,使其可以执行。这可以通过将数组传递给meta
方法来实现。
MyTask::make()->meta($arrayWithMetaData)->start();
或者,您也可以将其传递给start
方法。
MyTask::make()->start($arrayWithMetaData);
给定的数组将可用于传递给您的任务的check
方法的LongRunningTaskLogItem
实例。
class MyTask extends LongRunningTask { public function check(LongRunningTaskLogItem $logItem): TaskResult { // get some information about this task $meta = $logItem->meta // returns an array // rest of method } }
自定义检查间隔
默认情况下,当您的任务的check
方法返回TaskResult::ContinueChecking
时,它将在10秒后再次被调用。您可以通过更改配置文件中long-running-tasks
的default_check_frequency_in_seconds
键值来自定义该时间段。
您还可以在任务本身指定检查间隔。
class MyTask extends LongRunningTask { public int $checkFrequencyInSeconds = 20; }
要指定特定任务实例的检查间隔,您可以使用checkInterval
方法。
MyTask::make() ->checkFrequencyInSeconds(30) ->start();
自定义检查策略
默认情况下,此包使用DefaultCheckStrategy
来确定检查频率(以秒为单位),它始终返回check_frequency_in_seconds
属性的值。
您可以通过更改配置文件 long-running-tasks
中的 default_check_strategy_class
键的值来自定义应使用的策略。
您还可以在任务本身指定策略。
use Spatie\LongRunningTasks\Strategies\StandardBackoffCheckStrategy; class MyTask extends LongRunningTask { public string $checkStrategy = StandardBackoffCheckStrategy::class; }
要在特定任务实例上指定检查策略,您可以使用 checkStrategy
方法。
MyTask::make() ->checkStrategy(StandardBackoffCheckStrategy::class) ->start();
使用不同的队列
此包使用队列在一段时间后再次调用任务。默认情况下,它将使用 default
队列。您可以通过更改配置文件 long-running-tasks
中的 queue
键来自定义应使用的队列。
您还可以在任务本身指定队列。
class MyTask extends LongRunningTask { public string $queue = 'my-custom-queue'; }
要在特定任务实例上指定队列,您可以使用 onQueue
方法。
MyTask::make() ->queue('my-custom-queue') ->start();
跟踪任务状态
对于每个启动的任务,将在 long_running_task_log_items
表中创建一条记录。此记录将跟踪任务的状态。
LongRunningTaskLogItem
模型具有以下 status
属性
pending
:任务尚未开始。running
:任务正在运行。completed
:任务已完成。failed
:任务失败。可能抛出了未处理的异常。didNotComplete
:任务在给定的时间内未完成。
该表还包含以下属性
task
:任务的完全限定类名。queue
:任务正在运行的队列。check_frequency_in_seconds
:在再次检查任务之前应经过的秒数。meta
:传递给任务的元数据数组。last_check_started_at
:任务启动的日期和时间。last_check_ended_at
:任务结束的日期和时间。stop_checking_at
:任务应停止检查的日期和时间。lastest_exception
:包含最新抛出的异常的数组,键为message
和trace
。run_count
:任务运行次数。attempt
:任务在失败后尝试的次数。created_at
:记录创建的日期和时间。
防止无限期运行的任务
该包有一种防止任务无限期运行的方法。
当任务在 long-running-tasks
配置文件中 keep_checking_for_in_seconds
键指定的期间内未完成时,它将不再运行,并标记为 didNotComplete
。
您可以在特定任务上自定义此时间段。
class MyTask extends LongRunningTask { public int $keepCheckingForInSeconds = 60 * 10; }
您还可以在特定任务实例上指定时间段。
MyTask::make() ->keepCheckingForInSeconds(60 * 10) ->start();
处理异常
当任务中的 check
方法抛出异常时,它将被捕获并存储在 latest_exception
属性中。
您可以在任务上定义 onFailure
方法。当在 check
方法中抛出异常时,将调用此方法。
use Spatie\LongRunningTasks\LongRunningTask; use Spatie\LongRunningTasks\Enums\TaskResult; class MyTask extends LongRunningTask { public function check(LongRunningTaskLogItem $logItem): TaskResult { throw new Exception('Something went wrong'); } public function onFail(LongRunningTaskLogItem $logItem, Exception $exception): ?TaskResult { // handle the exception } }
您可以让 onFail
方法返回一个 TaskResult
。当它返回 TaskResult::ContinueChecking
时,任务将再次被调用。如果不返回任何内容,则任务将不再被调用。
事件
使用自己的模型
如果您需要在 LongRunningTaskLogItem
模型上添加额外的字段或功能,您可以创建自己的模型,该模型扩展了此包提供的 LongRunningTaskLogItem
模型。
namespace App\Models; use Spatie\LongRunningTasks\Models\LongRunningTaskLogItem as BaseLongRunningTaskLogItem; class LongRunningTaskLogItem extends BaseLongRunningTaskLogItem { // your custom functionality }
然后应更新 long-running-tasks
配置文件中的 log_model
键,以指向您的自定义模型。
// in config/long-running-tasks.php return [ // ... 'log_model' => App\Models\LongRunningTaskLogItem::class, ];
为了填充您模型额外的自定义字段,您可以使用 creating
和 updating
事件。您可以使用 meta
属性将数据传递给模型。
namespace App\Models; use Spatie\LongRunningTasks\Models\LongRunningTaskLogItem as BaseLongRunningTaskLogItem; class LongRunningTaskLogItem extends BaseLongRunningTaskLogItem { protected static function booted() { static::creating(function ($logItem) { $customValue = $logItem->meta['some_key']; // optionally, you could unset the custom value from the meta array unset($logItem->meta['some_key']); $logItem->custom_field = $customValue; }); } }
使用您自己的作业
默认情况下,该包使用 RunLongRunningTaskJob
作业来调用任务。如果您想使用自己的作业,您可以创建一个扩展此包提供的 RunLongRunningTaskJob
作业的作业。
namespace App\Jobs; use Spatie\LongRunningTasks\Jobs\RunLongRunningTaskJob as BaseRunLongRunningTaskJob; class RunLongRunningTaskJob extends BaseRunLongRunningTaskJob { // your custom functionality }
然后,您应更新 long-running-tasks
配置文件中的 task_job
键,使其指向您的自定义作业。
// in config/long-running-tasks.php return [ // ... 'task_job' => App\Jobs\RunLongRunningTaskJob::class, ];
事件
该包会触发您可以在应用程序中监听的事件,以便在特定事件发生时执行附加操作。
所有这些事件都具有一个包含 LongRunningTaskLogItem
模型的属性 $longRunningTaskLogItem
。
Spatie\LongRunningTasks\Events\TaskRunStarting
当任务即将运行时,将触发此事件。
Spatie\LongRunningTasks\Events\TaskRunEnded
当任务结束时,将触发此事件。
Spatie\LongRunningTasks\Events\TaskCompleted
当任务完成时,将触发此事件。
Spatie\LongRunningTasks\Events\TaskRunFailed
当任务失败时,将触发此事件。
Spatie\LongRunningTasks\Events\TaskRunDidNotComplete
当任务在给定时间内未完成时,将触发此事件。
Spatie\LongRunningTasks\Events\DispatchingNewRunEvent
当即将分发任务的新运行时,将触发此事件。
测试
composer test
变更日志
有关最近更改的更多信息,请参阅变更日志。
贡献
有关详细信息,请参阅贡献指南。
安全漏洞
有关如何报告安全漏洞的详细信息,请参阅我们的安全策略。
鸣谢
许可
MIT 许可证(MIT)。有关更多信息,请参阅许可文件。