Skip to content

Commit

Permalink
commit
Browse files Browse the repository at this point in the history
  • Loading branch information
elithrar committed Oct 16, 2024
1 parent 4033935 commit 2cb3bf2
Show file tree
Hide file tree
Showing 28 changed files with 1,179 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/content/changelogs/workflows.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
link: "/workflows/platform/changelog/"
productName: Workflows
productLink: "/workflows/"
productArea: Developer platform
productAreaLink: /workflows/
entries:
- publish_date: "2038-01-19"
title: Workflows is now in public beta.
description: |-
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/).
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.
You can learn more about Workflows in [our announcement blog], or start building in our [get started guide].
35 changes: 35 additions & 0 deletions src/content/docs/workflows/build/dynamic-steps.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
title: Dynamic steps
pcx_content_type: concept
sidebar:
order: 5

---

A Workflow does not have to define all of its steps statically: steps can be created programmatically and/or conditionally.

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


## Example

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.

For example, you can loop over each event, label the step dynamically, and have the step operate only over that `event`:

```ts
export class MyWorkflow extends Workflow<Env, Params> {
async run(events: WorkflowEvent[], step: WorkflowStep) {
// Dynamically create a step for each event passed to our workflow
// ... or for every file we want to read from R2 storage
// ... or each API call we need to make based on an incoming request
for (const event of events) {
await step.do(`processing ${event.id}`, async () => {
// Step logic for one event goes here
// You can also specify a StepConfig for each step, just as you
// would for any other step
})
}
}
}
```
11 changes: 11 additions & 0 deletions src/content/docs/workflows/build/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: Build with Workflows
pcx_content_type: navigation
sidebar:
order: 1

---

import { DirectoryListing } from "~/components"

<DirectoryListing />
9 changes: 9 additions & 0 deletions src/content/docs/workflows/build/retrying.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: Retrying
pcx_content_type: concept
sidebar:
order: 4

---

TODO
26 changes: 26 additions & 0 deletions src/content/docs/workflows/build/rules-of-steps.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
title: Rules of Steps
pcx_content_type: concept
sidebar:
order: 10

---

A Workflow step is 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.

### Ensure API calls are idempotent

TODO

### Don't rely on state outside of a step

TODO

### Set sensible retry parameters

TODO

### Name your steps clearly

TODO

86 changes: 86 additions & 0 deletions src/content/docs/workflows/build/trigger-workflows.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
title: Trigger Workflows
pcx_content_type: concept
sidebar:
order: 3

---

TODO - intro

## Workers API (Bindings)

You can interact with Workflows programmatically from any Worker script by creating a binding to a Workflow. A Worker can bind to multiple Workflows, including Workflows defined in other Workers projects (scripts) within your account.

You can interact with a Workflow:

* Directly over HTTP via the [`fetch`](/workers/runtime-apis/handlers/fetch/) handler
* From a [Queue consumer](/queues/configuration/javascript-apis/#consumer) inside a `queue` handler
* From a [Cron Trigger](/workers/configuration/cron-triggers/) inside a `scheduled` handler
* Within a [Durable Object](/durable-objects/).

:::note

New to Workflows? Start with the [Workflows tutorial](/workflows/get-started/guide/) to deploy your first Workflow and familiarize yourself with Workflows concepts.

:::

To bind to a Workflow from your Workers code, you need to define a [binding](/workers/wrangler/configuration/) to a specific Workflow. For example, to bind to the Workflow defined in the [get started guide](/workflows/get-started/guide/), you would configure a `wrangler.toml` with the below:

```toml title="wrangler.toml"
name = "workflows-tutorial"
main = "src/index.ts"
compatibility_date = "2024-10-15"

[[workflows]]
# The name of the Workflow
name = "workflows-tutorial"
# The binding name, which must be a valid JavaScript variable name. This will
# be how you call (run) your Workflow from your other Workers handlers or
# scripts.
binding = "MY_WORKFLOW"
# script_name is required during for the beta.
# Must match the "name" of your Worker at the top of wrangler.toml
script_name = "workflows-tutorial"
# Must match the class defined in your code that extends the Workflow class
class_name = "MyWorkflow"
```

The `binding = "MY_WORKFLOW"` line defines the JavaScript variable that our Workflow methods are accessible on, including `create` (which triggers a new instance) or `get` (which returns the status of an existing instance).

```ts title="src/index.ts"
interface Env {
MY_WORKFLOW: Workflow;
}

export default {
async fetch(req: Request, env: Env) {
//
const instanceId = new URL(req.url).searchParams.get("instanceId")

// If an ?instanceId=<id> query parameter is provided, fetch the status
// of an existing Workflow by its ID.
if (instanceId) {
let instance = await env.MY_WORKFLOW.get(id);
return Response.json({
status: await instance.status(),
});
}

// 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, {});
return Response.json({
id: instance.id,
details: await instance.status(),
});

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

## REST API (HTTP)

TODO
9 changes: 9 additions & 0 deletions src/content/docs/workflows/build/typescript.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: Dynamic steps
pcx_content_type: concept
sidebar:
order: 6

---

TODO - outline how to use TypeScript and
59 changes: 59 additions & 0 deletions src/content/docs/workflows/build/workers-api.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: Workers API
pcx_content_type: concept
sidebar:
order: 2

---

TODO


## Interacting with Workflows

* Running a Workflow with the `run()` method
* `StepConfig`
* `NonRetriableError`
* TODO on TypeScript type params

## Workflow

* <code>run(events: WorkflowEvent&lt;T&gt;[], step: WorkflowStep): Promise&lt;T&gt;</code>

TODO

```ts
export class MyWorkflow extends Workflow<Env, Params> {
async run(events: WorkflowEvent[], step: WorkflowStep) {
// TODO
}
}
```


## WorkflowStep

### step

TODO - into to steps

* <code>step.do(name: string, callback: (): RpcSerializable, config?: StepConfig): Promise&lt;T&gt;</code>

* TODO - describe each param
* TODO -

TODO - show an example
TODO - show an example of dynamically creating a step

* <code>step.sleep(name: string, duration: WorkflowDuration): Promise&lt;void&gt;</code>

* TODO -

TODO - show an example


## StepConfig

TODO

## NonRetriableError
15 changes: 15 additions & 0 deletions src/content/docs/workflows/examples/automate-lifecycle-emails.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
type: example
summary: Automate lifecycle emails
tags:
- Workflows
- Email
pcx_content_type: configuration
title: Automate lifecycle emails
sidebar:
order: 3
description: Automate lifecycle emails using Workflows and Resend

---

import { TabItem, Tabs } from "~/components"
15 changes: 15 additions & 0 deletions src/content/docs/workflows/examples/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
type: overview
hideChildren: false
pcx_content_type: navigation
title: Examples
sidebar:
order: 6

---

import { GlossaryTooltip, ListExamples } from "~/components"

Explore the following <GlossaryTooltip term="code example">examples</GlossaryTooltip> for D1.

<ListExamples directory="d1/examples/" />
15 changes: 15 additions & 0 deletions src/content/docs/workflows/examples/post-process-r2.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
type: example
summary: Post-process files from R2
tags:
- Workflows
- R2
pcx_content_type: configuration
title: Post-process files from R2
sidebar:
order: 3
description: Post-process files from R2 object storage using Workflows

---

import { TabItem, Tabs } from "~/components"
Loading

0 comments on commit 2cb3bf2

Please sign in to comment.