spatie/laravel-long-running-tasks

处理Laravel应用中的长时间运行的任务

0.0.4 2024-09-15 19:49 UTC

This package is auto-updated.

Last update: 2024-09-15 19:49:50 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

一些服务,如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::StopCheckingMyTaskcheck方法将每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::StopCheckingMyTaskcheck方法将每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-tasksdefault_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:包含最新抛出的异常的数组,键为 messagetrace
  • 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,
];

为了填充您模型额外的自定义字段,您可以使用 creatingupdating 事件。您可以使用 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)。有关更多信息,请参阅许可文件