blob: 14d9b92ff167fffbad1ed9a90f391ec78bcd6c18 [file] [view]
---
layout: default_md
title: RESTful Queue
title-class: page-title-classic
type: classic
---
[Developers](developers) > [Ideas](ideas) > [RESTful Queue](restful-queue)
RESTful Queue
-------------
This document is intended to document the ideal RESTful interface to message queues in light of
* [the discussion on rest-discuss](http://tech.groups.yahoo.com/group/rest-discuss/message/8955)
* [Atom Publishing Protocol](http://bitworking.org/projects/atom/draft-ietf-atompub-protocol-17.html) (APP)
* [httplr](http://www.dehora.net/doc/httplr/draft-httplr-01.html)
### Issues with Queues and REST
One of the main issues with making a truly RESTful API to a message queue is that a message queue is essentially a load balancer, so each consumer of a queue sees essentially a different queue; as only one consumer gets a copy of each message.
Also if a consumer goes away, the messages that were associated with that consumer need to be re-assigned to another consumer. So the main tricky part really is the operation for a consumer to find out what messages it may consume.
### Queue administration
This section deals with the general browsing and creation/deletion of queues.
#### Browse available queues
To browse the queues, they are a hierarchial structure usually, so lets browse them like any APP collection
```
GET /queues
-------------------->
200 OK
Atom Feed with one entry per directory/category/queue
<--------------------
```
#### Browse a queue's messages
```
GET /queues/uk/products/books/computers
-------------------->
200 OK
Atom Feed with one entry per pending message
<--------------------
```
Note that we could expose the queues as a tree, for example
```
GET /queues/uk/products
-------------------->
200 OK
Atom Feed with one entry per queue in uk.products.* together with any child catgory/directory
<--------------------
```
#### Creating a queue
Creating a queue is typically idempotent; since really you are just creating a name that folks can post to.
```
POST /queues
-------------------->
201 OK
Location: someUniqueUrlForTheNewQueueToBePostedTo
<--------------------
```
#### Deleting a queue
```
DELETE /queues/foo.bar
-------------------->
200 OK
<--------------------
```
### Send to queue
Sending to queue is the usual APP-style double request; one to get the unique URI to post to and secondly to do the actual post...
```
POST /queues/foo.bar
-------------------->
201 OK
Location: someUniqueUrlForTheNewMessageToBePostedTo
<--------------------
```
The client can then repeatedly POST the mesage to someUniqueUrlForTheNewMessageToBePostedTo until it gets a 200 OK which avoids duplicates.
#### Optional alternative for single request
If a smart client is capable of generating a system wide unique GUID (id) for the message, the server side could ignore duplicates. So posting to queue could be done without the double-request approach above
```
POST /queues/foo.bar?guid=clientGeneratedUniqueId
-------------------->
200 OK
<--------------------
```
### Consuming from a queue
As described above, this is the tricky part of mapping message queues to REST.
So we introduce a resource for a _subscription_ to a queue. The subscription remains active until some timeout value - so a subscription is a sort of lease.
When a subscription is created it can be given a variety of different pieces of data such as
* the [prefetch buffer](what-is-the-prefetch-limit-for)
* what destinations it applies to (for example we could use wildcards)
* whether a selector/filter is applied
#### Create a subscription
```
POST /subscriptions
-------------------->
201 OK
Location: subscriptionUri
<--------------------
```
The actual subscription data could be form encoded key/value pairs.
#### Deleting a subscription
Good clients will delete subscriptions when they are no longer required; though they do timeout eventually.
```
DELETE subscriptionUri
-------------------->
200 OK
<--------------------
```
#### Consuming messages
You consume messages by browsing the subscription (like any APP resource) then DELETEing the message when you have finished processing it.
```
GET subscriptionUri
-------------------->
200 OK
Atom Feed with one entry per message associated to this subscription
<--------------------
```
Then to acknowledge a particular message has been processed
```
DELETE messageUri
-------------------->
200 OK
<--------------------
```
Deltas with APP
---------------
Almost all of the above could be just pure APP really. The only real difference is that each consumer has its own feed of messages which are to be consumed.
In ActiveMQ's case, we use a [prefetch value per consumer](what-is-the-prefetch-limit-for) to define how many messages each consumer gets in its buffer, before messages must be acknowledged to get more messages.
So the idea is that we have a per-consumer feed which is created; it can then be browsed (by anyone with sufficient karma).