Skip to content

Commit f55f6cc

Browse files
committed
Fix lint
1 parent c14c614 commit f55f6cc

File tree

2 files changed

+153
-106
lines changed

2 files changed

+153
-106
lines changed

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

Lines changed: 16 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ import { SSE_HEADERS } from '@/lib/core/utils/sse'
1010
import { markExecutionCancelled } from '@/lib/execution/cancellation'
1111
import { LoggingSession } from '@/lib/logs/execution/logging-session'
1212
import { executeWorkflowCore } from '@/lib/workflows/executor/execution-core'
13-
import { type ExecutionEvent, encodeSSEEvent } from '@/lib/workflows/executor/execution-events'
13+
import { createSSECallbacks } from '@/lib/workflows/executor/execution-events'
1414
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
15-
import type { IterationContext, SerializableExecutionState } from '@/executor/execution/types'
16-
import type { NormalizedBlockOutput } from '@/executor/types'
15+
import type { ExecutionMetadata, SerializableExecutionState } from '@/executor/execution/types'
1716
import { hasExecutionResult } from '@/executor/utils/errors'
1817

1918
const logger = createLogger('ExecuteFromBlockAPI')
@@ -100,16 +99,17 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
10099

101100
const stream = new ReadableStream<Uint8Array>({
102101
async start(controller) {
103-
const sendEvent = (event: ExecutionEvent) => {
104-
if (isStreamClosed) return
105-
try {
106-
controller.enqueue(encodeSSEEvent(event))
107-
} catch {
102+
const { sendEvent, onBlockStart, onBlockComplete, onStream } = createSSECallbacks({
103+
executionId,
104+
workflowId,
105+
controller,
106+
isStreamClosed: () => isStreamClosed,
107+
setStreamClosed: () => {
108108
isStreamClosed = true
109-
}
110-
}
109+
},
110+
})
111111

112-
const snapshot = new ExecutionSnapshot({
112+
const metadata: ExecutionMetadata = {
113113
requestId,
114114
workflowId,
115115
userId,
@@ -119,7 +119,10 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
119119
workflowUserId,
120120
useDraftState: true,
121121
isClientSession: true,
122-
})
122+
startTime: new Date().toISOString(),
123+
}
124+
125+
const snapshot = new ExecutionSnapshot(metadata, {}, {}, {})
123126

124127
try {
125128
const startTime = new Date()
@@ -140,100 +143,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
140143
startBlockId,
141144
sourceSnapshot: sourceSnapshot as SerializableExecutionState,
142145
},
143-
callbacks: {
144-
onBlockStart: async (
145-
blockId: string,
146-
blockName: string,
147-
blockType: string,
148-
iterationContext?: IterationContext
149-
) => {
150-
sendEvent({
151-
type: 'block:started',
152-
timestamp: new Date().toISOString(),
153-
executionId,
154-
workflowId,
155-
data: {
156-
blockId,
157-
blockName,
158-
blockType,
159-
...(iterationContext && {
160-
iterationCurrent: iterationContext.iterationCurrent,
161-
iterationTotal: iterationContext.iterationTotal,
162-
iterationType: iterationContext.iterationType,
163-
}),
164-
},
165-
})
166-
},
167-
onBlockComplete: async (
168-
blockId: string,
169-
blockName: string,
170-
blockType: string,
171-
callbackData: {
172-
input?: unknown
173-
output: NormalizedBlockOutput
174-
executionTime: number
175-
},
176-
iterationContext?: IterationContext
177-
) => {
178-
const hasError = (callbackData.output as any)?.error
179-
sendEvent({
180-
type: hasError ? 'block:error' : 'block:completed',
181-
timestamp: new Date().toISOString(),
182-
executionId,
183-
workflowId,
184-
data: {
185-
blockId,
186-
blockName,
187-
blockType,
188-
input: callbackData.input,
189-
...(hasError
190-
? { error: (callbackData.output as any).error }
191-
: { output: callbackData.output }),
192-
durationMs: callbackData.executionTime || 0,
193-
...(iterationContext && {
194-
iterationCurrent: iterationContext.iterationCurrent,
195-
iterationTotal: iterationContext.iterationTotal,
196-
iterationType: iterationContext.iterationType,
197-
}),
198-
},
199-
})
200-
},
201-
onStream: async (streamingExecution: unknown) => {
202-
const streamingExec = streamingExecution as {
203-
stream: ReadableStream
204-
execution: any
205-
}
206-
const blockId = streamingExec.execution?.blockId
207-
const reader = streamingExec.stream.getReader()
208-
const decoder = new TextDecoder()
209-
210-
try {
211-
while (true) {
212-
const { done, value } = await reader.read()
213-
if (done) break
214-
const chunk = decoder.decode(value, { stream: true })
215-
sendEvent({
216-
type: 'stream:chunk',
217-
timestamp: new Date().toISOString(),
218-
executionId,
219-
workflowId,
220-
data: { blockId, chunk },
221-
})
222-
}
223-
sendEvent({
224-
type: 'stream:done',
225-
timestamp: new Date().toISOString(),
226-
executionId,
227-
workflowId,
228-
data: { blockId },
229-
})
230-
} finally {
231-
try {
232-
reader.releaseLock()
233-
} catch {}
234-
}
235-
},
236-
},
146+
callbacks: { onBlockStart, onBlockComplete, onStream },
237147
})
238148

239149
if (result.status === 'cancelled') {

apps/sim/lib/workflows/executor/execution-events.ts

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,140 @@ export function formatSSEEvent(event: ExecutionEvent): string {
180180
export function encodeSSEEvent(event: ExecutionEvent): Uint8Array {
181181
return new TextEncoder().encode(formatSSEEvent(event))
182182
}
183+
184+
/**
185+
* Options for creating SSE execution callbacks
186+
*/
187+
export interface SSECallbackOptions {
188+
executionId: string
189+
workflowId: string
190+
controller: ReadableStreamDefaultController<Uint8Array>
191+
isStreamClosed: () => boolean
192+
setStreamClosed: () => void
193+
}
194+
195+
/**
196+
* Creates SSE callbacks for workflow execution streaming
197+
*/
198+
export function createSSECallbacks(options: SSECallbackOptions) {
199+
const { executionId, workflowId, controller, isStreamClosed, setStreamClosed } = options
200+
201+
const sendEvent = (event: ExecutionEvent) => {
202+
if (isStreamClosed()) return
203+
try {
204+
controller.enqueue(encodeSSEEvent(event))
205+
} catch {
206+
setStreamClosed()
207+
}
208+
}
209+
210+
const onBlockStart = async (
211+
blockId: string,
212+
blockName: string,
213+
blockType: string,
214+
iterationContext?: { iterationCurrent: number; iterationTotal: number; iterationType: string }
215+
) => {
216+
sendEvent({
217+
type: 'block:started',
218+
timestamp: new Date().toISOString(),
219+
executionId,
220+
workflowId,
221+
data: {
222+
blockId,
223+
blockName,
224+
blockType,
225+
...(iterationContext && {
226+
iterationCurrent: iterationContext.iterationCurrent,
227+
iterationTotal: iterationContext.iterationTotal,
228+
iterationType: iterationContext.iterationType as any,
229+
}),
230+
},
231+
})
232+
}
233+
234+
const onBlockComplete = async (
235+
blockId: string,
236+
blockName: string,
237+
blockType: string,
238+
callbackData: { input?: unknown; output: any; executionTime: number },
239+
iterationContext?: { iterationCurrent: number; iterationTotal: number; iterationType: string }
240+
) => {
241+
const hasError = callbackData.output?.error
242+
const iterationData = iterationContext
243+
? {
244+
iterationCurrent: iterationContext.iterationCurrent,
245+
iterationTotal: iterationContext.iterationTotal,
246+
iterationType: iterationContext.iterationType as any,
247+
}
248+
: {}
249+
250+
if (hasError) {
251+
sendEvent({
252+
type: 'block:error',
253+
timestamp: new Date().toISOString(),
254+
executionId,
255+
workflowId,
256+
data: {
257+
blockId,
258+
blockName,
259+
blockType,
260+
input: callbackData.input,
261+
error: callbackData.output.error,
262+
durationMs: callbackData.executionTime || 0,
263+
...iterationData,
264+
},
265+
})
266+
} else {
267+
sendEvent({
268+
type: 'block:completed',
269+
timestamp: new Date().toISOString(),
270+
executionId,
271+
workflowId,
272+
data: {
273+
blockId,
274+
blockName,
275+
blockType,
276+
input: callbackData.input,
277+
output: callbackData.output,
278+
durationMs: callbackData.executionTime || 0,
279+
...iterationData,
280+
},
281+
})
282+
}
283+
}
284+
285+
const onStream = async (streamingExecution: unknown) => {
286+
const streamingExec = streamingExecution as { stream: ReadableStream; execution: any }
287+
const blockId = streamingExec.execution?.blockId
288+
const reader = streamingExec.stream.getReader()
289+
const decoder = new TextDecoder()
290+
291+
try {
292+
while (true) {
293+
const { done, value } = await reader.read()
294+
if (done) break
295+
const chunk = decoder.decode(value, { stream: true })
296+
sendEvent({
297+
type: 'stream:chunk',
298+
timestamp: new Date().toISOString(),
299+
executionId,
300+
workflowId,
301+
data: { blockId, chunk },
302+
})
303+
}
304+
sendEvent({
305+
type: 'stream:done',
306+
timestamp: new Date().toISOString(),
307+
executionId,
308+
workflowId,
309+
data: { blockId },
310+
})
311+
} finally {
312+
try {
313+
reader.releaseLock()
314+
} catch {}
315+
}
316+
}
317+
318+
return { sendEvent, onBlockStart, onBlockComplete, onStream }
319+
}

0 commit comments

Comments
 (0)