REST乐观锁定和多个PUT

时间:2016-02-21 11:29:43

标签: angularjs rest

据我了解,PUT请求不应返回任何内容。 考虑客户端想要运行此伪​​代码:

$ ./bin/idx2ptr f

 executing 'function'

 a[0] : 1 | b[0] : 0
 a[1] : 1 | b[1] : 0
 a[2] : 2 | b[2] : 1
 a[3] : 2 | b[3] : 0
 a[4] : 3 | b[4] : 1
 a[5] : 3 | b[5] : 0
 a[6] : 3 | b[6] : 0
 a[7] : 4 | b[7] : 1


$ ./bin/idx2ptr p

 executing 'functionp'

 a[0] : 1 | b[0] : 0
 a[1] : 1 | b[1] : 0
 a[2] : 2 | b[2] : 1
 a[3] : 2 | b[3] : 0
 a[4] : 3 | b[4] : 1
 a[5] : 3 | b[5] : 0
 a[6] : 3 | b[6] : 0
 a[7] : 4 | b[7] : 1

(想象一下,我有一个输入控件和一个“保存”按钮,这允许我更改输入控件中显示的对象“x”的一部分,然后在按钮上单击PUT更改为服务器,然后继续编辑,也许“保存“另一个更改为”x“)

关于如何在REST API中实现乐观锁定的不同提议,上面的代码必须失败,因为get()返回的“x”的版本标记(但是实现)将在put()之后变得陈旧。 那你们人们通常如何让它发挥作用? 或者你只是在每次PUT之后重新获取对象?

2 个答案:

答案 0 :(得分:0)

你可以使用"有条件的"使用HTTP的操作,例如此处描述的mysql2标头:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24

简而言之:您使用If-Match请求发送ETag,并在GET标头中将此ETag提供回服务器。如果您尝试If-Match的资源有另一个PUT,服务器将会响应失败。您还可以使用带有ETag标头的简单时间戳。

当然,您必须让服务器代码了解条件请求。

对于多个步骤,If-Unmodified-Since确实可以返回新的表示,因此它也可以包含新的PUT或时间戳。即使服务器未返回ETag的新表示形式,您仍然可以使用PUT条件If-Unmodified-Since的响应中的时间戳。

答案 1 :(得分:0)

这可能是我在寻找的内容:http://tools.ietf.org/html/rfc7231#section-4.3.4 他们含蓄地说我们可以从PUT返回ETag。虽然只有在服务器应用了更改的情况下,但没有任何更正。

然而,这引出了另一个问题。在真实世界的应用程序中,PUT调用者将在JS gui中异步运行,就像我在问题中的示例一样。因此,无论是否输入任何更改,都可以多次按下“保存”按钮。如果我们不使用乐观锁定,那么假设PUT幂等性使得每次按钮点击发送另一个PUT查询是安全的,只要最后一个获胜(但实际上如果有变化那么它不能保证,所以问题仍然存在)

但是通过乐观锁定,当第一个PUT成功时,它会返回更新的ETag,好吗?如果有另一个PUT请求正在运行,仍然有过时的标签版本,后一个请求将获得412并且用户将看到消息“其他人更改了资源” - 但实际上这是我们以前的更改。

你通常采取什么措施来防止这种情况发生?禁用“保存”按钮,直到其请求完全完成?如果它超时怎么办?或者你认为如果它是超时的话会看到并发更改错误消息是可以接受的,因为稳定性已经受到影响了吗?