Skip to content

Commit 062e2a2

Browse files
fix(deployed-state): use deployed state for API sync and async execs, deployed state modal visual for enabled/disabled (#885)
* fix(deployments): use deployed state for API sync and async execs * fix deployed workflow modal visualization for enabled * fix tests
1 parent 746b877 commit 062e2a2

File tree

5 files changed

+65
-34
lines changed

5 files changed

+65
-34
lines changed

apps/sim/app/api/workflows/[id]/execute/route.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ describe('Workflow Execution API Route', () => {
8787
}))
8888

8989
vi.doMock('@/lib/workflows/db-helpers', () => ({
90-
loadWorkflowFromNormalizedTables: vi.fn().mockResolvedValue({
90+
loadDeployedWorkflowState: vi.fn().mockResolvedValue({
9191
blocks: {
9292
'starter-id': {
9393
id: 'starter-id',
@@ -121,7 +121,7 @@ describe('Workflow Execution API Route', () => {
121121
],
122122
loops: {},
123123
parallels: {},
124-
isFromNormalizedTables: true,
124+
isFromNormalizedTables: false, // Changed to false since it's from deployed state
125125
}),
126126
}))
127127

@@ -516,7 +516,7 @@ describe('Workflow Execution API Route', () => {
516516
}))
517517

518518
vi.doMock('@/lib/workflows/db-helpers', () => ({
519-
loadWorkflowFromNormalizedTables: vi.fn().mockResolvedValue({
519+
loadDeployedWorkflowState: vi.fn().mockResolvedValue({
520520
blocks: {
521521
'starter-id': {
522522
id: 'starter-id',
@@ -550,7 +550,7 @@ describe('Workflow Execution API Route', () => {
550550
],
551551
loops: {},
552552
parallels: {},
553-
isFromNormalizedTables: true,
553+
isFromNormalizedTables: false, // Changed to false since it's from deployed state
554554
}),
555555
}))
556556

apps/sim/app/api/workflows/[id]/execute/route.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { createLogger } from '@/lib/logs/console/logger'
99
import { LoggingSession } from '@/lib/logs/execution/logging-session'
1010
import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans'
1111
import { decryptSecret } from '@/lib/utils'
12-
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/db-helpers'
12+
import { loadDeployedWorkflowState } from '@/lib/workflows/db-helpers'
1313
import {
1414
createHttpResponseFromBlock,
1515
updateWorkflowRunCounts,
@@ -111,20 +111,13 @@ async function executeWorkflow(workflow: any, requestId: string, input?: any): P
111111
runningExecutions.add(executionKey)
112112
logger.info(`[${requestId}] Starting workflow execution: ${workflowId}`)
113113

114-
// Load workflow data from normalized tables
115-
logger.debug(`[${requestId}] Loading workflow ${workflowId} from normalized tables`)
116-
const normalizedData = await loadWorkflowFromNormalizedTables(workflowId)
114+
// Load workflow data from deployed state for API executions
115+
const deployedData = await loadDeployedWorkflowState(workflowId)
117116

118-
if (!normalizedData) {
119-
throw new Error(
120-
`Workflow ${workflowId} has no normalized data available. Ensure the workflow is properly saved to normalized tables.`
121-
)
122-
}
123-
124-
// Use normalized data as primary source
125-
const { blocks, edges, loops, parallels } = normalizedData
126-
logger.info(`[${requestId}] Using normalized tables for workflow execution: ${workflowId}`)
127-
logger.debug(`[${requestId}] Normalized data loaded:`, {
117+
// Use deployed data as primary source for API executions
118+
const { blocks, edges, loops, parallels } = deployedData
119+
logger.info(`[${requestId}] Using deployed state for workflow execution: ${workflowId}`)
120+
logger.debug(`[${requestId}] Deployed data loaded:`, {
128121
blocksCount: Object.keys(blocks || {}).length,
129122
edgesCount: (edges || []).length,
130123
loopsCount: Object.keys(loops || {}).length,

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ export function WorkflowBlock({ id, data }: NodeProps<WorkflowBlockProps>) {
7070
const currentWorkflow = useCurrentWorkflow()
7171
const currentBlock = currentWorkflow.getBlockById(id)
7272

73-
const isEnabled = currentBlock?.enabled ?? true
73+
// In preview mode, use the blockState provided; otherwise use current workflow state
74+
const isEnabled = data.isPreview
75+
? (data.blockState?.enabled ?? true)
76+
: (currentBlock?.enabled ?? true)
7477

7578
// Get diff status from the block itself (set by diff engine)
7679
const diffStatus =

apps/sim/lib/workflows/db-helpers.ts

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { eq } from 'drizzle-orm'
22
import { createLogger } from '@/lib/logs/console/logger'
33
import { db } from '@/db'
4-
import { workflowBlocks, workflowEdges, workflowSubflows } from '@/db/schema'
5-
import type { LoopConfig, WorkflowState } from '@/stores/workflows/workflow/types'
4+
import { workflow, workflowBlocks, workflowEdges, workflowSubflows } from '@/db/schema'
5+
import type { WorkflowState } from '@/stores/workflows/workflow/types'
66
import { SUBFLOW_TYPES } from '@/stores/workflows/workflow/types'
77

88
const logger = createLogger('WorkflowDBHelpers')
@@ -12,7 +12,49 @@ export interface NormalizedWorkflowData {
1212
edges: any[]
1313
loops: Record<string, any>
1414
parallels: Record<string, any>
15-
isFromNormalizedTables: true // Flag to indicate this came from new tables
15+
isFromNormalizedTables: boolean // Flag to indicate source (true = normalized tables, false = deployed state)
16+
}
17+
18+
/**
19+
* Load deployed workflow state for execution
20+
* Returns deployed state if available, otherwise throws error
21+
*/
22+
export async function loadDeployedWorkflowState(
23+
workflowId: string
24+
): Promise<NormalizedWorkflowData> {
25+
try {
26+
// First check if workflow is deployed and get deployed state
27+
const [workflowResult] = await db
28+
.select({
29+
isDeployed: workflow.isDeployed,
30+
deployedState: workflow.deployedState,
31+
})
32+
.from(workflow)
33+
.where(eq(workflow.id, workflowId))
34+
.limit(1)
35+
36+
if (!workflowResult) {
37+
throw new Error(`Workflow ${workflowId} not found`)
38+
}
39+
40+
if (!workflowResult.isDeployed || !workflowResult.deployedState) {
41+
throw new Error(`Workflow ${workflowId} is not deployed or has no deployed state`)
42+
}
43+
44+
const deployedState = workflowResult.deployedState as any
45+
46+
// Convert deployed state to normalized format
47+
return {
48+
blocks: deployedState.blocks || {},
49+
edges: deployedState.edges || [],
50+
loops: deployedState.loops || {},
51+
parallels: deployedState.parallels || {},
52+
isFromNormalizedTables: false, // Flag to indicate this came from deployed state
53+
}
54+
} catch (error) {
55+
logger.error(`Error loading deployed workflow state ${workflowId}:`, error)
56+
throw error
57+
}
1658
}
1759

1860
/**
@@ -88,7 +130,6 @@ export async function loadWorkflowFromNormalizedTables(
88130
const config = subflow.config || {}
89131

90132
if (subflow.type === SUBFLOW_TYPES.LOOP) {
91-
const loopConfig = config as LoopConfig
92133
loops[subflow.id] = {
93134
id: subflow.id,
94135
...config,
@@ -126,7 +167,7 @@ export async function saveWorkflowToNormalizedTables(
126167
): Promise<{ success: boolean; jsonBlob?: any; error?: string }> {
127168
try {
128169
// Start a transaction
129-
const result = await db.transaction(async (tx) => {
170+
await db.transaction(async (tx) => {
130171
// Clear existing data for this workflow
131172
await Promise.all([
132173
tx.delete(workflowBlocks).where(eq(workflowBlocks.workflowId, workflowId)),

apps/sim/trigger/workflow-execution.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { createLogger } from '@/lib/logs/console/logger'
66
import { LoggingSession } from '@/lib/logs/execution/logging-session'
77
import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans'
88
import { decryptSecret } from '@/lib/utils'
9-
import { loadWorkflowFromNormalizedTables } from '@/lib/workflows/db-helpers'
9+
import { loadDeployedWorkflowState } from '@/lib/workflows/db-helpers'
1010
import { updateWorkflowRunCounts } from '@/lib/workflows/utils'
1111
import { db } from '@/db'
1212
import { environment as environmentTable, userStats } from '@/db/schema'
@@ -60,16 +60,10 @@ export const workflowExecution = task({
6060
)
6161
}
6262

63-
// Load workflow data from normalized tables
64-
const normalizedData = await loadWorkflowFromNormalizedTables(workflowId)
65-
if (!normalizedData) {
66-
logger.error(`[${requestId}] Workflow not found in normalized tables: ${workflowId}`)
67-
throw new Error(`Workflow ${workflowId} data not found in normalized tables`)
68-
}
69-
70-
logger.info(`[${requestId}] Workflow loaded successfully: ${workflowId}`)
63+
// Load workflow data from deployed state (this task is only used for API executions right now)
64+
const workflowData = await loadDeployedWorkflowState(workflowId)
7165

72-
const { blocks, edges, loops, parallels } = normalizedData
66+
const { blocks, edges, loops, parallels } = workflowData
7367

7468
// Merge subblock states (server-safe version doesn't need workflowId)
7569
const mergedStates = mergeSubblockState(blocks, {})

0 commit comments

Comments
 (0)