Skip to content
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
31 changes: 17 additions & 14 deletions src/content/docs/workflows/build/events-and-parameters.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,23 @@ Store state durably by returning it from your `step.do` callbacks.

```ts
export default {
async fetch(req: Request, env: Env) {
let someEvent = { url: req.url, createdTimestamp: Date.now() }
// Trigger our Workflow
// Pass our event as the second parameter to the `create` method
// on our Workflow binding.
let instance = await env.MYWORKFLOW.create(await crypto.randomUUID(), someEvent);

return Response.json({
id: instance.id,
details: await instance.status(),
});

return Response.json({ result });
},
async fetch(req: Request, env: Env) {
let someEvent = { url: req.url, createdTimestamp: Date.now() }
// Trigger our Workflow
// Pass our event as the second parameter to the `create` method
// on our Workflow binding.
let instance = await env.MYWORKFLOW.create({
id: await crypto.randomUUID(),
params: someEvent
});

return Response.json({
id: instance.id,
details: await instance.status(),
});

return Response.json({ result });
},
};
```

Expand Down
12 changes: 6 additions & 6 deletions src/content/docs/workflows/build/rules-of-workflows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ check if they were already charged:

```ts
export class MyWorkflow extends WorkflowEntrypoint {
async run(event: WorkflowEvent, step: WorkflowStep) {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
const customer_id = 123456;
// ✅ Good: Non-idempotent API/Binding calls are always done **after** checking if the operation is
// still needed.
Expand Down Expand Up @@ -69,7 +69,7 @@ You can also think of it as a transaction, or a unit of work.

```ts
export class MyWorkflow extends WorkflowEntrypoint {
async run(event: WorkflowEvent, step: WorkflowStep) {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// ✅ Good: Unrelated API/Binding calls are self-contained, so that in case one of them fails
// it can retry them individually. It also has an extra advantage: you can control retry or
// timeout policies for each granular step - you might not to want to overload http.cat in
Expand All @@ -94,7 +94,7 @@ Otherwise, your entire Workflow might not be as durable as you might think, and

```ts
export class MyWorkflow extends WorkflowEntrypoint {
async run(event: WorkflowEvent, step: WorkflowStep) {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// 🔴 Bad: you're calling two seperate services from within the same step. This might cause
// some extra calls to the first service in case the second one fails, and in some cases, makes
// the step non-idempotent altogether
Expand All @@ -120,7 +120,7 @@ function getRandomInt(min, max) {
}

export class MyWorkflow extends WorkflowEntrypoint {
async run(event: WorkflowEvent, step: WorkflowStep) {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// 🔴 Bad: `imageList` will be not persisted across engine's lifetimes. Which means that after hibernation,
// `imageList` will be empty again, even though the following two steps have already ran.
const imageList: string[] = [];
Expand Down Expand Up @@ -163,7 +163,7 @@ function getRandomInt(min, max) {
}

export class MyWorkflow extends WorkflowEntrypoint {
async run(event: WorkflowEvent, step: WorkflowStep) {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// ✅ Good: imageList state is exclusively comprised of step returns - this means that in the event of
// multiple engine lifetimes, imageList will be built accordingly
const imageList: string[] = await Promise.all([
Expand Down Expand Up @@ -231,7 +231,7 @@ Dynamically naming a step will prevent it from being cached, and cause the step

```ts
export class MyWorkflow extends WorkflowEntrypoint {
async run(event: WorkflowEvent, step: WorkflowStep) {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// 🔴 Bad: Dynamically naming the step prevents it from being cached
// This will cause the step to be re-run if subsequent steps fail.
await step.do(`step #1 running at: ${Date.now}`, async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ This can be useful when you detect a terminal (permanent) error from an upstream

```ts
// Import the NonRetryableError definition
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent, NonRetryableError } from 'cloudflare:workers';
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers';
import { NonRetryableError } from 'cloudflare:workflows';

// In your step code:
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
Expand Down
4 changes: 2 additions & 2 deletions src/content/docs/workflows/build/trigger-workflows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ To bind to a Workflow from your Workers code, you need to define a [binding](/wo
```toml title="wrangler.toml"
name = "workflows-tutorial"
main = "src/index.ts"
compatibility_date = "2024-10-15"
compatibility_date = "2024-10-22"

[[workflows]]
# The name of the Workflow
Expand Down Expand Up @@ -80,7 +80,7 @@ export default {
// Else, create a new instance of our Workflow, passing in any (optional) params
// and return the ID.
const newId = await crypto.randomUUID();
let instance = await env.MY_WORKFLOW.create(newId, {});
let instance = await env.MY_WORKFLOW.create({ id: newId });
return Response.json({
id: instance.id,
details: await instance.status(),
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/workflows/build/workers-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ For example, to bind to a Workflow called `workflows-starter` and to make it ava
#:schema node_modules/wrangler/config-schema.json
name = "workflows-starter"
main = "src/index.ts"
compatibility_date = "2024-10-16"
compatibility_date = "2024-10-22"

[[workflows]]
# name of your workflow
Expand Down
14 changes: 9 additions & 5 deletions src/content/docs/workflows/get-started/guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,12 @@ Open the `src/index.ts` file in your text editor. This file contains the followi
// Import the Workflow definition
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workers"

type Params = {}

// Create your own class that implements a Workflow
export class MyWorkflow implements WorkflowEntrypoint {
export class MyWorkflow extends WorkflowEntrypoint {
// Define a run() method
async run(event: WorkflowEvent, step: WorkflowStep) {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// Define one or more steps that optionally return state.
const state = await step.do('my first step', async () => {
return {}
Expand Down Expand Up @@ -99,10 +101,12 @@ At its most basic, a step looks like this:
// Import the Workflow definition
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workers"

type Params = {}

// Create your own class that implements a Workflow
export class MyWorkflow implements WorkflowEntrypoint {
export class MyWorkflow extends WorkflowEntrypoint {
// Define a run() method
async run(event: WorkflowEvent, step: WorkflowStep) {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// Define one or more steps that optionally return state.
let state = step.do("my first step", async () => {

Expand Down Expand Up @@ -150,7 +154,7 @@ Open the `wrangler.toml` file at the root of your `workflows-starter` folder, wh
#:schema node_modules/wrangler/config-schema.json
name = "workflows-starter"
main = "src/index.ts"
compatibility_date = "2024-10-23"
compatibility_date = "2024-10-22"

[[workflows]]
# name of your workflow
Expand Down
Loading