3

Each user has a collection of gems. These gems can be accessed via a REST API:

GET    /user/<user id>/gem              -> get all gems
GET    /user/<user id>/gem/<gem id>     -> get an existing gem
POST   /user/<user id>/gem              -> add a new gem
PUT    /user/<user id>/gem/<gem id>     -> edit an existing gem
DELETE /user/<user id>/gem/<gem id>     -> delete an existing gem

I have several backend processes, which run concurrently and which could add gems via the POST HTTP method. (They can also edit (PUT) or delete (DELETE) gems, but that's not important for my question. Well actually, it is. Please continue reading.)

Seen from a high-level view, they do the following:

1.  GET /user/<current user id>/gem
2.  some calculations, based on step 1
3a. if (step 2 decided that a gem should be added)
3b.     POST /user/<current user id>/gem

As said, these processes run in parallel. Usually, two processes are not managing the gems of the same user, but it might happen.

So I need a mechanism to disallow the POST in step 3b if something changed in the meantime. I thought about using ETags and optimistic locking:

1.  GET /user/<current user id>/gem and remember the returned ETag
2.  some calculations, based on step 1
3a. if (step 2 decided that a gem should be added)
3b.     POST /user/<current user id>/gem with header 'If-Match=<ETag from step 1>'
3c.     if (server returns 412 - precondition failed)
3d.         start again at step 1

I am not sure if ETags are intended for this. Most examples of ETag are about one single resources (such as /gem/23), but not about a collection of resources (such as /gem). That is, in step 3b, I am providing the ETag of the complete collection of gems, while in essence I am providing one single gem to be added.

1 Answers1

0

Sure, your problem sounds like it's very well-suited to that use of ETags. The fact that it's a collection doesn't really matter; what matters is that it's a resource with a representation that you can consistently generate an ETag from.

One thing to think about is if there's anything about the collection's representation that can change that doesn't matter to your API consumer. For example, let's say you output the collection in some random or inconsistent order, but the collection is defined semantically as being unordered. In that case you could generate a weak ETag based on the set of items in the collection.

Community
  • 1
  • 1
Kevin Christopher Henry
  • 46,175
  • 7
  • 116
  • 102