从拉拉维尔作业返回数据

2022-08-30 23:32:46

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

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

对应用程序的要求之一是响应不超过30秒,或者根本不响应。所以,我必须尽可能多地重复请求。我试图通过Laravel Queues意识到这一点,目前在我的工作课上有类似的东西:

private $apiActionName;

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

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

控制器中的此操作代码:

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

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

TL;DR:如何从排队的作业返回数据,而不将其保存在任何位置,即使它在队列中有多个尝试?也许有人知道其他方式,如果乔布斯不适合这样做。任何建议将不胜感激。

提前致谢!


答案 1

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

您可以尝试类似这样的操作,假设您的作业同步运行:

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;
}

然后在控制器中:

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

显然,一旦您移动到异步模式和队列,这将不起作用 - 当您调用getResponse()时,响应将不存在。但这就是异步作业的全部目的:)


答案 2

拉拉维尔 7 及更早版本

如果您使用的是队列驱动程序以外的其他队列驱动程序,并且使用的是 Laravel 版本 7 或更早版本,则可以使用 @Denis Mysenko 方法和方法从 Job 对象中获取数据,该方法运行良好。syncdispatchNow

拉拉维尔 8

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

溶液

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

如果作业不使用该特征,则句柄方法的返回将在使用时可供请求使用 - 请参阅此答案QueueabledispatchSync

<?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;
    }
}

在客户端脚本中

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

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


推荐