From ec053d81265bce9a077c9536a00ebb37e3fcdb21 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Sat, 24 Jan 2026 18:46:59 -0300 Subject: [PATCH] fix: stop state ping-pong by removing broadcastStateRefresh from auto-persist The CRDT auto-persist was broadcasting state-refresh after each save, causing other clients to fetch from DB and overwrite their local variables/characters with stale values. Since CRDT already syncs nodes/edges via yjs-update broadcasts, the state-refresh from auto-persist was redundant and destructive. Manual save still broadcasts state-refresh as intended. Co-Authored-By: Claude Opus 4.5 --- src/app/editor/[projectId]/FlowchartEditor.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app/editor/[projectId]/FlowchartEditor.tsx b/src/app/editor/[projectId]/FlowchartEditor.tsx index 325dd07..2e20982 100644 --- a/src/app/editor/[projectId]/FlowchartEditor.tsx +++ b/src/app/editor/[projectId]/FlowchartEditor.tsx @@ -566,6 +566,11 @@ function FlowchartEditorInner({ projectId, projectName, userId, userDisplayName, }, onPersist: async (persistNodes: FlowchartNode[], persistEdges: FlowchartEdge[]) => { try { + // Auto-persist saves the current state for durability. We do NOT + // broadcast state-refresh here because CRDT already syncs nodes/edges + // via yjs-update broadcasts. Broadcasting here causes ping-pong: + // other clients fetch from DB, overwrite their local variables/characters, + // then their persist writes stale data back, causing a loop. await supabase .from('projects') .update({ @@ -577,8 +582,6 @@ function FlowchartEditorInner({ projectId, projectName, userId, userDisplayName, }, }) .eq('id', projectId) - // Notify other clients to refresh after successful auto-persist - realtimeRef.current?.broadcastStateRefresh() } catch { // Persistence failure is non-critical; will retry on next change }