Skip to content

Commit 56f9abd

Browse files
committed
workflows: show how to bind from Pages
1 parent 8f8b7d5 commit 56f9abd

File tree

2 files changed

+136
-4
lines changed

2 files changed

+136
-4
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
---
2+
title: Call Workflows from Pages
3+
pcx_content_type: concept
4+
sidebar:
5+
order: 11
6+
---
7+
8+
import { TypeScriptExample } from "~/components";
9+
10+
You can bind and trigger Workflows from [Pages Functions](/pages/functions/) by deploying a Workers project with your Workflow definition and then invoking that Worker using [service bindings](/pages/functions/bindings/#service-bindings) or a standard `fetch()` call.
11+
12+
:::note
13+
14+
You will need to deploy your Workflow as a standalone Workers project first before your Pages Function can call it. Visit the Workflows [get started guide](/workflows/get-started/guide/) if you have not yet deployed a Workflow.
15+
16+
:::
17+
18+
### Use Service Bindings
19+
20+
[Service Bindings](/workers/runtime-apis/bindings/service-bindings/) allow you to call a Worker from another Worker or a Pages Function without needing to expose it directly.
21+
22+
To do this, you:
23+
24+
1. Deploy your Workflow in a Worker
25+
2. Create a Service Binding to that Worker in your Pages project
26+
3. Call the Worker remotely using the binding
27+
28+
For example, if you have a Worker called `workflows-starter`, you would create a new Service Binding in your Pages project as follows, ensuring that the `service` name matches the name of the Worker your Workflow is defined in:
29+
30+
<WranglerConfig>
31+
32+
```toml
33+
services = [
34+
{ binding = "WORKFLOW_SERVICE", service = "workflows-starter" }
35+
]
36+
```
37+
38+
</WranglerConfig>
39+
40+
Your Worker can expose a specific method (or methods) that only other Workers or Pages Functions can call over the Service Binding.
41+
42+
In the following example, we expose a specific `createInstance` method that accepts our `Payload` and returns the [`InstanceStatus`](/workflows/build/workers-api/#instancestatus) from the Workflows API:
43+
44+
<TypeScriptExample filename="index.ts">
45+
import { WorkerEntrypoint } from "cloudflare:workers";
46+
47+
interface Env {
48+
MY_WORKFLOW: Workflow;
49+
}
50+
51+
type Payload = {
52+
hello: string;
53+
}
54+
55+
export default class WorkflowsService extends WorkerEntrypoint<Env> {
56+
// Currently, entrypoints without a named handler are not supported
57+
async fetch() { return new Response(null, {status: 404}); }
58+
59+
async createInstance(payload: Payload) {
60+
let instance = await this.env.MY_WORKFLOW.create({
61+
params: payload
62+
});
63+
64+
return Response.json({
65+
id: instance.id,
66+
details: await instance.status(),
67+
});
68+
}
69+
}
70+
</TypeScriptExample>
71+
72+
Your Pages Function would resemble the followijng:
73+
74+
<TypeScriptExample filename="functions/request.ts">
75+
interface Env {
76+
WORKFLOW_SERVICE: Service;
77+
}
78+
79+
export const onRequest: PagesFunction<Env> = async (context) => {
80+
// This payload could be anything from within your app or from your frontend
81+
let payload = {"hello": "world"}
82+
return context.env.WORKFLOWS_SERVICE.createInstance(payload)
83+
};
84+
</TypeScriptExample>
85+
86+
Visit the [bindings documentation for Pages Functions](/pages/functions/bindings/#service-bindings) to learn more about binding to resources from Pages Functions, including how to bind via the Cloudflare dashboard.
87+
88+
### Using fetch
89+
90+
:::note
91+
92+
We recommend using [Service Bindings](/workers/runtime-apis/bindings/service-bindings/) when calling a Worker in your own account.
93+
94+
Service Bindings don't require you to expose a public endpoint from your Worker, don't require you to configure authentication, and allow you to call methods on your Worker directly, avoiding the overhead of managing HTTP requests and responses.
95+
96+
:::
97+
98+
An alternative to setting up a Service Binding is to call the Worker over HTTP by using the Workflows [Workers API](/workflows/build/workers-api/#workflow) to `create` a new Workflow instance for each incoming HTTP call to the Worker:
99+
100+
<TypeScriptExample filename="index.ts">
101+
// This is in the same file as your Workflow definition
102+
export default {
103+
async fetch(req: Request, env: Env): Promise<Response> {
104+
let instance = await env.MY_WORKFLOW.create({
105+
params: payload
106+
});
107+
return Response.json({
108+
id: instance.id,
109+
details: await instance.status(),
110+
});
111+
},
112+
};
113+
</TypeScriptExample>
114+
115+
Your [Pages Function](/pages/functions/get-started/) can then make a regular `fetch` call to the Worker:
116+
117+
<TypeScriptExample filename="functions/request.ts">
118+
export const onRequest: PagesFunction<Env> = async (context) => {
119+
// Other code
120+
let payload = {"hello": "world"}
121+
const instanceStatus = fetch("https://YOUR_WORKER.workers.dev/", {
122+
method: "POST",
123+
body: JSON.stringify(payload) // Send a paylod for our Worker to pass to the Workflow
124+
}
125+
return Response.json(instanceStatus);
126+
};
127+
</TypeScriptExample>
128+
129+
You can also choose to authenticate these requests by passing a shared secret in a header and validating that in your Worker.

src/content/docs/workflows/build/workers-api.mdx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,20 @@ binding = "MY_WORKFLOW"
125125
# this is class that extends the Workflow class in src/index.ts
126126
class_name = "MyWorkflow"
127127
```
128-
129128
</WranglerConfig>
130129

130+
### Bind from Pages
131+
132+
You can bind and trigger Workflows from [Pages Functions](/pages/functions/) by deploying a Workers project with your Workflow definition and then invoking that Worker using [service bindings](/pages/functions/bindings/#service-bindings) or a standard `fetch()` call.
133+
134+
Visit the documentation on [calling Workflows from Pages](/workflows/build/call-workflows-from-pages/) for examples.
135+
131136
### Cross-script calls
132137

133138
You can also bind to a Workflow that is defined in a different Worker script from the script your Workflow definition is in. To do this, provide the `script_name` key with the name of the script to the `[[workflows]]` binding definition in your `wrangler.toml` configuration.
134139

135140
For example, if your Workflow is defined in a Worker script named `billing-worker`, but you are calling it from your `web-api-worker` script, your `wrangler.toml` would resemble the following:
136141

137-
138-
139142
<WranglerConfig>
140143

141144
```toml title="wrangler.toml"
@@ -228,7 +231,7 @@ export default {
228231
// params expects the type User
229232
params: user
230233
})
231-
234+
232235
return Response.json({
233236
id: instance.id,
234237
details: await instance.status(),

0 commit comments

Comments
 (0)