Return data from Laravel Jobs

Bushikot picture Bushikot · May 19, 2016 · Viewed 12.3k times · Source

I am developing API on Laravel for mobile application.

Methods will make requests to other API's, combine and filter data, changing it's structure etc.

One of the requirements to app is to respond no more than 30 seconds, or not respond at all. So, I have to repeat requests as much as I have time. I trying to realize that with Laravel Queues, and currently have something like that in my Job class:

private $apiActionName;

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

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

And this action code in controller:

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

Yes, I know it is bad idea to return value from job, but expect that it's possible. However $this->dispatch() returns only queued job ID, not result of handle method.

TL;DR: How can I return data from queued Job, without saving it anywhere, and even if it have more than one tries in the queue? Maybe somebody know other ways if Jobs are not suitable for this. Any advice will be appreciated.

Thanks in advance!

Answer

Denis Mysenko picture Denis Mysenko · May 20, 2016

You are returning data in your Job class, but assigning $data to a dispatcher - note that dispatch() method is not a part of your Job class.

You could try something like this, assuming that your jobs run synchronously:

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

And then in your controller:

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

Obviously, this won't work once you move to async mode and queues - response won't be there yet by the time you call getResponse(). But that's the whole purpose of async jobs :)