RFC: race condition in resource updates

Richard Su rwsu at redhat.com
Fri Nov 30 00:07:42 UTC 2012


Hi,

There is a race condition when two clients attempt to update the same 
resource at the same time. Both clients sees the same initial state. 
Client A changes it to state A and then Client B changes it to state B. 
Client B should know that the resource was changed to state A before 
deciding whether to change the state to B.

This race condition is present in both the UI and API.

If we want to prevent this type of race condition, there are two ways to 
solve it: one leaves it optional and the other forces the prevention. 
The optional case, uses headers, and leaves the decision to prevent such 
race conditions to the client. The forced case uses the updated_at field 
as a means to check if a resource has been modified.

It is not clear to me if it should be forced since the UI currently 
allows it whether by design or oversight. Your opinion on this matter is 
appreciated.


* Optional Case

Use the ETag header, containing a MD5 hash, to indicate the state of the 
resource. As far as I can tell we have this header already, perhaps it 
is auto generated.

In a PUT, clients will include a If-Match header as part of the request, 
setting the value to the ETag hash it received when it last received the 
resource's state. Before processing a PUT, the server will compare ETag 
to If-Match and allow the request to complete if the values match. If 
the values do not match the server returns status code 412 - 
Precondition Failed. A time based alternative to ETag and If-Match would 
be Last-Modified and If-Unmodified-Since.

This does not address the issue for the UI.

(This idea is from 
http://blog.m.artins.net/restful-web-services-preventing-race-conditions/)


* Forced Case

Most of the resources available through the api have a updated_at field. 
One exception is deployables, and this will need to be rectified. The 
updated_at field can be used as a timestamp to flag an error if a 
resource has changed since the client last requested a view of it.

For the API, in a PUT, clients will be required to return back the 
updated_at value. If the server sees updated_at has not changed, the 
request is allowed to complete. If the value has changed, the server 
returns status 409 - Conflict.

For the UI, we can embed updated_at as hidden form data and perform the 
same comparisons. If a change is detected, the server will display an 
error message.







More information about the aeolus-devel mailing list