morphatic
morphatic

Reputation: 7975

Is there a way to pass a callback as data parameter to Laravel 4.2 Queue::push()

I've got some time-consuming code that processes the results of a series of HTTP requests that I'd like to run in the background. I'm using a Redis store for managing the queue. Here's what I've tried:

Queue::push( 'FetchUrls', [
    'urls'     => [ 'http://one.com', 'http://two.com', 'http://three.com' ],
    'complete' => function( $response ) { /* process data returned by URL here */ },
    'error'    => function( $error    ) { /* process HTTP errors here */ },
]);

What shows up in the Redis queue store is a JSON serialization of the $data parameter:

{
    "job": "FetchUrls",
    "data": { 
        "urls": [
            "http:\/\/one.com",
            "http:\/\/two.com",
            "http:\/\/three.com"
        ],
        "complete": [],
        "error": []
    },
    "id": "aAlkNM0ySLXcczlLYho19TlWYs9hStzl",
    "attempts": 1
}

As you can see, the callbacks just show up as empty arrays in the queue store. I've never used the Queue class before and so I may be approaching this problem in the wrong way. I'm looking for a suggestion for the best way to work around this. Thanks!

Upvotes: 1

Views: 1135

Answers (2)

DefiniteIntegral
DefiniteIntegral

Reputation: 579

You could pass function names and invoke them with something like call_user_func().

Queue::push('FetchUrls', [
    'urls'     => ['http://one.com', 'http://two.com', 'http://three.com'],
    'complete' => ['ResponseHandler', 'fetchComplete'],
    'error'    => ['ResponseHandler', 'fetchError'],
]);

class FetchUrls
{
    public function fire($job, $data)
    {
        list($urls, $complete, $error) = $data;

        foreach ($urls as $url) {
            if ($response = $this->fetch($url)) {
                $job->delete();
                call_user_func($complete, $response);
            } else {
                $job->release();
                call_user_func($error, $this->getError());
            }
        }
    }

    private function fetch($url)
    {
        // ...
    }

    private function getError()
    {
        // ...
    }
}

class ResponseHandler
{
    public static function fetchComplete($response)
    {
        // ...
    }

    public static function fetchError($error)
    {
        // ...
    }
}

There's a not-class-based version of this approach, but this is relatively clean.

call_user_func() with ['ResponseHandler', 'fetchComplete'] as the first parameter will invoke ResponseHandler::fetchComplete().

Upvotes: 2

Andreyco
Andreyco

Reputation: 22872

To be safe, you should push arrays only (since problems with serializations).
To answer your question - there is no workaround, you should rethink the logic.

Upvotes: 3

Related Questions