Optimistic Concurrency
The Content Store relies on a technique called optimistic concurrency to deal with concurrent updates to content items. Clients are expected to co-ordinate updates between themselves using optimistic concurrency mechanisms. For background information about this technique, see http://www.w3.org/1999/04/Editing/.
Clients are required to either make active use of optimistic concurrency when updating content, or explicitly bypass it (not recommended), so you need to understand this section in order to make a client that will update content items.
Optimistic concurrency works as follows:
-
Each client that wants to make a modification to a content item downloads a copy of it. Each item is accompanied by an HTTP header called
ETag
. AnEtag
header is a unique identifier generated by the web service, and looks something like this:ETag: "129694559e911ee4c6d04212982"
-
Each client remembers the
ETag
associated with the content item it is modifying. -
After modifying the content item, the client performs a
PUT
operation to return it to the web service, including itsETag
in anIf-Match
header. Note that anETag
value includes its enclosing quote marks. A correctPUT
operation executed withcurl
would therefore look something like this:curl --include -u user:password -X PUT -H 'If-Match: "129694559e911ee4c6d04212982"' \
>
-H "Content-Type: application/atom+xml" http://host-ip-address/webservice/escenic/content/4 \>
--upload-file my-edited-article.xml -
The web service checks the supplied
Etag
to see if it matches the current copy of the content item. For the first client to return changes, this will be the case, and thePUT
operation will succeed. For all other clients that have been working on the content item, theEtag
will not match and the web service will return a412 PRECONDITION FAILED
response.
When a client receives a 412 PRECONDITION FAILED
response it should download the latest copy of the content item (with
its new ETag
), re-apply its changes to the new copy,
and then PUT
it back, hopefully succeeding this time.
If more than two clients are working on the same copy, however, this
might not be the case. In the worst case a client might need to retry
many times. Clients should be able to handle a certain number of
retries, back off after a few retries, and lower the rate of retry, and
possibly even request human intervention.
A client can circumvent the optimistic concurrency mechanism by sending
the header "If-Match: *"
in its
PUT
operations. This header specifies that the
operation should succeed no matter which version is current. The web
service will then accept the PUT
request without
performing any concurrency checks. The consequence of doing so is that
any changes made to the content item by other clients will be
overwritten. Your client should therefore never
do
this unless you know the consequences and are certain that it will not
cause problems.