每个用户都有一组宝石。可以通过REST API访问这些gem:
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
我有几个后端进程,它们可以并发运行,并且可以通过POST
HTTP方法添加gems。 (他们也可以编辑(PUT
)或删除(DELETE
)宝石,但这对我的问题并不重要。实际上,它是。请继续阅读。)
从高级别的角度来看,他们会做以下事情:
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
如上所述,这些过程并行运行。通常,两个进程不管理同一用户的gem,但可能会发生。
因此,如果在此期间发生变化,我需要一种机制来禁止步骤POST
中的3b
。我想过使用ETags和乐观锁定:
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
我不确定ETag是否适用于此。 ETag的大多数示例都是关于一个资源(例如/gem/23
),而不是关于资源集合(例如/gem
)。也就是说,在步骤3b
中,我提供了完整宝石集合的ETag,而实质上我提供了一个单独的宝石。
答案 0 :(得分:0)
当然,您的问题听起来非常适合使用ETag。它是一个集合的事实并不重要;重要的是,它是一种具有表示的资源,您可以始终从中生成ETag。
要考虑的一件事是,是否有关于集合的表示的任何内容可以改变,这对您的API消费者来说并不重要。例如,假设您以一些随机或不一致的顺序输出集合,但集合在语义上被定义为无序。在这种情况下,您可以根据集合中的项目集生成weak ETag。