You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/changelogs/workflows.yaml
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ entries:
8
8
- publish_date: "2038-01-19"
9
9
title: Workflows is now in public beta.
10
10
description: |-
11
-
Workflows, a new product for building reliable, multi-step workflows using Cloudflare Workers, is now in public beta. The public beta is avaiable to any user with a [free or paid Workers plan](/workers/platform/pricing/).
11
+
Workflows, a new product for building reliable, multi-step workflows using Cloudflare Workers, is now in public beta. The public beta is available to any user with a [free or paid Workers plan](/workers/platform/pricing/).
12
12
13
13
A Workflow allows you to define multiple, independent steps that encapsulate errors, automatically retry, persist state, and can run for seconds, minutes, hours or even days. A Workflow can be useful for post-processing data from R2 buckets before querying it, automating a [Workers AI RAG pipeline](/workers-ai/tutorials/build-a-retrieval-augmented-generation-ai/), or managing user signup flows and lifecycle emails.
Copy file name to clipboardExpand all lines: src/content/docs/workflows/build/dynamic-steps.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,12 +8,12 @@ sidebar:
8
8
9
9
A Workflow does not have to define all of its steps statically: steps can be created programmatically and/or conditionally.
10
10
11
-
This allows you to not only trigger steps based on specific input parameters, but to also name steps dynamically, set the retry configuration for a step
11
+
This allows you to not only trigger steps based on specific input parameters, but to also name steps dynamically and set the retry configuration for a single step.
12
12
13
13
14
14
## Example
15
15
16
-
Steps can be created on-the-fly, allowing you create a step for each parameter passed to your Workflow, for each file you want to read from storage, or for calls to third-party APIs.
16
+
You can create steps on-the-fly. You can create a step for each parameter passed to your Workflow, for each file you want to read from storage, or for calls to third-party APIs.
17
17
18
18
For example, you can loop over each event, label the step dynamically, and have the step operate only over that `event`:
Copy file name to clipboardExpand all lines: src/content/docs/workflows/build/events-and-parameters.mdx
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,11 +10,11 @@ When a Workflow is triggered, it can receive an optional event. This event can i
10
10
11
11
Events are a powerful part of a Workflow, as you often want a Workflow to act on data. Because a given Workflow instance executes durably, events are a useful way to provide a Workflow with data that should be immutable (not changing) and/or represents data the Workflow needs to operate on at that point in time.
12
12
13
-
## Passing parameters to a Workflow
13
+
## Pass parameters to a Workflow
14
14
15
15
You can pass parameters to a Workflow in two ways:
16
16
17
-
* As an optional argument to the `create` method on a [Workflow binding] when triggering a Workflow from a Worker.
17
+
* As an optional argument to the `create` method on a [Workflow binding](/workers/wrangler/commands/#trigger) when triggering a Workflow from a Worker.
18
18
* Via the `--params` flag when using the `wrangler` CLI to trigger a Workflow.
19
19
20
20
You can pass any JSON-serializable object as a parameter.
@@ -80,7 +80,7 @@ interface YourEventType {
80
80
}
81
81
```
82
82
83
-
When we pass our`YourEventType` to `WorkflowEvent` as a type parameter, the `event.payload` property now has the type `YourEventType` throughout our workflow definition:
83
+
When you pass your`YourEventType` to `WorkflowEvent` as a type parameter, the `event.payload` property now has the type `YourEventType` throughout your workflow definition:
Copy file name to clipboardExpand all lines: src/content/docs/workflows/build/rules-of-workflows.mdx
+39-19Lines changed: 39 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,16 +5,16 @@ sidebar:
5
5
order: 10
6
6
---
7
7
8
-
A Workflow contains one or more steps. Each step is a self-contained, individually retriable component of a Workflow. Steps may emit (optional) state that allows a Workflow to persist and continue from that step, even if a Workflow fails due to a network or infrastructure issue. A Workflow is comprised of one or more steps.
8
+
A Workflow contains one or more steps. Each step is a self-contained, individually retriable component of a Workflow. Steps may emit (optional) state that allows a Workflow to persist and continue from that step, even if a Workflow fails due to a network or infrastructure issue.
9
9
10
10
This is a small guidebook on how to build more resilient and correct Workflows.
11
11
12
12
### Ensure API/Binding calls are idempotent
13
13
14
14
Because a step might be retried multiple times, your steps should (ideally) be idempotent. For context, idempotency is a logical property where the operation (in this case a step),
15
-
can be applied multiple times without changing the result beyond the intial application.
15
+
can be applied multiple times without changing the result beyond the initial application.
16
16
17
-
As an example, let's assume you have a Workflow that charges your customers and you really don't want to charge them twice by accident, before charging them, you should
17
+
As an example, let us assume you have a Workflow that charges your customers, and you really do not want to charge them twice by accident. Before charging them, you should
18
18
check if they were already charged:
19
19
20
20
```ts
@@ -55,13 +55,13 @@ export class MyWorkflow extends WorkflowEntrypoint {
55
55
56
56
:::note
57
57
58
-
Guaranteeing idempotency might be optional in your specific use-case and implementation, although we recommend it to always try to guarantee it.
58
+
Guaranteeing idempotency might be optional in your specific use-case and implementation, but we recommend that you always try to guarantee it.
59
59
60
60
:::
61
61
62
62
### Make your steps granular
63
63
64
-
Steps should be as self-contained as possible, this allows your own logic to be more durable in case of failures in third-party APIs, network errors, and so on.
64
+
Steps should be as self-contained as possible. This allows your own logic to be more durable in case of failures in third-party APIs, network errors, and so on.
65
65
66
66
You can also think of it as a transaction, or a unit of work.
67
67
@@ -85,12 +85,12 @@ export class MyWorkflow extends WorkflowEntrypoint {
85
85
}
86
86
```
87
87
88
-
Otherwise your entire workflow might not be as durable as you might think, and encounter into some undefined behaviour and you can avoid them by:
88
+
Otherwise, your entire Workflow might not be as durable as you might think, and you may encounter some undefined behaviour. You can avoid them by following the rules below:
89
89
90
90
- 🔴 Do not encapsulate your entire logic in one single step.
91
-
- 🔴 Do not call seperate services in the same step (unless you need it to prove idempotency)
92
-
- 🔴 Do not make too many service calls in the same step (unless you need it to prove idempotency)
93
-
- 🔴 Do not do too much CPU-intensive work inside of a single step - sometimes engine might have to restart and it will start over from that step.
91
+
- 🔴 Do not call separate services in the same step (unless you need it to prove idempotency).
92
+
- 🔴 Do not make too many service calls in the same step (unless you need it to prove idempotency).
93
+
- 🔴 Do not do too much CPU-intensive work inside a single step - sometimes the engine may have to restart, and it will start over from the beginning of that step.
94
94
95
95
```ts
96
96
exportclassMyWorkflowextendsWorkflowEntrypoint {
@@ -106,9 +106,9 @@ export class MyWorkflow extends WorkflowEntrypoint {
106
106
}
107
107
```
108
108
109
-
### Don't rely on state outside of a step
109
+
### Do not rely on state outside of a step
110
110
111
-
Workflows may hibernate and lose all in-memory state. This will happen when engine detects that there's no pending work and can hibernate until it needs to wake-up (because of a sleep, retry or event).
111
+
Workflows may hibernate and lose all in-memory state. This will happen when engine detects that there is no pending work and can hibernate until it needs to wake-up (because of a sleep, retry, or event).
112
112
113
113
This means that you should not store state outside of a step:
114
114
@@ -193,14 +193,34 @@ export class MyWorkflow extends WorkflowEntrypoint {
193
193
}
194
194
```
195
195
196
-
### Set sensible retry parameters
196
+
### Do not mutate your incoming events
197
197
198
-
TODO
198
+
The `event` passed to your Workflow's `run` method is immutable: changes you make to the event are not persisted across steps and/or Workflow restarts.
Copy file name to clipboardExpand all lines: src/content/docs/workflows/build/sleeping-and-retrying.mdx
+58-5Lines changed: 58 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,20 +6,49 @@ sidebar:
6
6
7
7
---
8
8
9
-
TODO
9
+
This guide details how to sleep a Workflow and/or configure retries for a Workflow step.
10
10
11
-
## Sleeping
11
+
## Sleep a Workflow
12
12
13
-
TODO
13
+
You can set a Workflow to sleep as an explicit step, which can be useful when you want a Workflow to wait, schedule work ahead, or pause until an input or other external state is ready.
14
14
15
15
:::note
16
16
17
17
A Workflow instance that is resuming from sleep will take priority over newly scheduled (queued) instances. This helps ensure that older Workflow instances can run to completion and are not blocked by newer instances.
18
18
19
19
:::
20
20
21
+
### Sleep for a relative period
21
22
22
-
## Retrying steps
23
+
Use `step.sleep` to have a Workflow sleep for a relative period of time:
24
+
25
+
```ts
26
+
awaitstep.sleep("sleep for a bit", "1 hour")
27
+
```
28
+
29
+
The second argument to `step.sleep` accepts both `number` (seconds) or a human-readable format, such as "1 minute" or "26 hours". The accepted units for `step.sleep` when used this way are as follows:
30
+
31
+
```ts
32
+
|"second"
33
+
|"minute"
34
+
|"hour"
35
+
|"day"
36
+
|"week"
37
+
|"month"
38
+
|"year"
39
+
```
40
+
41
+
### Sleep until a fixed date
42
+
43
+
Use `step.sleepUntil` to have a Workflow sleep to a specific `Date`: this can be useful when you have a timestamp from another system or want to "schedule" work to occur at a specific time (e.g. Sunday, 9AM UTC).
44
+
45
+
```ts
46
+
// sleepUntil accepts a Date object as its second argument
47
+
const workflowsLaunchDate =Date.parse("24 Oct 2024 13:00:00 UTC");
48
+
awaitstep.sleepUntil("sleep until X times out", workflowsLaunchDate)
49
+
```
50
+
51
+
## Retry steps
23
52
24
53
Each call to `step.do` in a Workflow accepts an optional `StepConfig`, which allows you define the retry behaviour for that step.
25
54
@@ -41,7 +70,7 @@ When providing your own `StepConfig`, you can configure:
41
70
* The total number of attempts to make for a step
42
71
* The delay between attempts
43
72
* What backoff algorithm to apply between each attempt: any of `constant`, `linear`, or `exponential`
44
-
* When to timeout (in duration) before considering the step as failed (including during a retry attempt).
73
+
* When to timeout (in duration) before considering the step as failed (including during a retry attempt)
45
74
46
75
For example, to limit a step to 10 retries and have it apply an exponential delay (starting at 10 seconds) between each attempt, you would pass the following configuration as an optional object to `step.do`:
47
76
@@ -55,3 +84,27 @@ let someState = step.do("call an API", {
55
84
timeout: "30 minutes",
56
85
}, async () => { /* Step code goes here /* }
57
86
```
87
+
88
+
## Force a Workflow to fail
89
+
90
+
You can also force a Workflow instance to fail and _not_ retry by throwing a `NonRetryableError` from within the step.
91
+
92
+
This can be useful when you detect a terminal (permanent) error from an upstream system (such as an authentication failure) or other errors where retrying would not help.
93
+
94
+
```ts
95
+
// Import the NonRetryableError definition
96
+
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent, NonRetryableError } from 'cloudflare:workers';
97
+
98
+
// In your step code:
99
+
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
Copy file name to clipboardExpand all lines: src/content/docs/workflows/build/trigger-workflows.mdx
+12-8Lines changed: 12 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,11 @@ sidebar:
6
6
7
7
---
8
8
9
-
TODO - intro
9
+
You can trigger Workflows both programmatically and via the Workflows APIs, including:
10
+
11
+
1. With [Workers](/workers) via HTTP requests in a `fetch` handler, or bindings from a `queue` or `scheduled` handler
12
+
2. Using the [Workflows REST API](/api/paths/accounts-account_id--workflows/get)
13
+
2. Via the [wrangler CLI](/workers/wrangler/commands/#workflows) in your terminal
10
14
11
15
## Workers API (Bindings)
12
16
@@ -17,7 +21,7 @@ You can interact with a Workflow:
17
21
* Directly over HTTP via the [`fetch`](/workers/runtime-apis/handlers/fetch/) handler
18
22
* From a [Queue consumer](/queues/configuration/javascript-apis/#consumer) inside a `queue` handler
19
23
* From a [Cron Trigger](/workers/configuration/cron-triggers/) inside a `scheduled` handler
20
-
* Within a [Durable Object](/durable-objects/).
24
+
* Within a [Durable Object](/durable-objects/)
21
25
22
26
:::note
23
27
@@ -52,7 +56,7 @@ The following example shows how you can manage Workflows from within a Worker, i
52
56
53
57
* Retrieving the status of an existing Workflow instance by its ID
54
58
* Creating (triggering) a new Workflow instance
55
-
* Returning the status of a given instance ID.
59
+
* Returning the status of a given instance ID
56
60
57
61
```ts title="src/index.ts"
58
62
interfaceEnv {
@@ -89,7 +93,7 @@ export default {
89
93
90
94
### Inspect a Workflow's status
91
95
92
-
You can inspect the status of any running Workflow instance by calling `status` against a specific instance ID. This allows you to programmatically inspect whether an instance is queued (waiting to be scheduled), actively running, paused or errored.
96
+
You can inspect the status of any running Workflow instance by calling `status` against a specific instance ID. This allows you to programmatically inspect whether an instance is queued (waiting to be scheduled), actively running, paused, or errored.
93
97
94
98
```ts
95
99
let instance =awaitenv.MY_WORKFLOW.get("abc-123")
@@ -114,7 +118,7 @@ The possible values of status are as follows:
114
118
};
115
119
```
116
120
117
-
### Explicitly pausing a Workflow
121
+
### Explicitly pause a Workflow
118
122
119
123
You can explicitly pause a Workflow instance (and later resume it) by calling `pause` against a specific instance ID.
120
124
@@ -123,7 +127,7 @@ let instance = await env.MY_WORKFLOW.get("abc-123")
123
127
awaitinstance.pause() // Returns Promise<void>
124
128
```
125
129
126
-
### Resuming a Workflow
130
+
### Resume a Workflow
127
131
128
132
You can resume a paused Workflow instance by calling `resume` against a specific instance ID.
0 commit comments