检测会话的多个实例

时间:2012-11-05 10:53:59

标签: jquery django

我正在构建一个充当基于Web的文件编辑器的应用程序。用户可以选择要编辑的文件,然后从服务器检索该文件并显示在字段中。然后,用户可以编辑该文件,并最终保存该文件。

这引入了我试图解决的竞争条件。

客户端文件并不总是与服务器端文件同步。当用户打开已在其他位置打开和编辑的文件时,保存将覆盖其他客户端执行的任何编辑。虽然可以使用某种形式的合并来解决这个问题,但这远远超出了该项目的范围。

当用户登录两台不同的PC或两台不同的浏览器,并尝试两次打开同一文件时,可以使用会话密钥检测到这一点。但是,当用户打开第二个选项卡时,会话密钥将是相同的。

目前我定期ping文件(例如,每2秒)并检查之前的ping是否大约是2秒前。如果它小于那个(减去滞后的某个值)那么可能是两个观察该文件的客户端。但是,如果用户在文件和文件之间快速切换,则会中断,这只是简单的丑陋。

有更好,更清洁的方法吗?

我正在使用Django后端,并且前端严重依赖于jQuery,因此任何基于这两者的功能都会有我的偏好。

一些相关代码如下所示:

从客户端,定期查看文件服务器端:

setInterval(function(){
    opened = $('input[name=file]:checked', '#files').val();
    if(opened){
        $.post('./' + opened + '/ding').error(function(){
            alert('Something is awry.');
        });
    }
}, 2000);

从服务器端,处理这些dings:

def ding(request, user_id, project_id, file_id):
    user = User.objects.get(pk=user_id)
    project = Project.objects.get(pk=project_id)
    file = File.objects.get(pk=file_id)

    session_key = request.session.session_key

    can_claim = file.last_seen_open == None or timezone.now() - file.last_seen_open > datetime.timedelta(seconds=4)
    is_mine = file.last_opened_by == session_key
    is_iffy = file.last_seen_open != None and timezone.now() - file.last_seen_open < datetime.timedelta(seconds=1)

    if is_iffy:
        return HttpResponse(status=409, content="File is iffy")
    if can_claim or is_mine:
        file.last_opened_by = session_key
        file.last_seen_open = timezone.now()
        file.save()
        return HttpResponse(status=200, content="File ding'd")
    else:
        return HttpResponse(status=409, content="File claimed by someone else")

如果文件在同一个密钥上打开两次,则返回响应“409:File is iffy”

1 个答案:

答案 0 :(得分:0)

我偶然发现了你的问题。由于问题已经有几个月了,我不确定你是否还在等待答案。不过,我认为有一个简单的解决方案:

当用户请求文件时,不仅要获取文件的内容,还要获取上次修改日期。存储客户端的价值。当用户进行一些更改并选择保存文件时,请将值与新内容一起发送。在服务器端,您只需将文件的当前修改日期与用户发送的值进行比较即可。如果它们不匹配,则该文件已被其他用户同时更新。