【问题标题】:Return data from Laravel Jobs从 Laravel Jobs 返回数据
【发布时间】:2016-09-16 22:50:32
【问题描述】:

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

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

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

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,而不是 handle 方法的结果。

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

提前致谢!

【问题讨论】:

标签: php laravel api-design task-queue


【解决方案1】:

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

然后在你的控制器中:

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

显然,一旦您切换到异步模式和队列,这将不起作用 - 到您调用 getResponse() 时,响应还不会出现。但这就是异步作业的全部目的:)

【讨论】:

  • 感谢您的回复!我需要在异步模式下运行它的问题,因为否则 Job 在失败的情况下不会重复。我尝试使用 getter 遵循您的建议,然后在循环中检查 getResponse(),但它不起作用(重试有其他 id?)。顺便说一句,可以从非排队作业中返回值,而无需 getter: $data = $this->dispatchNow($job);
  • 将,在异步模式下,您将无法根据定义返回值 - 因为它将在一段时间后以异步模式运行。因此,您的工作必须将结果保存在某个地方,并且客户端/控制器必须通过轮询或实时流(websockets、pubsub)再次请求它。无论哪种方式,您都不能只从异步作业返回结果
  • Laravel 5.8 试过这个,没用。您需要使用 $this->dispatchNow 而不是 $this->dispatch 从 $job->getResponse(); 获取更新的值;
  • 如果 Job 有一个 Rate Limiter 并且如果达到这个限制会产生一个 $this->relase($seconds = 10)
【解决方案2】:

Laravel 7 及之前的版本

如果您使用的是sync 以外的队列驱动程序并且您使用的是 Laravel 版本 7 或更早版本,您可以使用 @Denis Mysenko 方法和方法 dispatchNow 来获取来自 Job 对象的数据表明它运行良好。

Laravel 8

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

解决方案

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

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

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

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

【讨论】:

  • 它的作品。谢谢... +1
【解决方案3】:

如果你想从 Laravel 作业中返回数据,你需要在 Providers/AppServiceProvider.php 里面写一些 Queue 方法 boot 方法(Laravel 7.x / 8)

public function boot()
{
   Queue::before(function ( JobProcessing $event ) {
      Log::info('Job ready: ' . $event->job->resolveName());
      Log::info('Job started: ' . $event->job->resolveName());
   });
    
   Queue::after(function ( JobProcessed $event ) {
      Log::notice('Job done: ' . $event->job->resolveName());
      Log::notice('Job payload: ' . print_r($event->job->payload(), true));
   });
    
   Queue::failing(function ( JobFailed $event ) {
       Log::error('Job failed: ' . 
                  $event->job->resolveName() . 
                 '(' . $event->exception->getMessage() . ')'
                 );
   });
}

【讨论】:

    猜你喜欢
    • 2020-05-30
    • 2019-08-14
    • 2013-06-15
    • 2020-05-04
    • 2018-04-07
    • 1970-01-01
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多