New Zend Server Job Queue Library

This will probably be one of the last posts I do on the Zend Server Job Queue functionality.  From this point on they will probably be less frequent, though I’m sure several posts will allude to it.  The reason I’m going to put it on the back burner is because I have written a library which is now available on GitHub.  What it does is encapsulate all of the functionality that I think needs to be there to be able to implement asynchronous functionality.  I’ve been working on it off and on for at least a year, trying out different things.

As I was working through it there were a few things that I wanted to accomplish.

  1. It needed to be easy to use
  2. It needed to be installed in a few minutes
  3. It needed to hide a lot of the implementation details.

That said, I think that I’ve been able to accomplish a lot of that.  With that, let’s take a quick run through.

Creating the job class

There is only one class that you need to know.  It is called JobAbstract and it is in the com\zend\jobqueue namespace.  Yes, the library requires PHP 5.3, though it works with PHP 5.2 code as I’ve already built a Magento extension for it.  In order to implement the job queue, on the code side, you simply create objects that represent your tasks, extending the JobAbstract class and implementing the job() method.  So if you had a job that you wanted to have send out an email it would look something like this.

namespace org\eschrade\job;
use com\zend\jobqueue\JobAbstract;
 
class SendEmail extends JobAbstract
{
    private $to;
    private $message;
 
    public function __construct($to, $message)
    {
        $this->to = $to;
        $this->message = $message;
    }
 
    public function job()
    {
        $mail = new \Zend_Mail();
        $mail->addTo($this->to);
        $mail->setBodyHtml($this->message);
        $mail->send();
    }
}

Then when you want to execute this job you simply call the job

$job = new org\eschrade\job\SendEmail('you@yourdomain', 'Welcome here!');
$response = $job->execute();

This will invoke the Manager object (which we’ll look at in a bit) which will then send the request to the specified job queue server, or to a load balancer.  The response is important if you want to get the results of the job.  If the request is serviced through a load balancer you don’t necessarily have any knowledge about where your job is going to execute.  Thus, if you want to get the result of the job you need to know how to get the job.  That information is stored in the result.  It’s a very simple, serializable object that is intended for persistent storage, such as a session or database.

Setting up the Manager

The manager is mostly self-contained.  The only thing it requires is that you provide a URL for the backend job queue end point.  The end point needs to only contain the following code.

1
2
3
4
use com\zend\jobqueue\Manager;
 
$mgr = new Manager();
$mgr->invoke();

Now, your application may require more at the end point to bootstrap it, but that’s all it needs to interact with your front end servers.

On the front end you need to tell the Manager what the URL is to connect to a job queue server.  As I said before, it can be an individual server or a load balancer in front of a hundred job queue servers, it really doesn’t matter, except that you can scale quite easily without any configuration changes.  To set the URL simply tell the Manager what the URL is.

1
Manager::setDefaultUrl('http://lb/queue.php');

And that’s pretty much it.

Communicating with the backend

Once you’ve sent the job off to the backend to execute you might want to interact with the results of the job.  Once the job object has finished executing, the Manager will serialize the job so you can get the results.  This would typically be done via getters and setters.  I have a good example of this in the library code on GitHub.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class GetRemoteLinks extends JobAbstract
{
 
    private $url;
    private $links = array();
 
    public function __construct($url)
    {
        $this->url = $url;
    }
 
    public function getLinks()
    {
        return $this->links;
    }
 
    public function getUrl()
    {
        return $this->url;
    }
 
    public function job()
    {
 
        $http = new \Zend_Http_Client($this->url);
        $response = $http->request();
        $selector = new \Zend_Dom_Query();
        $selector->setDocumentHtml(
                $response->getBody()
         );
        foreach ($selector->query('a') as $result) {
            if ($result->getAttribute('href')) {
                $this->links[] = $result->getAttribute('href');
            }
        }
    }
}

To execute this job you would call

1
2
$job = new GetRemoteLinks('http://www.eschrade.com/');
$result = $job->execute();

Then later on

1
2
3
4
5
6
$mgr = new Manager();
if (($job = $mgr->getCompletedJob($result)) !== null) {
    foreach ($job->getLinks() as $link) {
        echo $link . '<br />';
    }
}

 

That’s pretty much it.

6 comments
aravindkumarit
aravindkumarit

There is not ZendJobQueue.php inside your code and it is not runnign???

Warning: include_once(ZendJobQueue.php) [function.include-once]: failed to open stream: No such file or directory in G:\wamp\www\JZ\library\Zend\Loader.php on line 146

aravindkumarit
aravindkumarit

Hi when I give the url I am receiving the following error:


Notice: Undefined property: org\eschrade\job\GetRemoteLinks::$queueBinding in G:\wamp\www\JZ\library\com\zend\jobqueue\JobAbstract.php on line 62

in bootstrap I set

set_include_path('G:/wamp/www/JZ/library/'); 


aravindkumarit
aravindkumarit

Hi I am getting the following error when try to execute your code from git... Warning: require_once(Zend/Loader/Autoloader.php) [function.require-once]: failed to open stream: No such file or directory in G:\wamp\www\JZ\public\bootstrap.php on line 

Ken Swift
Ken Swift

Maybe I am missing something but how can it be "implement asynchronous" if You have to wait for results of the job? If script have to wait for results I could as well implement this job in normal way without zend_que. Or maybe it is that I don't have to wait for results and then it is asynchronous ?

admin
admin

Once you call execute() you can forget about it, unless you want the results after the job has completed. Then you call getCompletedJob() to get the completed job object after it is done executing. Because the response of the execute() method, which is used to retrieve the job from the manager, is serializable you can do that on a subsequent request by storing the response in a session and checking during the execution of a later request.

aravindkumarit
aravindkumarit

@adminHi when I give the url I am receiving the following error:


Notice: Undefined property: org\eschrade\job\GetRemoteLinks::$queueBinding in G:\wamp\www\JZ\library\com\zend\jobqueue\JobAbstract.php on line 62

in bootstrap I set

set_include_path('G:/wamp/www/JZ/library/'); 

Trackbacks

  1. […] his newly updated blog today (changed to WordPress) Kevin Schroeder has a new post looking at a new queuing library available for Zend Server’s Job Queue including an example of its use. This will probably […]

  2. abcphp.com says:

    New Zend Server Job Queue Library…

    This will probably be one of the last posts I do on the Zend Server Job Queue functionality.  From this point on they will probably be less frequent, though I’m sure several posts will allude to it.  The reason I’m going to put it on the back burner …

  3. […] New Zend Server Job Queue Library […]

Post Navigation

Web Analytics