2012-11-05 43 views
0

我正在构建一个用作基于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); 

从服务器端,处理这些弯折:

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:文件不可用”

回答

0

我在这里意外地发现了你的问题。由于问题已经过了几个月,我不确定你是否还在等待答案。尽管如此,我认为有一个简单的解决方案:

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

相关问题