diff --git a/cli/src/commands/flow/flow.ts b/cli/src/commands/flow/flow.ts index 2ddaaa36c7..5de3dba4d4 100644 --- a/cli/src/commands/flow/flow.ts +++ b/cli/src/commands/flow/flow.ts @@ -15,7 +15,7 @@ import { buildFolderPath, getMetadataFileName, loadNonDottedPathsSetting } from import { requireLogin } from "../../core/auth.ts"; import { resolveWorkspace, validatePath } from "../../core/context.ts"; -import { resolve, track_job } from "../script/script.ts"; +import { resolve, track_job, pollForJobResult } from "../script/script.ts"; import { defaultFlowDefinition } from "../../../bootstrap/flow_bootstrap.ts"; import { SyncOptions, mergeConfigWithConfigFile } from "../../core/conf.ts"; import { FSFSElement, elementsToMap, ignoreF } from "../sync/sync.ts"; @@ -574,32 +574,27 @@ async function preview( log.debug(`Flow value: ${JSON.stringify(localFlow.value, null, 2)}`); - // Run the flow preview - let result; - try { - result = await wmill.runFlowPreviewAndWaitResult({ - workspace: workspace.workspaceId, - requestBody: { - value: localFlow.value, - path: flowPath.substring(0, flowPath.indexOf(".flow")).replaceAll(SEP, "/"), - args: input, - }, - }); - } catch (e: any) { - if (e.body) { - // If a failure_module ran, the body contains its result — not an error - if (e.body.result !== undefined) { - if (opts.silent) { - console.log(JSON.stringify(e.body.result)); - } else { - log.info(colors.yellow.bold("Flow failed, error handler result:")); - log.info(JSON.stringify(e.body.result, null, 2)); - } - process.exitCode = 1; - return; - } + // Run the flow preview — start the job, then poll for completion + const jobId = await wmill.runFlowPreview({ + workspace: workspace.workspaceId, + requestBody: { + value: localFlow.value, + path: flowPath.substring(0, flowPath.indexOf(".flow")).replaceAll(SEP, "/"), + args: input, + }, + }); + + const { result, success } = await pollForJobResult(workspace.workspaceId, jobId); + + if (!success) { + if (opts.silent) { + console.log(JSON.stringify(result)); + } else { + log.info(colors.yellow.bold("Flow failed, error handler result:")); + log.info(JSON.stringify(result, null, 2)); } - throw e; + process.exitCode = 1; + return; } if (opts.silent) { diff --git a/cli/src/commands/script/script.ts b/cli/src/commands/script/script.ts index 9ab5064658..bbecf40bf1 100644 --- a/cli/src/commands/script/script.ts +++ b/cli/src/commands/script/script.ts @@ -1118,6 +1118,27 @@ export async function track_job(workspace: string, id: string) { } } +const POLL_INTERVAL_MS = 2000; + +export async function pollForJobResult( + workspace: string, + jobId: string, +): Promise<{ result: unknown; success: boolean }> { + while (true) { + const maybeResult = await wmill.getCompletedJobResultMaybe({ + workspace, + id: jobId, + getStarted: false, + }); + + if (maybeResult.completed) { + return { result: maybeResult.result, success: maybeResult.success ?? false }; + } + + await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS)); + } +} + async function show(opts: GlobalOptions, path: string) { const workspace = await resolveWorkspace(opts); await requireLogin(opts); @@ -1532,8 +1553,8 @@ async function preview( } } } else { - // For regular scripts, use the standard preview API - const result = await wmill.runScriptPreviewAndWaitResult({ + // For regular scripts, start the preview job then poll for completion + const jobId = await wmill.runScriptPreview({ workspace: workspace.workspaceId, requestBody: { content, @@ -1544,8 +1565,21 @@ async function preview( }, }); + const { result, success } = await pollForJobResult(workspace.workspaceId, jobId); + + if (!success) { + if (opts.silent) { + console.log(JSON.stringify(result)); + } else { + log.info(colors.red.bold("Preview failed")); + log.info(JSON.stringify(result, null, 2)); + } + process.exitCode = 1; + return; + } + if (opts.silent) { - console.log(JSON.stringify(result, null, 2)); + console.log(JSON.stringify(result)); } else { log.info(colors.bold.underline.green("Preview completed")); log.info(JSON.stringify(result, null, 2));