Zend Framework: Zend_Queue Component Proposal
| Proposed Component Name | Zend_Queue |
|---|---|
| Developer Notes | http://framework.zend.com/wiki/display/ZFDEV/Zend_Queue |
| Proposers | Justin Plock Daniel Lo |
| Revision | 1.0 - 3 March 2008: Initial revision 1.1 - 27 February 2009: Updated proposal 1.2 - 9 April 2009: Code complete (wiki revision: 14) |
Table of Contents
1. Overview
Zend_Queue is a standardized interface for dealing with a variety of queuing systems. Proposed systems include: simple array access, Zend_Cache, Zend Platform Job Queue, Amazon's Simple Queue Service (SQS). It should support creating queues, determining the number of messages in a queue, retrieving messages from a queue (all or specific number), submitting messages to a queue, and removing queues.
2. References
- Amazon Simple Queue Service (SQS)
- Amazon SQS Getting Started Guide
- Amazon SQS Developer Guide
- Visibility Timeout
- Zend Platform Job Queue
- FIFO
3. Component Requirements, Constraints, and Acceptance Criteria
- This component should support a variety of backend services (Zend_Db, Zend Platform Job Queue, Arrays, MemcacheQ, etc).
- This component will support the full Amazon SQS API
- This component will support creating new queues
- This component will support deleting existing queues
- This component will support counting the number of a messages in a queue
- This component will support retrieving messages from a queue (all or a specific count)
- This component will support submitting messages to a queue
4. Dependencies on Other Framework Components
- Zend_Http_Client
- Zend_Log
- Zend_Db
5. Theory of Operation
Zend_Queue will be a factory class for to create a specific queue interface class. Simple "send" and "receive" methods will be employed by each backend to interact with queues. "create", "getCount" and "delete" methods will be used to manage queues.
6. Milestones / Tasks
- Milestone 1: [DONE] Design notes will be published here
- Milestone 2: [DONE] Working prototype checked into the incubator supporting use cases
- Milestone 3: [DONE] Unit tests exist, work, and are checked into SVN.
- Milestone 4: [DONE] Initial documentation exists.
7. Class Index
- Zend_Queue_Exception
- Zend_Queue (factory class)
- Zend_Queue_Message
- Zend_Queue_Message_Iterator
- Zend_Queue_Adapter_Abstract
- Zend_Queue_Adapter_Exception
- Zend_Queue_Adapter_Amazon (interface for Amazon SQS)
- Zend_Queue_Adapter_Db (interface for Zend_Db)
- Zend_Queue_Adapter_Memcacheq (interface for MemcacheQ)
- Zend_Queue_Adapter_Null
- Zend_Queue_Adapter_Stomp
- Zend_Queue_Adapter_Stomp_IO
- Zend_Queue_Adapter_Array
8. Use Cases
| UC-01 |
|---|
9. Class Skeletons
| Zend Comments The Zend Framework team approves this proposal for immediate development in the
|
Hi,
I'm very interested in your proposal, since we implemented a basic Queue Service ourselves using a DB as a backend. If we unify the development it would be better. We may need a STOMP or AMQP Backend for our next iteration, we would provide that.
I think it is very important that all backend adapters be concurrency-safe. E.g. if 5 clients are requesting the next message from the queue, the Adapter needs to make sure each message is returned only once. We do this by
$sQuery = 'UPDATE '.Hitmeister_Db_Tables::get('system_messages').
' SET '.$this->aDbFields['status_message'].' = \'READ\''.
' WHERE '.$this->aDbFields['id_message'].' = '.$oMessage->id_message.
' AND '.$this->aDbFields['status_message'].' = \'NEW\'';
//-- execute the statement
$oStatement = $this->oDBH->prepare($sQuery);
$oStatement->execute();
if(!$oStatement)
{ throw new Hits_Abstract_Service_Perform_Exception('@client: could not change status of message - id_message: '.$oMessage->id_message); }
//-- check if was not able to update
if ($oStatement->rowCount() == 0)
{ try { return System_Messages::GetNextMessage($this->aServiceParams, $this->aServiceParams['output_fields'], $this->aApiParams); }
catch (Exception $e)
{ throw $e; }
}
This is more efficient than locking the table, at least in our use scenario.
One more thing we found: if you reduce the strict FIFO requirement to "more or less FIFO" you can get more performance out of the components. Perhaps make it variable in the next version?
What needs to be done for this proposal to move ahead. It seems to have been very little movement since august.
The code is pretty much done. As with my S3 proposal, this needs unit tests and documentation. I committed a MemcacheQ adapter this morning. Any help would be appreciated as I'm not to sure how to write documentation for the manual.
I think a component named that unspecific should be as unspecific as it's name is. How would you integrate Apache ActiveMQ or Rabbit MQ? Message Queues are Queues as well.
I'm currently working on a library for the Stomp protocol using various Message Queues which I designed with maximum flexibility in mind. You might want to take a look at how many parts are exchangeable in such a system (and that's Stomp specific!):
http://github.com/felixjendrusch/stomp/tree/master/
I'm still writing the documentation because I had to get it working as fast as possible for a customer, sorry for that. Some components are not finished yet but it's working.
I started creating a queue using Zend_Queue_Db and have come across an issue. It appears that the send and receive methods of Zend_Queue_Db expect the active queue to be set by queue_id instead of name.
Zend_Queue_Db::create() will set the active queue by ID, so send and receive will work in that case. But, when using setActiveQueue() by name like in UC-01, send and receive will both fail because it is trying to set the queue_id to the queue name.
Is this the expected behavior or is it an issue with Zend_Queue_Db?
I still do not feel very confident with the name of this component. Zend_Queue is to general for this... what about message queues (Apache ActiveMQ, RabbitMQ, ...)? Will they get their own component (Zend_MessageQueue?)?
ActiveMQ and RabbitMQ are supported using the Zend_Queue_Adapter_Stomp adapter.
Stomp is a protocol. Apache ActiveMQ and RabbitMQ are message brokers supporting various protocols. Saying that Apache ActivqMQ and RabbitMQ are supported using a protocol is just wrong.
Supporting the Stomp protocol is nice but in reality just supporting its definitions is not enough (e.g. RabbitMQ uses a different frame delimiter).
Hi Justin,
Can you rename setMsgClass(), setMsgsetClass(), and so on to setMessageClass() and setMessageSetClass()? Randomly abbreviating words like that can make an API difficult to remember.
I would also suggest that Stomp receive first-level support as Zend_Stomp (this is the case with other protocols, such as HTTP, Wildfire, etc.). Zend_Queue_Adapter_ActiveMQ and Zend_Queue_Adapter_RabbitMQ can then use that component. Perhaps the frame delimiter could be configurable via a method in Zend_Stomp, and ActiveMQ and RabbitMQ classes could simply set up the delimiter and then proxy requests to Zend_Stomp.
Is there any support for filtering based on certain criteria? This is a very common use case.
Otherwise, looking forward to seeing this in trunk!
-Matt
Are you planing to implement "gearman" ?
It's an upcomming job system, which is easy to use and not bound to any language (you can add jobs to the queue from php, and get them from java).
http://www.danga.com/gearman/
http://www.gearman.org/doku.php
I don't think it makes sense to implement Gearman as part of a unified Queue interface. Gearman is a job queue which is fundamentally different from a message queue. Looking through the Zend_Queue_Adapter_Abstract, the only method that would be supported would be send(). recieve() is for a worker not a client, and deleteMessage() is automatic with Gearman.
There needs to be a separate proposal for Zend_Queue_Job or Zend_JobQueue that would support Gearman and Zend Platform's JobQueue. It also makes sense to start a Zend_Gearman proposal that ports in the Gearman Pear class, supports the Pear class and the Gearman PHP extension, sort of like Zend_Json does.
ZF Home Page
Code Browser
Wiki Dashboard
1. I think Zend_Queue_Message_Iterator is a typo of Zend_Queue_Adapter_Array, or vise verse. Could you please also provide skeleton of this class?
2. For method Zend_Queue_Message::setFromArray(), probably the input array should be stored in $this->_data.
Very nice proposal. Thanks.