Skip to content

Commit 0809e83

Browse files
fix(ui): use less brutally strict workflow validation
Workflow building would fail when a current image node was in the workflow due to the strict validation. So we need to use the other workflow builder util first, which strips out extraneous data. This bug was introduced during an attempt to optimize the workflow building logic, which was causing slowdowns on the workflow editor.
1 parent 7269c9f commit 0809e83

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/enqueueRequestedNodes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { enqueueRequested } from 'app/store/actions';
22
import { buildNodesGraph } from 'features/nodes/util/graph/buildNodesGraph';
3-
import { buildWorkflowRight } from 'features/nodes/util/workflow/buildWorkflow';
3+
import { buildWorkflowWithValidation } from 'features/nodes/util/workflow/buildWorkflow';
44
import { queueApi } from 'services/api/endpoints/queue';
55
import type { BatchConfig } from 'services/api/types';
66

@@ -15,7 +15,7 @@ export const addEnqueueRequestedNodes = () => {
1515
const { nodes, edges } = state.nodes;
1616
const workflow = state.workflow;
1717
const graph = buildNodesGraph(state.nodes);
18-
const builtWorkflow = buildWorkflowRight({
18+
const builtWorkflow = buildWorkflowWithValidation({
1919
nodes,
2020
edges,
2121
workflow,

invokeai/frontend/web/src/features/nodes/store/workflowSlice.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import {
99
} from 'features/nodes/store/nodesSlice';
1010
import type { WorkflowsState as WorkflowState } from 'features/nodes/store/types';
1111
import type { FieldIdentifier } from 'features/nodes/types/field';
12+
import type { WorkflowV2 } from 'features/nodes/types/workflow';
1213
import { cloneDeep, isEqual, uniqBy } from 'lodash-es';
1314

14-
export const initialWorkflowState: WorkflowState = {
15-
_version: 1,
15+
export const blankWorkflow: Omit<WorkflowV2, 'nodes' | 'edges'> = {
1616
name: '',
1717
author: '',
1818
description: '',
@@ -22,7 +22,12 @@ export const initialWorkflowState: WorkflowState = {
2222
notes: '',
2323
exposedFields: [],
2424
meta: { version: '2.0.0', category: 'user' },
25+
};
26+
27+
export const initialWorkflowState: WorkflowState = {
28+
_version: 1,
2529
isTouched: true,
30+
...blankWorkflow,
2631
};
2732

2833
const workflowSlice = createSlice({

invokeai/frontend/web/src/features/nodes/util/workflow/buildWorkflow.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import { logger } from 'app/logging/logger';
22
import { parseify } from 'common/util/serialize';
33
import type { NodesState, WorkflowsState } from 'features/nodes/store/types';
44
import { isInvocationNode, isNotesNode } from 'features/nodes/types/invocation';
5-
import { type WorkflowV2, zWorkflowV2 } from 'features/nodes/types/workflow';
5+
import type { WorkflowV2 } from 'features/nodes/types/workflow';
6+
import { zWorkflowV2 } from 'features/nodes/types/workflow';
67
import i18n from 'i18n';
7-
import { cloneDeep, omit } from 'lodash-es';
8+
import { cloneDeep, pick } from 'lodash-es';
89
import { fromZodError } from 'zod-validation-error';
910

1011
export type BuildWorkflowArg = {
@@ -13,14 +14,26 @@ export type BuildWorkflowArg = {
1314
workflow: WorkflowsState;
1415
};
1516

17+
const workflowKeys = [
18+
'name',
19+
'author',
20+
'description',
21+
'version',
22+
'contact',
23+
'tags',
24+
'notes',
25+
'exposedFields',
26+
'meta',
27+
] satisfies (keyof WorkflowV2)[];
28+
1629
export type BuildWorkflowFunction = (arg: BuildWorkflowArg) => WorkflowV2;
1730

1831
export const buildWorkflowFast: BuildWorkflowFunction = ({
1932
nodes,
2033
edges,
2134
workflow,
2235
}: BuildWorkflowArg): WorkflowV2 => {
23-
const clonedWorkflow = omit(cloneDeep(workflow), 'isTouched');
36+
const clonedWorkflow = pick(cloneDeep(workflow), workflowKeys);
2437

2538
const newWorkflow: WorkflowV2 = {
2639
...clonedWorkflow,
@@ -73,25 +86,23 @@ export const buildWorkflowFast: BuildWorkflowFunction = ({
7386
return newWorkflow;
7487
};
7588

76-
export const buildWorkflowRight = ({
89+
export const buildWorkflowWithValidation = ({
7790
nodes,
7891
edges,
7992
workflow,
8093
}: BuildWorkflowArg): WorkflowV2 | null => {
81-
const newWorkflowUnsafe = {
82-
...workflow,
83-
nodes,
84-
edges,
85-
};
94+
// builds what really, really should be a valid workflow
95+
const workflowToValidate = buildWorkflowFast({ nodes, edges, workflow });
8696

87-
const result = zWorkflowV2.safeParse(newWorkflowUnsafe);
97+
// but bc we are storing this in the DB, let's be extra sure
98+
const result = zWorkflowV2.safeParse(workflowToValidate);
8899

89100
if (!result.success) {
90101
const { message } = fromZodError(result.error, {
91-
prefix: i18n.t('nodes.unableToParseNode'),
102+
prefix: i18n.t('nodes.unableToValidateWorkflow'),
92103
});
93104

94-
logger('nodes').warn({ workflow: parseify(newWorkflowUnsafe) }, message);
105+
logger('nodes').warn({ workflow: parseify(workflowToValidate) }, message);
95106
return null;
96107
}
97108

0 commit comments

Comments
 (0)