Skip to main content

How can I forward processing to another step? Do I have to wait for a response?

· 3 min read
Jeremy Scott
Co-founder

Version 3.1.0 of opscotch adds two big improvements for handing work to other steps: a new JavascriptStateContext for reading results and errors, and sendToStepAndForget(...) for fire-and-forget concurrency.

You now have four ways to call another step:

  • sendToStep(stepId, body) — wait for completion, get a JavascriptStateContext.
  • sendToStep(stepId, body, headers) — same, but include headers (available via context.getHeader(...) in the target step).
  • sendToStepAndForget(stepId, body) — launch another step in another thread, return immediately.
  • sendToStepAndForget(stepId, body, headers) — fire-and-forget with headers.

JavascriptStateContext (new in 3.1.0) is a read-only context returned by the blocking sendToStep(...) calls. It gives you:

  • getBody(), getMessageBodyAsString()
  • getStepProperties(), getProperty(key)
  • Error helpers: isErrored(), getAllErrors(), hasUserErrors(), getUserErrors(), hasSystemErrors(), getSystemErrors(), getFirstError(...)

Placeholder docs: sendToStep, sendToStepAndForget, JavascriptStateContext.

When to wait vs. fire-and-forget

  • Use sendToStep(...) when you need the downstream result (body, properties, errors) before continuing.
  • Use sendToStepAndForget(...) when you just need to kick off work and move on—this is the launching point for concurrent processing in workflows.

Examples

Blocking call with headers and error handling:

let response = context.sendToStep("transform-step", "payload", { "userid": "alice" });

if (response.isErrored()) {
if (response.hasUserErrors()) {
let userIssue = response.getFirstError(response.getUserErrors());
context.addUserError("Transform issue: " + userIssue);
}
if (response.hasSystemErrors()) {
let sysIssue = response.getFirstError(response.getSystemErrors());
context.addSystemError("Transform failed: " + sysIssue);
}
} else {
let result = response.getBody(); // string; parse if JSON
context.setBody(result);
}

Fire-and-forget with headers:

context.sendToStepAndForget("ingest-step", "payload", { "source": "batch-42" });
// continue immediately; no returned context

What you can read from JavascriptStateContext

  • getBody() / getMessageBodyAsString() — response or passed-through body (string; parse JSON if needed).
  • getStepProperties() / getProperty(key) — the target step’s properties after it completed.
  • Error state — isErrored(), plus user/system error lists as above.

Remember: JavascriptStateContext is read-only; use it to inspect, not to mutate.

Error behavior

  • If the downstream step throws an exception, it shows up as a system error in the returned JavascriptStateContext.
  • Distinguish who should act:
    • User errors (addUserError) mean the operator/caller needs to fix input/config.
    • System errors (addSystemError) mean developers need to fix code/config.

With sendToStepAndForget, you won’t see errors unless you design another path to observe them (e.g., logging or a separate reporting step).

For more on adding and inspecting errors, see How can I work with errors in JavaScript processors?.

Why this matters

You can now:

  • Chain steps and capture results and errors cleanly with sendToStep(...).
  • Fan out work concurrently with sendToStepAndForget(...) when you don’t need to block.
  • Keep error handling consistent by inspecting JavascriptStateContext before proceeding.