[
Lists Home |
Date Index |
Thread Index
]
"K. Ari Krupnikov" wrote:
>Suppose I want to build a RESTful interface to an ACID system. I want
>to allow the user to incrementally change the state of the system, but
>only "commit" the changes when he is satisfied with their sum. I
>imagine a user GETting a resource, POSTing some changes to it which
>may have side effects on other resources, GETting other resources to
>observe the side effects, and eventually committing to the changes or
>rejecting them. It's easy enough to take care of ACD because these
>happen on the server and are transparent to REST, but I'm not sure how
>would one ensure Isolation. Two users who are GETting the same
>resource should see different things depending on which transaction
>each of them is in. I can't see a way to do this except to add
>something like ?transaction-id=0x234BD2037 to every URI which would
>expose completely unnecessary implementation details to the user.
>
>Am I thinking of this in the wrong terms?
>
>
First, you may want to try asking this question on
rest-discuss@yahoogroups.com. However, here is a suggestion:
If you are going to have a transaction concept, I suggest having a
transaction resource. For instance, suppose you were to POST your
credentials to http://example.com/t. On successful authentication, it
returns to you a new URI, http://example.com/t/12345. Doing a GET on
that URI would return a simple document (possibly XML) that indicates
the status of the transaction. For instance, you might have something
like the following:
<transaction>
<state>pending</state>
<lastError />
</transaction>
The state may be one of the following: pending, failed, completed. It
starts off as pending, when you are finished, you will attempt to set it
to completed. If the transaction cannot be completed, it will be set
(by the server) to failed, and the lastError element will contain
information on why it failed.
This returned URI is also your transaction context. You GET, POST,
etc. the URIs you normally would have except that the path will begin
with "t/12345/" (e.g. instead of http://example.com/resource, it would
be http://example.com/t/12345/resource). Because of this, all
"resources" interacted with can be specific to the owner of the
transaction, while everyone else sees either the original resource or
their own transaction variant.
Now, if you decide to cancel the transaction, you just DELETE
http://example.com/t/12345. If you decide to complete the transaction,
you do the following:
GET http://example.com/t/12345
set the state to "completed"
PUT http://example.com/t/12345
If you get back a 200 (or 204), then the transaction is successful. If
you get back a 4xx response, a GET on the transaction resource would
tell you where the problem is. Note that the PUT is being used here
because the transaction resource would not go away after the transaction
was completed, which is good when you need to remember how you got from
point A to point B.
While I am at it, you could extend the transaction document even more.
For instance, you could log each action performed within the
transaction, allowing you to do things like conditionally rollback parts
of the transaction. The document might look something like:
<transaction>
<state>pending</state>
<log>
<action method="POST" uri="http://example.com/t/12345/resource1"
id="1"/>
<action method="POST" uri="http://example.com/t/12345/resource3"
id="2"/>
<action method="POST"
uri="http://example.com/t/12345/resource3a" id="3"/>
<action method="DELETE"
uri="http://example.com/t/12345/resource2" id="4"/>
</log>
</transaction>
In order to "roll back" a change, you would PUT an updated transaction
document with the rolled-back actions removed from the list. This also
means that you could roll back changes and complete the transaction in
one step (a single PUT) if you wanted to.
Seairth Jacobs
http://www.seairth.com
|