监控用户会话以防止编辑冲突

发布于 2024-09-15 10:14:11 字数 621 浏览 7 评论 0原文

我正在开发类似于 Pastebin 的东西(是的,它是通用的),但允许多个用户编辑。明显的问题是多个用户尝试编辑同一个文件。我正在考虑当一个用户正在处理文件时锁定文件(这不是最好的解决方案,但我不需要任何太复杂的东西),但为了防止/警告用户,我显然需要一个用于监控每个用户的编辑会话的系统。使用数据库和ajax,我正在考虑两种解决方案。

第一种方法是让编辑页面以任意时间间隔(例如一分钟)对服务器执行 ping 操作,并且它将更新数据库中的编辑会话条目。然后,下次脚本请求编辑时,它会检查最近的 ping,如果最近的 ping 是另一个任意时间之前(例如五分钟),那么我们假设前一个用户已经退出,并且可以再次编辑该文件。当然,这种方法的问题在于,先前用户退出的假设只是一个假设。他可能因为 Wi-Fi 连接不稳定,然后就断线了十分钟,而窗户始终开着。

当然,为了解决这个问题,我们必须让服务器响应先前关闭的会话的新请求并返回错误,告诉客户端向用户指出他的会话已关闭结束,然后通过将其另存为服务器上的另一个文件并要求用户手动合并等来处理它。不言而喻,这对于最终用户来说是相当可怕的。

所以我开始思考另一个解决方案。当用户会话结束时,也可能触发一个 unload 事件,但我无法确定这是否可靠。

有没有人有其他更优雅的解决方案来解决这个问题?

I'm working on something similar to a pastebin (yeah, it's that generic) but allowing for multiple user editing. The obvious problem is that of multiple users attempting to edit the same file. I'm thinking along the lines of locking down the file when one user is working on it (it's not the best solution, but I don't need anything too complex), but to prevent/warn the user I'd obviously need a system for monitoring each user's edit sessions. Working with database and ajax, I'm thinking of two solutions.

The first would be to have the edit page ping the server at a arbitrary interval, say a minute, and it would update the edit session entry in the db. Then the next time a script request to edit, it checks for the most recent ping, and if the most recent was another arbitrary time ago, say five minute, then we assume that the previous user had quited and the file can be edited again. Of course, the problem with this method is that the assumption that the previous user had quited is simply an assumption. He could be having flaky wi-fi connection and simply dropped out for ten minutes, all the time with the window still open.

Of course, to deal with this problem, we'd have to have the server respond to new request from previously closed sessions with an error, telling the client side to point out to the user that his session has ended, and then deal with it by, say, saving it as another file on the server and asking the user to manually merge it, etc. It goes without saying that this is rather horrible for the end user.

So I've came around to think of another solution. It may also be possible to get a unload event to fire when the user's session ends, but I cannot be sure whether this will work reliably.

Does anybody has any other, more elegant solution to this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

爱你是孤单的心事 2024-09-22 10:14:11

如果您预计对文件的并发编辑数量较少,则可以仅在数据库中存储该文件的版本号,并且当用户将文件下载到浏览器中时,他们也会获得该版本号。仅当版本号匹配时,他们才被允许上传更改。第一个上传的获胜。当检测到冲突时,您应该发回最新的文件和用户的更改,以便用户可以手动合并更改。优点是,即使同一用户同时进行两次编辑,该方法也有效。如果此功能最终被频繁使用,您可以添加类似于 diff 工具使用的客户端合并(但在这种情况下您可能需要保留旧版本)。

If you expect the number of concurrent edits to the file to be minor, you could just store a version number for the file in the db, and when the user downloads the file into their browser they also get the version number. They are only allowed to upload their changes if the version number matches. First one to upload wins. When a conflict is detected you should send back the latest file and the user's changes so that the user can manually merge in the changes. The advantage is that this works even if it's the same user making two simultaneous edits. If this feature ends up being frequently used you could add client-side merging similar to what a diff tool uses (but you might need to keep the old revisions in that case).

转角预定愛 2024-09-22 10:14:11

您最好选择“合并”解决方案。使用这种方法,您只需在用户将文档发布到服务器时检查更改。

基本方法是:
1. 用户A获取文档进行编辑,文档版本为1
2. 用户B获取文档进行编辑,文档版本为1
3. 用户B发布了一些更改,其中基础版本号为1
4.服务器更新文档,文档现在版本2
5. 用户B发布一些更改,包括基础版本号1
6. 服务器响应说自用户开始编辑以来文档已更改,并向用户发送新文档及其版本 - 然后用户需要将其更改合并到文档版本 2 中,然后发回服务器。用户现在实际上正在编辑文档版本 2
7. 用户A发布了一些更改,其中版本号为2
8. 服务器更新文档,现在版本为 3

您仍然可以每分钟执行一次“ping”,以获取当前版本号 - 您已经知道他们正在编辑的版本,因此如果有新版本可用,您可以让他们知道并让他们下载最新版本以进行更改。

这种方法的主要好处是用户永远不会锁定文件,因此您不需要任何任意的“超时”。

You're probably better off going for a "merge" solution. Using this approach you only need to check for changes when the user posts their document to the server.

The basic approach would be:
1. User A gets the document for editing, document is at version 1
2. User B gets the document for editing, document is at version 1
3. User B posts some changes, including the base version number of 1
4. Server updates document, document now at version 2
5. User B posts some changes, including the base version number of 1
6. Server responds saying document has changed since the user starts editing, and sends user the new document, and their version - user will then need to perform any merging of their changes into document version 2, and post back to the server. User is essentially now editing document version 2
7. User A posts some changes, including the version number of 2
8. Server updates the document, which is now at version 3

You can still do a "ping" every minute, to get the current version number - you already know what version they're editing, so if a new version is available you can let them know and let them download the latest version to make their changes into.

The main benefit of this approach is that users never lock files, so you don't need any arbitrary "time-outs".

最初的梦 2024-09-22 10:14:11

我想说你走在正确的道路上。我可能会实现一个混合解决方案:

有一个名为“active_edits”的表或类似的表,其中包含 document_id、用户和last_update_time 列。假设您的 ping 时间为 1 分钟,超时时间为 5 分钟。因此,用例如下所示:

Bob 打开一个文档。它检查last_update_time。如果超过 5 分钟前,则用 Bob 和当前时间更新表。如果不是,则表明其他人正在处理该文档,因此请给出错误消息。假设没有对其进行编辑,Bob 会处理该文档一段时间,并且客户端每分钟都会发出更新时间通知。

我想说应该包含一个“完成编辑”按钮和一个onunload处理程序。 Onunload,据我了解可能很不稳定,但不妨添加它。这两者都会向服务器发送一个仅发送的帖子,表示 Bob 已完成。即使 Bob 没有点击“完成编辑”并且 onunload 消失,最坏的情况是另一个用户必须再等待 5 分钟才能编辑。优点是,如果这些正常工作(合理的假设),那么系统会工作得更好一些。

在您描述的鲍勃无线连接不良或休息的情况下:我会说这不是什么大问题。您的 ping 函数应确保自 Bob 上次 ping 以来该文档尚未被其他人接管。如果有,只需给 Bob 一条消息,说明“其他人已开始处理该文档”,并为他们提供重新加载的选项。

编辑:另外,我会调查 window.onbeforeunload,而不是 onunload。我相信它会更早执行。我相信这是网站(包括斜线)用来让您确认您确实想要离开该页面的功能。我认为它适用于除 Opera 之外的主要浏览器。

I would say you are on the right track. I would probably implement a hybrid solution:

Have a single table called "active_edits" or something like that with a column for the document_id, the user, and the last_update_time. Lets say your ping time is 1 minute and your timeout is 5 minutes. So a use-case would look like this:

Bob opens a document. It checks the last_update_time. If it is over 5 minutes ago, update the table with Bob and the current time. If it is not, someone else is working on the document, so give an error message. Assuming it is not being edited, Bob works on the document for a while and the client pings an update time every minute.

I would say do include a "finish editing" button and a onunload handler. Onunload, from what I understand can be flaky, but might as well add it. Both of these would send a single send-only post to the server saying that Bob is done. Even if Bob doesn't hit "finish editing" and onunload flakes out, the worst case is that another user would have to wait 5 more minutes to edit. The advantage is that if these normally work (a fair assumption) then the system works a bit better.

In the case you described where a Bob is on a bad wireless connection or takes a break: I would say this isn't a big deal. Your ping function should make sure that the document hasn't been taken over by someone else since Bob's last ping. If it has, just give Bob a message saying "someone else has started working on the document" and give them the option to reload.

EDIT: Also, I would be looking into window.onbeforeunload, not onunload. I believe it executes earlier. I believe this is the function website (slashdot included) use to allow you to confirm that you actually want to leave the page. I think it works in the major browsers except Opera.

分开我的手 2024-09-22 10:14:11

与这个问题一样 如何管理并发访问表单?,我不会尝试实现悲观锁定。在无状态环境中可靠地工作实在是太困难了。相反,我会使用乐观锁定。然而,在本例中,我使用了文件的 SHA 哈希之类的东西来确定自用户上次读取文件以来文件是否已更改。对于每个更改文件的请求,您将运行文件字节的 SHA 哈希,并将其与首次读取数据时提取的版本进行比较。如果已更改,您可以拒绝更改,并强制用户再次进行编辑(提取文件内容的新副本),或者提供更高级的冲突解决方案。

As with this SO question How do you manage concurrent access to forms?, I would not try to implement pessimistic locking. It is simply too difficult to get working reliably in a stateless environment. Instead, I would use optimistic locking. However, in this case I used something like a SHA hash of the file to determine if the file had changed since the user last read from the file. For each request to change the file, you would run a SHA hash of the file bytes and compare it with the version you pulled when you first read the data. If had changed, you reject the change and either force the user to do their edits again (pulling a fresh copy of the file contents) or you provide a fancier conflict resolution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文