ETags and Optimistic Concurrency Control

Another use for Etags is Concurrency Control, there we can use for Pessimistic and Optimistic.
Here i will explain specifically Optimistic Concurrency Control.

This helps solve the Lost Update problem which is what happens when multiple people edit a resource without knowledge of eachothers’ changes. In this scenario, the last person to update a resource “wins”, and previous updates are lost.

For Example
Let’s say that 2 API clients both GET a resource example.com/api/article/4, retrieving a blog article with an ID of 4:

$ curl -i example.com/api/article/4

HTTP/1.1 200 OK
Date: Sat, 09 Feb 2013 16:09:50 GMT
Last-Modified: Sat, 02 Feb 2013 12:02:47 GMT
Content-Type: application/json

{
id: 4,
content: "Heres a blog article, it has lots of content...",
status: "published".
created: "Sat, 02 Feb 2013 08:29:53 GMT",
updated: "Sat, 02 Feb 2013 12:02:47 GMT",
}

Now, client A notices a grammar error with the word ‘Heres’ and decides to fix it. Client A issues a PUT request, with updated text.

$ curl -i -X PUT -d "content=Here's a blog article, it has lots of content..." example.com/api/article/4

HTTP/1.1 200 OK
Date: Sat, 09 Feb 2013 16:11:46 GMT
Last-Modified: Sat, 09 Feb 2013 16:11:46 GMT
Content-Type: application/json

{
id: 4,
content: "Here's a blog article, it has lots of content...",
status: "published".
created: "Sat, 02 Feb 2013 08:29:53 GMT",
updated: "Sat, 09 Feb 2013 16:11:46 GMT",
}

Now, around the same time, client B decides to add some content. However, client B doesn’t know about client A’s change! Client B makes an update:

$ curl -i -X PUT -d "content=Heres a blog article, it has lots of content, and now has an extra sentence..." example.com/api/article/4

HTTP/1.1 200 OK
Date: Sat, 09 Feb 2013 16:12:02 GMT
Last-Modified: Sat, 09 Feb 2013 16:12:02 GMT
Content-Type: application/json

{
id: 4,
content: "Heres a blog article, it has lots of content, and now has an extra sentence...",
status: "published".
created: "Sat, 02 Feb 2013 08:29:53 GMT",
updated: "Sat, 09 Feb 2013 16:12:02 GMT",
}

The incorrect ‘Heres’ is back! Client A’s update is lost; We have experienced the Lost Update Problem.

How ETags can help
ETags can be used in combination with the If-Match header to let the server decide if a resource should be updated.

This works by letting a client know that a resource has been updated since the last time they checked. The server informs the client via a 412 Precondition Failed response.

>If a resource changes, so does it’s ETag. In this way, each “version” of the resource has a unique ETag. If a client attempts and update with a mismatching ETag, then the update is cancelled and a 412 status is given.

This is how the previous example would play out if ETags were employed.

The 2 API clients both GET the resource /api/article/4, retrieving the article. This time, an ETag is returned.

$ curl -i example.com/api/article/4

HTTP/1.1 200 OK
Date: Sat, 09 Feb 2013 16:09:50 GMT
Last-Modified: Sat, 02 Feb 2013 12:02:47 GMT
ETag: c0947-b1-4d0258df1f625
Content-Type: application/json

{
id: 4,
content: "Heres a blog article, it has lots of content...",
status: "published".
created: "Sat, 02 Feb 2013 08:29:53 GMT",
updated: "Sat, 02 Feb 2013 12:02:47 GMT",
}

Now, client A once again notices the grammar error and decides to fix it. Client A issues a PUT request, with updated text and the ETag received in the first request, in the form of the If-Match header.

$ curl -i -X PUT -d "content=Here's a blog article, it has lots of content..." -H "If-Match: c0947-b1-4d0258df1f625" example.com/api/article/4

HTTP/1.1 200 OK
Date: Sat, 09 Feb 2013 16:11:46 GMT
Last-Modified: Sat, 09 Feb 2013 16:11:46 GMT
ETag: df35b-af-36f3b324a3ff6
Content-Type: application/json

{
id: 4,
content: "Here's a blog article, it has lots of content...",
status: "published".
created: "Sat, 02 Feb 2013 08:29:53 GMT",
updated: "Sat, 09 Feb 2013 16:11:46 GMT",
}

What happened here? The ETag given by Client A matches the ETag of the resource, and so we know that the resource has not changed without Client A’s knowledge. The update is performed, and a new ETag is generated for that resource.

Around the same time, client B decides to add some content. However, client B doesn’t know about client A’s change! Client B attempts an update, with the old ETag:

$ curl -i -X PUT -d "content=Heres a blog article, it has lots of content, and now has an extra sentence..." -H "If-Match: c0947-b1-4d0258df1f625" example.com/api/article/4

HTTP/1.1 412 Precondition Failed
Date: Sat, 09 Feb 2013 16:12:02 GMT

Here we see that the update did not occur. The ETag used in the If-Match header did not match the ETag of the resource. Client B therefore received a 412 Precondition Failed response and then knows it needs to update it’s knowledge of the resource before attempting to update again.

Notes
This type of concurrency control puts a higher onus on the client. The client would need to implement ETags, using If-Match headers and handling 412 responses.
Note that the server needs decide to what to do if no If-Match header is present – Does it enforce its use, or only use concurrency control when it has the needed headers? The answer to this may boil down to your particular needs.

Advertisements
Post a comment or leave a trackback: Trackback URL.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: