前端系統設計 - 設計即時共編文件系統 (Collaborative Editor)

2024年3月28日

💎 加入 E+ 成長計畫 與超過 350+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

本篇詳細解說本收錄在 E+ 的前端系統設計專題

前一篇 前端系統設計 - 設計聊天系統 (Chat System) 中,我們談了聊天系統。在這一篇,我們將來討論雲端共編文件。

大家可以把即時共編文件理解成一個協作的編輯器 (collaborative editor),如果抽象化來思考,各類的雲端共編文件,不論是常見的 Google Doc、Notion,或者是 VS Code 之前推出的共編 Live Share 功能,甚至是設計工具 Figma,其實概念都是一樣,需要支援多人同時針對某個編輯器進行操作。

當然因為具體支援的功能很不同,在設計的細節上也會有所不同。舉例來說,Notion 會需要支援各類的資料庫,但是 Figma 則是需要支援各類的媒體類別。因此,最開始的問題釐清仍是最重要的。

這邊列出推薦在最開始可以詢問的釐清問題:

  • 這個系統的目標用戶是誰? 上面提的 Google Doc、Notion、Figma 等,目標族群很不同,都是即時共編系統,但設計上會有差異
  • 最基本的功能涵蓋什麼? 除了文件編輯與閱覽外,需要有歷史記錄、版本控制嗎?
  • 文件是純文字的嗎? 還是要支援不同多媒體? 例如圖片、語音、影片等
  • 有預期在多使用者同時編輯同一段落時,要如何處理衝突嗎?
  • 要支援離線 (offline) 功能嗎? 如果要的話,是閱讀與編輯都支援嗎?

除了上面這些,還有細部可以問的,包含:

  • 要有通知的功能嗎?
  • 需要有評論或註解的功能嗎?
  • 需要有文字的游標表示嗎? 例如許多即時共編文件,會顯示誰正在編輯哪一段落

即時共編文件的本質

即時共編文件,是當你打了某個新的內容時,在其他裝置的使用者的文件中,也會出現該新增的內容。同樣地,如果你做了修改或刪除,其他裝置的使用者文件中的該內容,也會被及時修改與刪除。

從架構的角度來看

如前一段提到,從架構的角度來看,即時共編文件,與即時聊天的性質非常相似。具體來說,也會有個客戶端的存儲,以及客戶端的控制器來處理同步的問題。客戶端的 UI 會是以跟客戶端存儲同步為主,而由客戶端控制器來處理客戶端存儲與伺服器端的同步。

以 Notion 來說,當今天輸入內容到文件中,客戶端會呼叫 /saveTransactions 的 API,但在 API 回傳成功之前,Notion 就已經會把內容更新到畫面上,達到低延遲感的使用體驗。這時畫面顯示的資料,就會是跟客戶端存儲同步的。

這邊的 /saveTransactions 中的 transaction 就是每一個在 Notion 文件的操作 (與對資料庫操作的交易概念類似)。而如果今天輸入內容到一半斷線, /saveTransactions 傳送失敗,這時會需要有一個重新嘗試 (retry) 的機制 ,以 Notion 為例,會是每隔幾秒重新打 /saveTransactions API 來嘗試。

與聊天系統相似的,是文件系統也會有短時間同時輸入許多內容,因此需要有機制來確保不會每打一個字,就呼叫 API 來與後端同步。在這部分,可以用防抖 (debounce) 來實踐即可。換句話說,當在連續輸入時,不會馬上呼叫 /saveTransactions API,而是當打字有停下時,才會觸發 /saveTransactions

同樣與聊天系統相似,即時共編文件系統也會透過一個佇列 (queue) 來做控管。Notion 的官方部落格是這樣描述,當呼叫新增內容到文件後「這筆交易會被儲存到 TransactionQueue 當中,TransactionQueue 負責將所有交易發送至 Notion 的伺服器,藉此保存你的資料並與協作者分享。 the transaction is saved into TransactionQueue, the part of the client responsible for sending all transactions to Notion’s servers so your data is persisted and shared with collaborators. 」

本文為 E+ 成長計畫的深度內容,截取前三分之一開放免費閱讀。歡迎加入 E+ 成長計畫閱讀完整版本 (點此了解 E+ 的詳細介紹)

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們