blob: 72b20a179e9822dbd0fcc0810389c62d95baa693 [file] [log] [blame]
<div class="wiki-content maincontent"><h2>RESTful Queue</h2>
<p>This document is intended to document the ideal RESTful interface to message queues in light of</p>
<ul><li><a shape="rect" href="http://tech.groups.yahoo.com/group/rest-discuss/message/8955">the discussion on rest-discuss</a></li><li><a shape="rect" href="http://bitworking.org/projects/atom/draft-ietf-atompub-protocol-17.html">Atom Publishing Protocol</a> (APP)</li><li><a shape="rect" href="http://www.dehora.net/doc/httplr/draft-httplr-01.html">httplr</a></li></ul>
<h3>Issues with Queues and REST</h3>
<p>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.</p>
<p>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.</p>
<h3>Queue administration</h3>
<p>This section deals with the general browsing and creation/deletion of queues.</p>
<h4>Browse available queues</h4>
<p>To browse the queues, they are a hierarchial structure usually, so lets browse them like any APP collection</p>
<structured-macro ac:macro-id="3fa761d7-8cd8-4f8c-83b8-a2b1668580a4" ac:name="code" ac:schema-version="1"><plain-text-body>
GET /queues
--------------------&gt;
200 OK
Atom Feed with one entry per directory/category/queue
&lt;--------------------
</plain-text-body></structured-macro>
<h4>Browse a queue's messages</h4>
<structured-macro ac:macro-id="1bf2b8f7-f81e-4248-8e19-1e9fd926097a" ac:name="code" ac:schema-version="1"><plain-text-body>
GET /queues/uk/products/books/computers
--------------------&gt;
200 OK
Atom Feed with one entry per pending message
&lt;--------------------
</plain-text-body></structured-macro>
<p>Note that we could expose the queues as a tree, for example</p>
<structured-macro ac:macro-id="9e54d0a4-4970-4724-a2f9-a6f0d29def2d" ac:name="code" ac:schema-version="1"><plain-text-body>
GET /queues/uk/products
--------------------&gt;
200 OK
Atom Feed with one entry per queue in uk.products.* together with any child catgory/directory
&lt;--------------------
</plain-text-body></structured-macro>
<h4>Creating a queue</h4>
<p>Creating a queue is typically idempotent; since really you are just creating a name that folks can post to.</p>
<structured-macro ac:macro-id="75a802e6-2ef3-4091-81ed-000610653001" ac:name="code" ac:schema-version="1"><plain-text-body>
POST /queues
--------------------&gt;
201 OK
Location: someUniqueUrlForTheNewQueueToBePostedTo
&lt;--------------------
</plain-text-body></structured-macro>
<h4>Deleting a queue</h4>
<structured-macro ac:macro-id="346b40b2-c328-4458-b4ea-26a176422a1a" ac:name="code" ac:schema-version="1"><plain-text-body>
DELETE /queues/foo.bar
--------------------&gt;
200 OK
&lt;--------------------
</plain-text-body></structured-macro>
<h3>Send to queue</h3>
<p>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...</p>
<structured-macro ac:macro-id="6f2ef332-dfeb-4e45-9d03-c204a1a7bd72" ac:name="code" ac:schema-version="1"><plain-text-body>
POST /queues/foo.bar
--------------------&gt;
201 OK
Location: someUniqueUrlForTheNewMessageToBePostedTo
&lt;--------------------
</plain-text-body></structured-macro>
<p>The client can then repeatedly POST the mesage to someUniqueUrlForTheNewMessageToBePostedTo until it gets a 200 OK which avoids duplicates.</p>
<h4>Optional alternative for single request</h4>
<p>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</p>
<structured-macro ac:macro-id="dc797621-e532-4c96-a49e-2a20bcb948af" ac:name="code" ac:schema-version="1"><plain-text-body>
POST /queues/foo.bar?guid=clientGeneratedUniqueId
--------------------&gt;
200 OK
&lt;--------------------
</plain-text-body></structured-macro>
<h3>Consuming from a queue</h3>
<p>As described above, this is the tricky part of mapping message queues to REST. </p>
<p>So we introduce a resource for a <em>subscription</em> to a queue. The subscription remains active until some timeout value - so a subscription is a sort of lease.</p>
<p>When a subscription is created it can be given a variety of different pieces of data such as </p>
<ul><li>the <link><page ri:content-title="What is the Prefetch Limit For?"></page><link-body>prefetch buffer</link-body></link></li><li>what destinations it applies to (for example we could use wildcards)</li><li>whether a selector/filter is applied</li></ul>
<h4>Create a subscription</h4>
<structured-macro ac:macro-id="d49de1c7-6395-4df3-8699-dab96e796744" ac:name="code" ac:schema-version="1"><plain-text-body>
POST /subscriptions
--------------------&gt;
201 OK
Location: subscriptionUri
&lt;--------------------
</plain-text-body></structured-macro>
<p>The actual subscription data could be form encoded key/value pairs.</p>
<h4>Deleting a subscription</h4>
<p>Good clients will delete subscriptions when they are no longer required; though they do timeout eventually.</p>
<structured-macro ac:macro-id="6badd40e-e6f3-4b2c-af45-6ee2c6a8db8d" ac:name="code" ac:schema-version="1"><plain-text-body>
DELETE subscriptionUri
--------------------&gt;
200 OK
&lt;--------------------
</plain-text-body></structured-macro>
<h4>Consuming messages</h4>
<p>You consume messages by browsing the subscription (like any APP resource) then DELETEing the message when you have finished processing it.</p>
<structured-macro ac:macro-id="bfb180ae-ec58-4f0d-a60f-0467b961cf5f" ac:name="code" ac:schema-version="1"><plain-text-body>
GET subscriptionUri
--------------------&gt;
200 OK
Atom Feed with one entry per message associated to this subscription
&lt;--------------------
</plain-text-body></structured-macro>
<p>Then to acknowledge a particular message has been processed</p>
<structured-macro ac:macro-id="2b9a473f-a596-45c3-9d91-d25aca26d9c2" ac:name="code" ac:schema-version="1"><plain-text-body>
DELETE messageUri
--------------------&gt;
200 OK
&lt;--------------------
</plain-text-body></structured-macro>
<h2>Deltas with APP</h2>
<p>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. </p>
<p>In ActiveMQ's case, we use a <link><page ri:content-title="What is the Prefetch Limit For?"></page><link-body>prefetch value per consumer</link-body></link> to define how many messages each consumer gets in its buffer, before messages must be acknowledged to get more messages.</p>
<p>So the idea is that we have a per-consumer feed which is created; it can then be browsed (by anyone with sufficient karma).</p>
</div>