mirror of
https://github.com/langgenius/dify.git
synced 2026-04-15 09:57:03 +08:00
fix(collaboration): seed CRDT graph before leader resync
Avoid writing partial graph into CRDT during initial HTTP draft parsing in workflow-app. Seed CRDT from current ReactFlow graph only when CRDT is empty and collaboration is connected, then reuse it for leader snapshot rebroadcast. This prevents join-time resync from broadcasting an empty snapshot when leader has not produced local CRDT mutations yet.
This commit is contained in:
parent
a29e831ce5
commit
828276d672
@ -10,7 +10,6 @@ import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { FeaturesProvider } from '@/app/components/base/features'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import WorkflowWithDefaultContext from '@/app/components/workflow'
|
||||
import { collaborationManager } from '@/app/components/workflow/collaboration/core/collaboration-manager'
|
||||
import {
|
||||
WorkflowContextProvider,
|
||||
} from '@/app/components/workflow/context'
|
||||
@ -81,7 +80,6 @@ const WorkflowAppWithAdditionalContext = () => {
|
||||
const nodesData = useMemo(() => {
|
||||
if (data) {
|
||||
const processedNodes = initialNodes(data.graph.nodes, data.graph.edges)
|
||||
collaborationManager.setNodes([], processedNodes)
|
||||
return processedNodes
|
||||
}
|
||||
return []
|
||||
@ -90,7 +88,6 @@ const WorkflowAppWithAdditionalContext = () => {
|
||||
const edgesData = useMemo(() => {
|
||||
if (data) {
|
||||
const processedEdges = initialEdges(data.graph.edges, data.graph.nodes)
|
||||
collaborationManager.setEdges([], processedEdges)
|
||||
return processedEdges
|
||||
}
|
||||
return []
|
||||
|
||||
@ -1538,10 +1538,13 @@ export class CollaborationManager {
|
||||
const wasLeader = this.isLeader
|
||||
this.isLeader = data.isLeader
|
||||
|
||||
if (this.isLeader)
|
||||
if (this.isLeader) {
|
||||
this.seedCrdtGraphFromReactFlowIfNeeded()
|
||||
this.pendingInitialSync = false
|
||||
else
|
||||
}
|
||||
else {
|
||||
this.requestInitialSyncIfNeeded()
|
||||
}
|
||||
|
||||
if (wasLeader !== this.isLeader)
|
||||
this.eventEmitter.emit('leaderChange', this.isLeader)
|
||||
@ -1603,6 +1606,30 @@ export class CollaborationManager {
|
||||
})
|
||||
}
|
||||
|
||||
private seedCrdtGraphFromReactFlowIfNeeded(): void {
|
||||
if (!this.doc)
|
||||
return
|
||||
if (!this.reactFlowStore)
|
||||
return
|
||||
|
||||
// CRDT may still be empty when the canvas was initially loaded from HTTP draft data
|
||||
// before collaboration finished connecting, and no local mutation has been written yet.
|
||||
// Seed once from the current ReactFlow graph so leader resync can broadcast a full snapshot.
|
||||
if (this.getNodes().length > 0 || this.getEdges().length > 0)
|
||||
return
|
||||
|
||||
const state = this.reactFlowStore.getState()
|
||||
const nodes = state.getNodes()
|
||||
const edges = state.getEdges()
|
||||
|
||||
if (!nodes.length && !edges.length)
|
||||
return
|
||||
|
||||
this.syncNodes([], nodes)
|
||||
this.syncEdges([], edges)
|
||||
this.doc.commit()
|
||||
}
|
||||
|
||||
private broadcastCurrentGraph(): void {
|
||||
if (!this.currentAppId || !webSocketClient.isConnected(this.currentAppId))
|
||||
return
|
||||
@ -1614,6 +1641,8 @@ export class CollaborationManager {
|
||||
return
|
||||
|
||||
try {
|
||||
this.seedCrdtGraphFromReactFlowIfNeeded()
|
||||
|
||||
if (this.getNodes().length === 0 && this.getEdges().length === 0)
|
||||
return
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user