从Laravel Jobs返回数据

Bus*_*kot 5 php api-design task-queue laravel

我正在为Laravel移动应用程序开发API.

方法将向其他API发出请求,组合和过滤数据,更改其结构等.

应用程序的要求之一是响应时间不超过30秒,或者根本不响应.所以,我必须尽可能多地重复请求.我试图通过Laravel Queues实现这一点,并且目前在我的Job类中有类似的东西:

private $apiActionName;

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

public function handle(SomeService $someService)
{
    return $someService->{$this->apiActionName}();
}
Run Code Online (Sandbox Code Playgroud)

而这个动作代码在控制器中:

public function someAction()
{ 
    $data = $this->dispatch(new MyJob($apiActionName));
    return response()->json($data);
}
Run Code Online (Sandbox Code Playgroud)

是的,我知道从工作中返回价值是不错的主意,但我希望这是可能的.但是$ this-> dispatch()只返回排队的作业ID,而不是handle方法的结果.

TL; DR:如何从排队的作业中返回数据,而不将其保存在任何地方,即使它在队列中有多次尝试?如果乔布斯不适合这个,也许有人知道其他方法.任何建议将被认真考虑.

提前致谢!

Wes*_*ves 8

Laravel 7 及之前版本

如果您使用的队列驱动程序不是syncLaravel 版本 7 或更早版本,则可以使用@Denis MysenkodispatchNow方法和从 Job 对象获取数据的方法,该方法运行良好。

拉拉维尔 8

然而,在 Laravel 版本 8 中,该dispatchNow方法已被弃用,取而代之的是dispatchSync. 但是,这个新方法创建了作业的新实例,您将无法从客户端脚本访问这个新实例或其任何属性。

解决方案

但是,根据rodrigo.pedra 的回答,如果您从作业中删除该Illuminate\Bus\Queueable特征,您将能够从作业handle方法返回数据并在客户端脚本中使用此结果。

如果作业不使用该Queueable特征,则在使用时,handle 方法的返回将可用于请求dispatchSync- 请参阅此答案

<?php
// ...

class MyJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, SerializesModels;
    // use Queueable
    /* do not use ^^ this trait */

    private $apiActionName;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($apiActionName) 
    {
        $this->apiActionName = $apiActionName;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle() 
    {
        // operations generating result
        $result = $someService->{$this->apiActionName}();
 
        return $result;
    }
}

Run Code Online (Sandbox Code Playgroud)

在客户端脚本中

public function someAction()
{ 
    $result = MyJob::dispatchSync($apiActionName);
    return response()->json($result);
}

Run Code Online (Sandbox Code Playgroud)

注意:该dispatchSync方法与使用相同dispatch()->onQueue('sync'),这将强制队列系统使用sync驱动程序,立即运行作业。


Den*_*nko 7

您正在Job类中返回数据,但是将$ data分配给调度程序 - 请注意,dispatch()方法不是Job类的一部分.

假设您的作业同步运行,您可以尝试这样的事情:

private $apiActionName;
private $response;

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

public function handle(SomeService $someService)
{
    $this->response = $someService->{$this->apiActionName}();
}

public function getResponse()
{
    return $this->response;
}
Run Code Online (Sandbox Code Playgroud)

然后在你的控制器中:

public function someAction()
{ 
    $job = new MyJob($apiActionName);
    $data = $this->dispatch($job);
    return response()->json($job->getResponse());
}
Run Code Online (Sandbox Code Playgroud)

显然,一旦你转向异步模式和队列,这将无法工作 - 当你调用getResponse()时,响应将不会出现.但那是异步工作的全部目的:)

  • 在异步模式下,您将无法按定义返回值 - 因为它将在异步模式下运行一段时间.因此,您的工作必须将结果保存在某处,并且客户端/控制器必须通过轮询或实时流(websockets,pubsub)再次请求它.无论哪种方式,您都不能只返回异步作业的结果 (3认同)
  • 用 **Laravel 5.8** 尝试过,没有成功。您需要使用 `$this-&gt;dispatchNow` 而不是 `$this-&gt;dispatch` 来从 $job-&gt;getResponse(); 获取更新后的值; (2认同)