我想知道如何使用rest处理列表中的添加和删除。下面是一个我想更改的示例对象。
{
name: SomeName
id: 1
email: [foo@foo.com, bar@bar.com]
}
应该允许用户更新电子邮件列表,在其中他/她可以同时添加和删除电子邮件地址。
api是 PATCH /{id}
我可以想出两种方法来实现这一点
用户每次更新时都会传递完整的电子邮件列表。然而,我可以想到的问题是,如果两个人同时更新电子邮件,一些更新可能会丢失。
示例用户1希望删除foo并添加foo1 email: [foo1@foo1.com, bar@bar.com]
,而用户2希望删除bar并添加bar1 email: [foo@foo.com, bar1@bar1.com]
. 在这里,无论哪个请求稍后被处理,都将存储特定的数据,而期望的结果应该是 email: [foo1@foo1.com, bar1@bar1.com]
另一种方法是在api中分别删除和添加电子邮件地址。也就是说,有两个字段 email_addresses_to_add
以及 email_addresses_to_remove
.
在上面的例子中,用户1将发送 {email_addresses_to_remove:[foo@foo.com], email_addresses_to_add:[foo1@foo1.com]}
用户2将发送 {email_addresses_to_remove:[bar@bar.com], email_addresses_to_add:[bar1@bar1.com]}
要做到这一点,正确的方法是什么,以便能够优雅地处理并发更新?第二种方法正确吗?还是有更好的办法?
2条答案
按热度按时间qacovj5a1#
正确的方法是存在的,但是非常复杂。首先,你需要对数据进行修改,以便准确地知道更改列表的人在看什么。其次,您需要将每个操作(添加、删除、移动)视为一个原子操作,如下所示:
第三,您需要让客户发送的不是完整的电子邮件列表,而是他们对其执行的操作列表:
(您可以使用
PATCH
如果你想,这里的语义是正确的-PATCH
是一种修改非幂等运算的方法。)最后,您需要编写执行以下操作的服务器代码:将实际版本与发送的一个客户端进行比较;
如果修订相同-只需应用操作并生成新修订;
如果修订是相同的-服务器需要提取应用于修订之间的列表的所有操作,并以现代版本控制系统的方式“重新设置”客户端请求。例如,如果客户机删除了记录#3,但他看不见,另一个客户机在列表头插入了新记录,则必须删除#4。注意,必须使用幂等标记,因为您的操作不是幂等的。您可以在这里找到详细的解释:https://twirl.github.io/the-api-book/docs/api.en.html#chapter-11(规则9)。
坦白地说,我宁愿把它简单化,禁止合作编辑。这是非常棘手的事情,即使我们谈论最简单的事情。
ulydmbyx2#
在http中,最直接的处理方法是允许客户机编辑表示方向,然后用put发回新文档的完整副本。
补丁通常只在文档相对于http头比较大,并且相对于文档的大小变化很小的情况下才有意义。
但如果因为某些原因必须使用修补程序,则应发送修补程序文档。如何描述所做编辑的确切性质将取决于客户端决定使用哪种修补程序格式。
如果您这里有一个json文档,那么您有一些有趣的标准化选项。json修补程序(application/json patch+json)和json合并修补程序(application/merge patch+json)将是首先要考虑的两个。
如果您有多个作者试图修改同一个资源,那么您可能需要查看有条件的请求,这为客户端提供了一种方便的方法来标识他们接收的资源的表示(在应用自己的本地编辑之前)。