Skip to content

Commit

Permalink
Bootstrap docs for the current state of the Real-Time collaboration e…
Browse files Browse the repository at this point in the history
…xperiment (#54932)
  • Loading branch information
oandregal authored Oct 3, 2023
1 parent 23b3033 commit 140d04e
Showing 1 changed file with 54 additions and 0 deletions.
54 changes: 54 additions & 0 deletions packages/sync/CODE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Status of the sync experiment in Gutenberg

The sync package is part of an ongoing research effort to lay the groundwork of Real-Time Collaboration in Gutenberg.

Relevant docs:

- https://make.wordpress.org/core/2023/07/13/real-time-collaboration-architecture/
- https://github.com/WordPress/gutenberg/issues/52593
- https://docs.yjs.dev/

## Enable the experiment

The experiment can be enabled in the "Guteberg > Experiments" page. When it is enabled (search for `gutenberg-sync-collaboration` in the codebase), the client receives two new pieces of data:

- `window.__experimentalEnableSync`: boolean. Used by the `core-data` package to determine whether to bootstrap and use the sync provider offered by the `sync` package.
- `window.__experimentalCollaborativeEditingSecret`: string. A secret used by the `sync` package to create a secure connection among peers.

## The data flow

The current experiment updates `core-data` to leverage the YJS library for synchronization and merging changes. Each core-data entity record represents a YJS document and updates to the `--edit` record are broadcasted among peers.

These are the specific checkpoints:

1. REGISTER.
- See `getSyncProvider().register( ... )` in `registerSyncConfigs`.
- Not all entity types are sync-enabled at the moment, look at those that declare a `syncConfig` and `syncObjectType` in `rootEntitiesConfig`.
2. BOOTSTRAP.
- See `getSyncProvider().bootstrap( ... )` in `getEntityRecord`.
- The `bootstrap` function fetches the entity and sets up the callback that will dispatch the relevant Redux action when document changes are broadcasted from other peers.
3. UPDATE.
- See `getSyncProvider().update( ... )` in `editEntityRecord`.
- Each change done by a peer to the `--edit` entity record (local changes, not persisted ones) is broadcasted to the others.
- The data that is shared is the whole block list.

This is the data flow when the peer A makes a local change:

- Peer A makes a local change.
- Peer A triggers a `getSyncProvider().update( ... )` request (see `editEntityRecord`).
- All peers (including A) receive the broadcasted change and execute the callback (see `updateHandler` in `createSyncProvider.bootstrap`).
- All peers (including A) trigger a `EDIT_ENTITY_RECORD` redux action.

## What works and what doesn't

- Undo/redo does not work.
- Changes can be persisted and the publish/update button should react accordingly for all peers.
- Offline.
- Changes are stored in the browser's local storage (indexedDB) for each user/peer. Users can navigate away from the document and they'll see the changes when they come back.
- Offline changes can be deleted via visiting the browser's database in all peers, then reload the document.
- Documents can get out of sync. For example:
- Two peers open the same document.
- One of them (A) leaves the document. Then, the remaining user (B) makes changes.
- When A comes back to the document, the changes B made are not visible to A.
- Entities
- Not all entities are synced. For example, global styles are not. Look at the `base` entity config for an example (it declares `syncConfig` and `syncObjectType` properties).

0 comments on commit 140d04e

Please sign in to comment.