tochka-developers/queue-promises

此软件包最新版本(v1.4.0)没有提供许可信息。

Laravel队列作业的Promise

安装量: 11,962

依赖项: 0

建议者: 0

安全: 0

星标: 19

关注者: 8

分支: 2

开放问题: 1

类型:软件包

v1.4.0 2024-07-15 09:05 UTC

README

Packagist Packagist build Psalm coverage Psalm level Coverage Status

该模块允许链式调用Laravel作业。Promise将在所有链式作业完成后执行(无论成功或失败)。Promise可以访问作业结果。

安装

  • 使用composer安装此软件包
composer require tochka-developers/queue-promises
  • (Laravel 5.4)在config/app.php中注册ServiceProvider
'providers' => [
    ...
    \Tochka\Queue\Promises\QueuePromisesServiceProvider::class
    ...
]
  • 发布配置
php artisan vendor:publish --provider="Tochka\Queue\Promises\QueuePromisesServiceProvider"
  • config/promises.php中配置Promise存储。

  • 创建Promise存储表

php artisan migrate

用法

创建Promise

所有Promise都从Tochka\Queue\Promises\Jobs\Promise派生。您可以使用artisan创建一个模板Promise

php artisan make:promise TestPromise

类详情

Promise类相当简单,因为它只需要两个方法:successerrors。当所有链式作业成功完成时,由提供者调用success。当任何作业失败时,调用errors

<?php

namespace App\Promises;

use Tochka\Queue\Promises\Jobs\Promise;

class TestPromise extends Promise
{
    /**
     * Instance initialization
     *
     * @return void
     */
    public function __construct()
    {
        // Jobs chaining may be done here
    }
    
    /**
     * This will be called after all jobs of the promise have finished execution, but before success or errors.
     * If this method returns false, success and errors won't be called. 
     *
     * @return bool
     */
    public function before(): bool
    {
        // ...
        return true;
    }

    /**
     * This will be called if all the jobs have completed successfully.
     *
     * @return bool
     */
    public function success(): bool
    {
        // ...
        return true;
    }

    /**
     * This will be called if one or more jobs have failed.
     *
     * @return bool
     */
    public function errors(): bool
    {
        // ...
        return true;
    }
    
    /**
     * This will be called if the promise timed out.
     *
     * @return bool
     */
    public function timeout(): bool
    {
        // ...
        return true;
    }
    
    /**
     * This will be called after the execution of success or errors
     *
     * @return bool
     */
    public function after()
    {
        // ...
        return true;
    }
}

上述任何方法都可能没有实现。如果方法缺失,则假定它执行无操作并返回true

链初始化

为了使作业可以附加到Promise,它们必须实现Tochka\Queue\Promises\Contracts\MayPromised接口。最常见的使用案例收集在Tochka\Queue\Promises\Jobs\Promised特质中。您可以将这些特质简单地附加到您的类中,如下所示

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Tochka\Queue\Promises\Contracts\MayPromised;
use Tochka\Queue\Promises\Jobs\Promised;

class SomeJob implements ShouldQueue, MayPromised
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Promised;

    public $text;

    public function __construct($text)
    {
        $this->text = $text;
    }

    public function handle()
    {
        // some actions
    }
}

通过将任何数量的作业添加到Promise来构建链

$promise = new TestPromise();

$promise->add(new SomeJob('job 1'))
    ->add(new SomeJob('job 2'))
    ->add(new SomeJob('job 3'))
    ->add(new SomeJob('job 4'));

之后,Promise可以以两种模式之一运行

$promise->runSync();    // Run the promise synchronously 
$promise->runAsync();   // Run the promise asynchronously
  • 在同步模式下,所有链式作业将按顺序依次运行,直到其中之一失败或全部成功完成。之后,将执行Promise的successerrors
  • 在异步模式下,所有作业将立即入队,Promise将等待它们完成。

可以通过方法调用精细配置终止条件

$promise->setPromiseFinishConditions(
    true, // The promise must execute when a job completes successfully for the first time.  
    true  // The promise must execute when a job fails for the first time.
);

为了方便,runSyncrunAsync也可以接受相同的参数。

等待事件

有时需要在一个事件被分发后执行Promise,而不仅仅是当一定数量的作业完成。等待事件是通过Tochka\Queue\Promises\Jobs\WaitEvent作业完成的

$promise = new TestPromise();

$promise->add(new WaitEvent(SomeEvent1::class, 100))
        ->add(new WaitEvent(SomeEvent2::class, 100));
    
$promise->run()

WaitEvent的构造函数接收一个等待的事件的类和一个唯一标识符(未指定类型)。如果没有提供标识符,则WaitEvent将等待期望类的任何事件。如果给构造函数提供了标识符,则WaitEvent将只在具有此标识符的事件被分发时完成。为了使其正常工作,该事件必须实现Tochka\Queue\Promises\Contracts\PromisedEvent接口

class SomeEvent implements PromisedEvent
{
    public $id;
    public $data;

    public function __construct($id, string $data)
    {
        $this->id = $id;
        $this->data = $data;
    }

    /**
     * Get the event id
     * @return string
     */
    public function getUniqueId()
    {
        return $this->id;
    }
}

getUniqueId必须返回一个标识符或null,如果没有标识符存在。

请注意,如果等待一个不实现该接口的类,则WaitEvent永远不会完成。

Promise超时

有时,如果某些链式作业尚未完成,则在超时事件后执行Promise可能很有用。这是通过特殊的延迟检查作业实现的。

您必须配置超时子系统

  • 将配置参数timeout_queue设置为包含检查作业将被发布的队列的名称。默认情况下,检查作业被发布到default队列。
  • 为超时队列运行监听器或将其添加到现有监听器的队列列表中。

之后,承诺可能被设置为过期。设置超时的两种方法可行

  • setTimeout($timeout) — 承诺将在给定时间(以秒为单位)执行,或在所有工作完成之后(以先到者为准)。
  • setExpiredAt(Carbon $expired_at) — 承诺将在给定的戳记(更准确或更不准确)执行,或在所有工作完成之后(以先到者为准)。

如果承诺超时,则调用timeout方法(如果已定义)。

处理结果

getResults方法返回所有链式作业的结果

public function before(): bool
{
    $results = $this->getResults();
    foreach ($results as $result) {
        $status = $result->getJobStatus(); // This returns the job execution status
    }
}

作业结果以实现Tochka\Queue\Promises\Contracts\MayPromised的类返回。

依赖注入

获取作业结果的另一种方法是通用方法beforesuccesserrorstimeoutafter的依赖注入版本。

public function errors(SomeJob1 $job1, SomeJob2 $job2): bool
{
    echo $job1->getJobStatus();
    echo $job2->getJobStatus();
}

DI的工作方式如下

  • 如果参数实现了Tochka\Queue\Promises\Contracts\MayPromised的类型,则相应的结果将被注入到该参数中;
  • 如果参数实现了Tochka\Queue\Promises\Contracts\PromisedEvent(这在承诺等待事件时很有用),则事件本身将作为该参数传递;
  • 如果存在多个所需类的结果,则只有第一个将被绑定;
  • 如果有多个相同类的参数(例如,如果承诺等待同一类的多个作业),则结果的顺序对应于链中作业的顺序
$promise->add(new SomeJob('job 1'))
        ->add(new SomeJob('job 2'))
        ->add(new SomeJob('job 3'))
        ->add(new SomeJob('job 4'));
    
//...

public function errors(SomeJob $job1, SomeJob $job2, SomeJob $job3, SomeJob $job4): bool
{
    echo $job1->text; // job 1
    echo $job2->text; // job 2
    echo $job3->text; // job 3
    echo $job4->text; // job 4
}

请注意,如果承诺异步运行,则无法保证作业执行的顺序。这可能会产生不希望的结果

public function errors(SomeJob $job1, SomeJob $job2, SomeJob $job3, SomeJob $job4): bool
{
    echo $job1->text; // job 3
    echo $job2->text; // job 1
    echo $job3->text; // job 2
    echo $job4->text; // job 4
}
  • 如果没有适合参数的结果,则传递null
  • 如果参数类型没有实现Tochka\Queue\Promises\Contracts\MayPromised,则将通过Laravel DI构建传递给它的值(类似于调用app()并传递类名时的结果)。

Tochka\Queue\Promises\Contracts\MayPromised接口声明以下方法

/**
 * Get the job execution status 
 * Returns either MayPromised::JOB_STATUS_SUCCESS or MayPromised::JOB_STATUS_ERROR
 * @return string
 */
public function getJobStatus(): string;

/**
 * Get the job execution errors
 * Returns an array ['code' => ..., 'message' => ...]
 * @return array
 */
public function getJobErrors(): array;