Compare commits

...

1 Commits

Author SHA1 Message Date
CodeRabbit Fixer
0f763b523d fix: refactor: Rearchitect workflow/graph data sync to prevent desynced state during loading (#9533)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:41:39 +01:00
4 changed files with 124 additions and 134 deletions

View File

@@ -379,6 +379,13 @@ export const useWorkflowService = () => {
void workflowThumbnail.storeThumbnail(activeWorkflow)
domWidgetStore.clear()
}
// Deactivate the current workflow before the graph is reconfigured.
// This ensures there is never a window where activeWorkflow references
// the OLD workflow while rootGraph already contains NEW data — any
// checkState or data-sync path that reads activeWorkflow will see null
// and naturally skip, without needing a guard flag.
workflowStore.activeWorkflow = null
}
/**

View File

@@ -9,7 +9,6 @@ import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
import { flushScheduledSlotLayoutSync } from '@/renderer/extensions/vueNodes/composables/useSlotElementTracking'
import { st, t } from '@/i18n'
import { ChangeTracker } from '@/scripts/changeTracker'
import type { IContextMenuValue } from '@/lib/litegraph/src/interfaces'
import {
LGraph,
@@ -1307,8 +1306,6 @@ export class ComfyApp {
}
}
ChangeTracker.isLoadingGraph = true
try {
try {
// @ts-expect-error Discrepancies between zod and litegraph - in progress
this.rootGraph.configure(graphData)
@@ -1379,9 +1376,7 @@ export class ComfyApp {
values.length > 0 &&
(widget.value == null ||
(reset_invalid_values &&
!values.includes(
widget.value as string | number | boolean
)))
!values.includes(widget.value as string | number | boolean)))
) {
widget.value = values[0]
}
@@ -1441,9 +1436,6 @@ export class ComfyApp {
requestAnimationFrame(() => {
this.canvas.setDirty(true, true)
})
} finally {
ChangeTracker.isLoadingGraph = false
}
}
async graphToPrompt(graph = this.rootGraph) {

View File

@@ -28,14 +28,6 @@ logger.setLevel('info')
export class ChangeTracker {
static MAX_HISTORY = 50
/**
* Guard flag to prevent checkState from running during loadGraphData.
* Between rootGraph.configure() and afterLoadNewGraph(), the rootGraph
* contains the NEW workflow's data while activeWorkflow still points to
* the OLD workflow. Any checkState call in that window would serialize
* the wrong graph into the old workflow's activeState, corrupting it.
*/
static isLoadingGraph = false
/**
* The active state of the workflow.
*/
@@ -139,7 +131,7 @@ export class ChangeTracker {
}
checkState() {
if (!app.graph || this.changeCount || ChangeTracker.isLoadingGraph) return
if (!app.graph || this.changeCount) return
const currentState = clone(app.rootGraph.serialize()) as ComfyWorkflowJSON
if (!this.activeState) {
this.activeState = currentState

View File

@@ -9,7 +9,6 @@ import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
import { useSidebarTabStore } from '@/stores/workspace/sidebarTabStore'
import { app } from '@/scripts/app'
import { ChangeTracker } from '@/scripts/changeTracker'
import { resolveNode } from '@/utils/litegraphUtil'
export function nodeTypeValidForApp(type: string) {
@@ -82,7 +81,7 @@ export const useAppModeStore = defineStore('appMode', () => {
? { inputs: selectedInputs, outputs: selectedOutputs }
: null,
(data) => {
if (!data || ChangeTracker.isLoadingGraph) return
if (!data || !workflowStore.activeWorkflow) return
const graph = app.rootGraph
if (!graph) return
const extra = (graph.extra ??= {})