Skip to content

Commit 9ee5599

Browse files
committed
update
1 parent 54fbafb commit 9ee5599

1 file changed

Lines changed: 60 additions & 47 deletions

File tree

src/content/docs/workflows/examples/dynamic-workflows.mdx

Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ For example, an AI agent might decide at runtime to create a Workflow with these
1818

1919
With Dynamic Workers and Workflows, the Worker Loader, which loads Dynamic Workers, can create that Workflow on the spot, run it durably, and let Workflows handle retries, sleeping, and waiting for events. You do not need to pre-register a separate Workflow class for every run.
2020

21+
In this example, we'll set up a simple Dynamic Workflow which allows you to run arbitrary Workflows code at runtime.
22+
2123
## When to use this pattern
2224

2325
Use this pattern when your workflow logic is not known at deploy time.
@@ -80,7 +82,7 @@ Your Worker needs two things:
8082

8183
Although the Workflow is not statically defined, you still deploy one normal Workflow class. Its job is to load the dynamic code for the current run and call it with the `WorkflowStep` object. This class is what makes the [Workflows API](/workflows/build/workers-api/), including `step.do()`, `step.sleep()`, and `step.waitForEvent()`, continue to work as normal.
8284

83-
Use `env.LOADER.get(id, callback)` via the [Worker Loader API](/dynamic-workers/api-reference/#load) to create the Dynamic Worker. If the Dynamic Worker has already been created, the Worker Loader uses its `workerId` to reload the code and use the same Dynamic Worker.
85+
Use `env.LOADER.get()` via the [Worker Loader API](/dynamic-workers/api-reference/#load) to create the Dynamic Worker. If the Dynamic Worker has already been created, the Worker Loader uses its `workerId` to reload the code and use the same Dynamic Worker.
8486

8587
<TypeScriptExample>
8688

@@ -119,58 +121,69 @@ export class DynamicWorkflow extends WorkflowEntrypoint<Env, Params> {
119121
}
120122
```
121123

122-
<TypeScriptExample>
123-
124-
```ts
125-
function loadDynamicWorkflow(env: Env, scriptId: string, script: string) {
126-
return env.LOADER.get(`dynamic-workflow:${scriptId}`, async () => ({
127-
compatibilityDate: "$today",
128-
mainModule: "index.js",
129-
modules: {
130-
"index.js": script,
131-
},
132-
globalOutbound: null,
133-
}));
134-
}
135-
```
136-
137124
</TypeScriptExample>
138125

139-
## Write the dynamic workflow code
140-
141-
The dynamic code defines the steps for one run. It is regular Worker code loaded at runtime.
142-
143-
This example implements the support-ticket flow described earlier:
144-
145-
1. Summarize the ticket
146-
2. Wait for approval
147-
3. Send a follow-up
126+
## Create your Worker entrypoint
148127

149128
<TypeScriptExample>
150129

151130
```ts
152-
import { WorkerEntrypoint } from "cloudflare:workers";
153-
154-
export class DynamicWorkflowLogic extends WorkerEntrypoint {
155-
async run(event, step) {
156-
const summary = await step.do("summarize ticket", async () => {
157-
const ticket = event.payload.ticket;
158-
return `Summary: ${ticket.subject}`;
159-
});
160-
161-
await step.waitForEvent("wait for approval", {
162-
type: "ticket-approved",
163-
timeout: "24 hours",
164-
});
165-
166-
return step.do("send follow-up", async () => {
167-
return {
168-
sent: true,
169-
message: `Approved follow-up sent for: ${summary}`,
170-
};
171-
});
172-
}
173-
}
131+
export { DynamicWorkflow } from "./workflow";
132+
133+
export default {
134+
async fetch(request, env, ctx): Promise<Response> {
135+
const url = new URL(request.url);
136+
137+
if (url.pathname === "/api/run" && request.method === "POST") {
138+
try {
139+
const { script } = (await request.json()) as { script: string };
140+
141+
if (!script || typeof script !== "string") {
142+
return Response.json(
143+
{ error: "script is required" },
144+
{ status: 400 },
145+
);
146+
}
147+
148+
const instance = await env.WORKFLOW.create({
149+
params: { script },
150+
});
151+
152+
return Response.json({
153+
instanceId: instance.id,
154+
status: await instance.status(),
155+
});
156+
} catch (error) {
157+
return Response.json(
158+
{ error: error instanceof Error ? error.message : String(error) },
159+
{ status: 500 },
160+
);
161+
}
162+
}
163+
164+
if (url.pathname === "/api/status") {
165+
const instanceId = url.searchParams.get("instanceId");
166+
if (!instanceId) {
167+
return Response.json(
168+
{ error: "instanceId query param is required" },
169+
{ status: 400 },
170+
);
171+
}
172+
173+
try {
174+
const instance = await env.WORKFLOW.get(instanceId);
175+
return Response.json(await instance.status());
176+
} catch (error) {
177+
return Response.json(
178+
{ error: error instanceof Error ? error.message : String(error) },
179+
{ status: 500 },
180+
);
181+
}
182+
}
183+
184+
return new Response("Not Found", { status: 404 });
185+
},
186+
} satisfies ExportedHandler<Env>;
174187
```
175188

176189
</TypeScriptExample>

0 commit comments

Comments
 (0)