Просмотр исходного кода

refactor: optimize diff check and awareness state handling in collaborative editor

Yuki Takei 2 недель назад
Родитель
Сommit
91d7a450f5

+ 11 - 10
apps/app/src/server/service/yjs/create-mongodb-persistence.ts

@@ -42,12 +42,7 @@ export const createMongoDBPersistence = (
       const diff = Y.encodeStateAsUpdate(ydoc, persistedStateVector);
 
       // store the new data in db (if there is any: empty update is an array of 0s)
-      if (
-        diff.reduce(
-          (previousValue, currentValue) => previousValue + currentValue,
-          0,
-        ) > 0
-      ) {
+      if (diff.some((b) => b !== 0)) {
         mdb.storeUpdate(docName, diff);
         mdb.setTypedMeta(docName, 'updatedAt', Date.now());
       }
@@ -69,14 +64,20 @@ export const createMongoDBPersistence = (
       });
 
       // register awareness event bridge to Socket.IO rooms
+      // Only emit when the awareness state size actually changes (cursor moves
+      // and other updates fire frequently but don't change the user count)
+      let lastEmittedSize = -1;
       ydoc.awareness.on('update', async () => {
         const pageId = docName;
         const awarenessStateSize = ydoc.awareness.getStates().size;
 
-        io.in(getRoomNameWithId(RoomPrefix.PAGE, pageId)).emit(
-          SocketEventName.YjsAwarenessStateSizeUpdated,
-          awarenessStateSize,
-        );
+        if (awarenessStateSize !== lastEmittedSize) {
+          lastEmittedSize = awarenessStateSize;
+          io.in(getRoomNameWithId(RoomPrefix.PAGE, pageId)).emit(
+            SocketEventName.YjsAwarenessStateSizeUpdated,
+            awarenessStateSize,
+          );
+        }
 
         // emit draft status when last user leaves
         if (awarenessStateSize === 0) {

+ 4 - 4
packages/editor/src/client/stores/use-collaborative-editor-mode.ts

@@ -94,14 +94,14 @@ export const useCollaborativeEditorMode = (
         removed: number[];
       }) => {
         // remove the states of disconnected clients
-        update.removed.forEach((clientId) => {
-          awareness.states.delete(clientId);
-        });
+        for (const clientId of update.removed) {
+          awareness.getStates().delete(clientId);
+        }
 
         // update editor list
         if (onEditorsUpdated != null) {
           const clientList: EditingClient[] = Array.from(
-            awareness.states.values(),
+            awareness.getStates().values(),
             (value) => value.editors,
           );
           if (Array.isArray(clientList)) {