Why a collaborative editor?

A sensible question to ask is: Why even build a collaborative editor in the first place?

Having used Google Docs quite a bit as a team, we had always been intrigued by how it worked under-the-hood. Ironically, Googling how Google Docs works is fruitless. They are quite secretive about their proprietary software.

In the end we decided that, if Google would not tell us, the next best way to learn was to build it ourselves.

Interesting Software Engineering Challenges

Besides being a creative way to learn how Google Docs works, creating a real time, collaborative text editor poses some interesting software engineering challenges:

Maintaining consistency across all users while merging conflicting operations. Reducing latency as much as possible to achieve a real time effect. Scaling a real time application.

Let us go over each of these challenges in detail.

Challenge 1: Maintaining Consistency / Merging Conflicting Operations

The most important part of a collaborative editor is guaranteeing consistency across all users. After all, if the document did not stay consistent, it would be useless.

But how is this achieved?

To answer that, it is important to understand exactly what a text editor is and how it works.

What is a text editor?

For our project, we defined a text editor as a space where you can insert or delete text characters. Each character has a value and a numerical index that determines its position in the document.

For example, with the text “HAT”, the first character has a value “H” and a position of 0, “A” has position 1, and “T” has position 2.

A character can be inserted or deleted based on its positional index. To insert a “C” at the beginning of the text, the operation is insert("C", 0) . This insertion causes all the other letters to shift their position to the right by 1.

To delete the “H” would require the operation delete(1) .

One user editing a document is simple, but what if we want multiple users simultaneously editing the same document?

Multiple concurrent users

First, we will need to provide each user with a local copy of the document and allow them to make edits. Remember, we are aiming for “real-time”. We want users to be able to apply their edits immediately as if they were using a simple text editor.

Next, we need a way for users to inform other users of edits they made. We will introduce a Central Relay Server to facilitate this communication.

Two users connected through a central relay server.

The problem with this situation comes when users attempt to make concurrent edits.

Commutativity

As an example, say there are two users who both start with the word “HAT”. One user inserts a “C” while the other deletes the “H” and both of their edits are sent to the other person to be incorporated.

Oh no! One user has a “HAT” and the other user has a “CAT”. Their documents did not converge to the same state.

The reason for this divergence is because the insert and delete operations did not commute.

Commutativity occurs when different operations produce the same result no matter the order in which they are applied. Addition and multiplication are all commutative operations.

Idempotency

Let us try another example where the users simultaneously decide they want to delete the “H” from “HAT” to get “AT”.

The documents did converge but we have another problem! Both users ended up with “T” instead of “AT”. Neither of them wanted this result. This occurred because the delete operations are not idempotent.

Idempotency is when repeated operations produce the same result. For example, multiplying by 1 is an idempotent operation. No matter how many times you multiply a number by 1, the result is the same.

Consistency Requirements

Looking at the previous two example, we can see that a collaborative text editor must have the follow properties to remain consistent across all users:

Commutativity : Concurrent insert and delete operations converge to the same result regardless of the order in which they are applied.

: Concurrent insert and delete operations converge to the same result regardless of the order in which they are applied. Idempotency: Repeated delete operations produce the same result.

With the problem identified, how do we go about solving it? For our team, this required plenty of researching before we came upon two possible solutions.