2012-11-05 73 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

我在這裏意外地發現了你的問題。由於問題已經過了幾個月,我不確定你是否還在等待答案。儘管如此,我認爲有一個簡單的解決方案:

當用戶請求文件時,不僅要獲取文件的內容,還要獲取最後修改日期。將該值存儲在客戶端。當用戶進行了一些更改並選擇保存文件時,請將該值與新內容一起發送。服務器端,您可以將文件的當前修改日期與用戶發送的值進行比較。如果它們不匹配,則其他用戶在此期間更新了該文件。

相關問題