Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Invoke docs #390

Merged
merged 1 commit into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,7 @@
"workflow/howto/monitor",
"workflow/howto/security",
"workflow/howto/parallel-runs",
"workflow/howto/invoke",
"workflow/howto/schedule",
"workflow/howto/changes",
"workflow/howto/local-development",
Expand Down Expand Up @@ -1467,6 +1468,7 @@
"pages": [
"workflow/examples/allInOne",
"workflow/examples/waitForEvent",
"workflow/examples/invoke",
"workflow/examples/customerOnboarding",
"workflow/examples/authWebhook",
"workflow/examples/paymentRetry",
Expand Down
21 changes: 21 additions & 0 deletions workflow/basics/context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,27 @@ More details about the `Waiter` object:

<Snippet file="qstash/waiter.mdx" />

### context.invoke

Triggers another workflow run and waits for its completion.
The workflow continues when the invoked workflow finishes, whether successfully, with failure, or is canceled.
The response is the data returned by the invoked workflow, if any is returned.

```ts
export const { POST } = serve<{ topic: string }>(async (context) => {

const {response, isFailed, isCanceled} = await context.invoke("invoke another workflow", {
workflow: anotherWorkflowObject,
body: "test",
header: {...}
});

})
```

Only workflows that served together can invoke each other. To learn more about how you can serve multiple workflows together,
checkout [Invoke other workflows](/workflow/howto/invoke) guide.

### context.cancel

<Note>
Expand Down
57 changes: 57 additions & 0 deletions workflow/howto/invoke.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: "Invoke other workflows"
---

You can start another workflow run inside a workflow and await its execution to complete.
This allows to orchestrate multiple workflows together without external syncranization.

```typescript
const { response, isFailed, isCanceled } = await context.invoke("analyze-content", {
workflow: analyzeContent,
body: {/**/},
headers: {/**/}
})
```

As you may notice, we pass a workflow object to the invoke function. This object is initialized using the `createWorkflow()` function.

Normally, workflows are initialized with `serve()` method and exposed as a standalone route in your application.
However, when workflows are defined separately using `serve()`, type safety is not guaranteed.

To ensure type safety for request and response when invoking other workflows, we introduced the `createWorkflow()` function.
`createWorkflow()` returns a referenceable workflow object that can be used in `context.invoke()`.

```typescript
import { WorkflowContext } from "@upstash/workflow";
import { create, serve } from "@upstash/workflow/nextjs";

// 👇 anotherWorkflow: (string) => number
const anotherWorkflow = createWorkflow(async (context: WorkflowContext<string>) => {

await context.run("step-1", () => {
// Execute any business logic...
}),

return {message: "This is the data returned by workflow"}
});

const someWorkflow = createWorkflow(async (context) => {
// 👇 type(response) = {message: string}
const { response } = await context.invoke("invoke ", {
workflow: anotherWorkflow,
// 👇 type(body) = string
body: "user-1"
}),
});

export const { POST } = serve([someWorkflow, anotherWorkflow])
```

`createWorkflow()` does not expose your workflow like `serve()`, it just initializes the workflow object.
To be able to use the workflow, they must be exposed with `serve([<WORKFLOW_LIST>])` function.

<Warning>
If workflows are going to be invoke each other, they must be exposed in the same `serve` endpoint.

If you pass a workflow object which is initialized with `createWorkflow()` but not exposed inside the same `serve`, you will get a runtime error.
</Warning>