2010-08-20 46 views
5

我正在研究類似於pastebin的東西(是的,它的泛型),但允許多用戶編輯。顯而易見的問題是多個用戶試圖編輯同一個文件。我正在考慮鎖定文件,當一個用戶正在處理它(這不是最好的解決方案,但我不需要太複雜),但爲了防止/警告用戶,我顯然需要一個系統監視每個用戶的編輯會話。使用數據庫和ajax,我想到了兩種解決方案。監控用戶會話以防止編輯衝突

第一種方法是讓編輯頁以任意間隔(例如一分鐘)ping服務器,並且它會更新db中的編輯會話條目。然後下一次腳本請求進行編輯,它會檢查最近的ping,如果最近一次是另一個任意時間,比如說五分鐘,那麼我們假設前一個用戶已經退出,並且可以再次編輯該文件。當然,這種方法的問題是,前一個用戶已經退出的假設只是一個假設。他可能會有片狀的Wi-Fi連接,並且隨着窗戶仍然打開,隨時都會退出十分鐘。

當然,爲了處理這個問題,我們必須讓服務器響應來自之前關閉會話的新請求併發出錯誤,告訴客戶端指出用戶他的會話已經結束,然後通過將它另存爲服務器上的另一個文件並要求用戶手動合併它等等來處理它。不用說,這對最終用戶來說是相當可怕的。

所以我想出了另一種解決方案。當用戶的會話結束時,可能會觸發unload事件,但我無法確定這是否可以可靠地工作。

有沒有人有任何其他更優雅的解決方案來解決這個問題?

回答

6

如果您希望對文件的併發編輯次數較小,您可以將文件的版本號存儲在數據庫中,並且當用戶將文件下載到瀏覽器中時,它們也會獲得版本號。如果版本號匹配,則只允許上傳更改。首先上傳勝利。當檢測到衝突時,您應該發送最新文件和用戶的更改,以便用戶可以手動合併更改。優點是,即使它是同時進行兩個同時編輯的用戶,也可以工作。如果此功能最終被頻繁使用,則可以添加類似diff工具使用的客戶端合併(但在此情況下可能需要保留舊版本)。

2

你可能會選擇「合併」解決方案。使用這種方法,只需在用戶將文檔發佈到服務器時檢查更改。

的基本方法是: 1.用戶A獲取文檔進行編輯,文件的版本爲1 2.用戶B獲得要編輯的文檔中,文檔的版本爲1分 3.用戶B的帖子的一些變化包括基本版本號碼爲 4.服務器更新文檔,文檔現在在版本2 5.用戶B發佈一些更改,包括基本版本號碼1 6.服務器響應說文檔已經改變,因爲用戶開始編輯,並向用戶發送新文檔,然後他們的版本 - 用戶需要將其更改合併到文檔版本2中,然後發回服務器。用戶基本上現在正在編輯的文檔版本2級 7.用戶A的職位的一些變化,包括版本號2 8.服務器的更新文檔,這是現在的版本爲3

你仍然可以做一個「平」每分鐘,以獲得當前版本號 - 您已經知道他們正在編輯哪個版本,所以如果有新版本可用,您可以讓他們知道並讓他們下載最新版本以進行更改。

這種方法的主要好處是用戶永遠不會鎖定文件,所以您不需要任何「超時」任意的。

+0

這是一個很好的答案,但它確實不是我想要的:協作編輯部分對於共享部分來說確實很小,對不起,如果我沒有說清楚。採用這種解決方案會使事情變得更復雜 - 對於簡單的文本/代碼共享應用來說太複雜了。考慮到這裏用戶交互的複雜性,我需要考慮的邊緣情況的數量是......完全不可能的。還是很好的回答,當我等待下一個答案的時候,給了我一些思考。 – 2010-08-23 10:40:08

0

我會說你是在正確的軌道上。我可能會實現一個混合的解決方案:

有一個名爲「active_edits」或類似的文件_id,用戶和last_update_time列的表。假設你的ping時間是1分鐘,你的超時時間是5分鐘。因此,用例如下所示:

Bob打開一個文檔。它檢查last_update_time。如果超過5分鐘,用Bob和當前時間更新表格。如果不是,其他人正在處理文檔,請提供錯誤消息。假設它沒有被編輯,鮑勃在文檔上工作了一段時間,客戶每分鐘更新一次。

我想說包括「完成編輯」按鈕和onunload的處理程序。 Onunload,從我的理解可以是片狀,但不妨添加它。這兩種方式都會向服務器發送一封只發送郵件,表示Bob已完成。即使鮑勃沒有完成「完成編輯」並且無法播放,最糟糕的情況是,另一個用戶將不得不等待5分鐘才能編輯。好處是,如果這些正常工作(一個公平的假設),那麼系統運行得更好一些。

在這種情況下,你描述了鮑勃在一個糟糕的無線連接或休息一下:我會說這不是什麼大不了的事情。您的ping功能應該確保文檔在Bob上次ping之後沒有被其他人接管。如果有,請給Bob一條消息,說明「別人已經開始處理文檔」並給他們重新加載的選項。

編輯:另外,我會看着window.onbeforeunload,而不是onunload。我相信它會更早執行。我相信這是功能網站(包括slashdot)用來讓你確認你確實想離開這個頁面。我認爲它適用於除Opera之外的主流瀏覽器。

0

至於這個SO問題How do you manage concurrent access to forms?,我不會嘗試實施悲觀鎖定。在無狀態的環境中工作可靠性太困難了。相反,我會使用樂觀鎖定。但是,在這種情況下,我使用了文件的SHA哈希值來確定文件是否從用戶上次從文件中讀取後發生了更改。對於每次更改文件的請求,您都會運行文件字節的SHA散列,並將其與您在第一次讀取數據時所拉取的版本進行比較。如果發生了變化,您會拒絕更改並強制用戶再次進行編輯(拉取文件內容的全新副本),或者提供更有效的衝突解決方案。