Gents,

In case any more of you run into this issue there is a bug in Rails, which is described here: https://github.com/rails/rails/issues/7809

I also have an example application that highlights the bug here: https://github.com/mtaylor/Rails-Inverse-Nested-Attr-Bug

I've created a monkey patch and pushed it to above repo.  It is based on an outstanding pull request, created by Matt Jones, (see: the GH Issue for info).  Until the pull request is merged into rails we'll have to carry the fix ourselves.  If you run into this bug then please feel free to clone the Monkey Patch from my repo and include it in your src.

Regards

Martyn

-------- Original Message --------
Subject: Re: RFC: race condition in resource updates
Date: Fri, 30 Nov 2012 12:29:07 +0000
From: Martyn Taylor <mtaylor@redhat.com>
To: aeolus-devel@lists.fedorahosted.org


On 11/30/2012 12:07 AM, Richard Su wrote:
> 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.
>
Is this something that is managed by us or by the HTTP server?

Looking at the HTTP Spec this does seem to be the way to go.  But I am 
unsure on how this is implemented.  For example, we do not want the MD5 
Checksum to be done after the resource has been represented in a 
particular format, since the client is stuck using that format or it has 
to refresh its entire view (Since the checksum will change from XML to 
JSON).

> 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 seems more natural to me, but I wonder about caching. Last-modified 
is used by Caches between the client and the origin server.  Is it 
normal for a cache to update this tag?

Also, is this something we are implementing or is it provided by the 
HTTP Server?  If it is the latter then we may have timesync problems 
when clustering.

> 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.
I dislike this approach, particularly when the problem as been solved at 
the protocol level.
>
> 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.
>
Another argument for the UI consuming the API.
>
>
>
The "Optional" or "Protocol" approach gets my vote.  But I need to find 
out more on how this thing works.  ETags does seem to be designed for 
this specific purpose so I would start there.

Thanks

Martyn