diff --git a/src/content/docs/workflows/build/events-and-parameters.mdx b/src/content/docs/workflows/build/events-and-parameters.mdx index 50b79bf839b44a5..b32918d4086fb9f 100644 --- a/src/content/docs/workflows/build/events-and-parameters.mdx +++ b/src/content/docs/workflows/build/events-and-parameters.mdx @@ -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 }); + }, }; ``` diff --git a/src/content/docs/workflows/build/rules-of-workflows.mdx b/src/content/docs/workflows/build/rules-of-workflows.mdx index b89258b3ddeb5b5..e7b392b5ee83ca9 100644 --- a/src/content/docs/workflows/build/rules-of-workflows.mdx +++ b/src/content/docs/workflows/build/rules-of-workflows.mdx @@ -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, step: WorkflowStep) { const customer_id = 123456; // ✅ Good: Non-idempotent API/Binding calls are always done **after** checking if the operation is // still needed. @@ -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, 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 @@ -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, 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 @@ -120,7 +120,7 @@ function getRandomInt(min, max) { } export class MyWorkflow extends WorkflowEntrypoint { - async run(event: WorkflowEvent, step: WorkflowStep) { + async run(event: WorkflowEvent, 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[] = []; @@ -163,7 +163,7 @@ function getRandomInt(min, max) { } export class MyWorkflow extends WorkflowEntrypoint { - async run(event: WorkflowEvent, step: WorkflowStep) { + async run(event: WorkflowEvent, 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([ @@ -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, 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 () => { diff --git a/src/content/docs/workflows/build/sleeping-and-retrying.mdx b/src/content/docs/workflows/build/sleeping-and-retrying.mdx index 4836e04fb4dd5e5..cdfaf298f754992 100644 --- a/src/content/docs/workflows/build/sleeping-and-retrying.mdx +++ b/src/content/docs/workflows/build/sleeping-and-retrying.mdx @@ -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 { diff --git a/src/content/docs/workflows/build/trigger-workflows.mdx b/src/content/docs/workflows/build/trigger-workflows.mdx index 7b631d78a80f8a4..a4d562c3d4ec120 100644 --- a/src/content/docs/workflows/build/trigger-workflows.mdx +++ b/src/content/docs/workflows/build/trigger-workflows.mdx @@ -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 @@ -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(), diff --git a/src/content/docs/workflows/build/workers-api.mdx b/src/content/docs/workflows/build/workers-api.mdx index b9c45e2dc15706f..5eafdb7d320d8c7 100644 --- a/src/content/docs/workflows/build/workers-api.mdx +++ b/src/content/docs/workflows/build/workers-api.mdx @@ -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 diff --git a/src/content/docs/workflows/get-started/guide.mdx b/src/content/docs/workflows/get-started/guide.mdx index 85f90a645813da3..311a62c42f7ea8b 100644 --- a/src/content/docs/workflows/get-started/guide.mdx +++ b/src/content/docs/workflows/get-started/guide.mdx @@ -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, step: WorkflowStep) { // Define one or more steps that optionally return state. const state = await step.do('my first step', async () => { return {} @@ -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, step: WorkflowStep) { // Define one or more steps that optionally return state. let state = step.do("my first step", async () => { @@ -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