From 2cb3bf2ee82313dfd08d302a108c2e12b16f534c Mon Sep 17 00:00:00 2001 From: Matt Silverlock Date: Wed, 16 Oct 2024 07:42:38 +0100 Subject: [PATCH] commit --- src/content/changelogs/workflows.yaml | 15 + .../docs/workflows/build/dynamic-steps.mdx | 35 ++ src/content/docs/workflows/build/index.mdx | 11 + src/content/docs/workflows/build/retrying.mdx | 9 + .../docs/workflows/build/rules-of-steps.mdx | 26 ++ .../workflows/build/trigger-workflows.mdx | 86 ++++ .../docs/workflows/build/typescript.mdx | 9 + .../docs/workflows/build/workers-api.mdx | 59 +++ .../examples/automate-lifecycle-emails.mdx | 15 + src/content/docs/workflows/examples/index.mdx | 15 + .../workflows/examples/post-process-r2.mdx | 15 + .../workflows/get-started/cli-quick-start.mdx | 124 ++++++ .../docs/workflows/get-started/guide.mdx | 384 ++++++++++++++++++ .../docs/workflows/get-started/index.mdx | 11 + src/content/docs/workflows/index.mdx | 103 +++++ .../docs/workflows/observability/index.mdx | 11 + .../observability/metrics-analytics.mdx | 29 ++ .../docs/workflows/reference/changelog.mdx | 15 + .../docs/workflows/reference/glossary.mdx | 13 + .../reference/how-workflows-works.mdx | 27 ++ .../docs/workflows/reference/index.mdx | 11 + .../docs/workflows/reference/limits.mdx | 33 ++ .../docs/workflows/reference/pricing.mdx | 44 ++ .../workflows/reference/storage-options.mdx | 8 + .../workflows/reference/wrangler-commands.mdx | 8 + src/content/docs/workflows/workflows-api.mdx | 8 + src/content/glossary/workflows.yaml | 22 + src/content/products/workflows.yaml | 33 ++ 28 files changed, 1179 insertions(+) create mode 100644 src/content/changelogs/workflows.yaml create mode 100644 src/content/docs/workflows/build/dynamic-steps.mdx create mode 100644 src/content/docs/workflows/build/index.mdx create mode 100644 src/content/docs/workflows/build/retrying.mdx create mode 100644 src/content/docs/workflows/build/rules-of-steps.mdx create mode 100644 src/content/docs/workflows/build/trigger-workflows.mdx create mode 100644 src/content/docs/workflows/build/typescript.mdx create mode 100644 src/content/docs/workflows/build/workers-api.mdx create mode 100644 src/content/docs/workflows/examples/automate-lifecycle-emails.mdx create mode 100644 src/content/docs/workflows/examples/index.mdx create mode 100644 src/content/docs/workflows/examples/post-process-r2.mdx create mode 100644 src/content/docs/workflows/get-started/cli-quick-start.mdx create mode 100644 src/content/docs/workflows/get-started/guide.mdx create mode 100644 src/content/docs/workflows/get-started/index.mdx create mode 100644 src/content/docs/workflows/index.mdx create mode 100644 src/content/docs/workflows/observability/index.mdx create mode 100644 src/content/docs/workflows/observability/metrics-analytics.mdx create mode 100644 src/content/docs/workflows/reference/changelog.mdx create mode 100644 src/content/docs/workflows/reference/glossary.mdx create mode 100644 src/content/docs/workflows/reference/how-workflows-works.mdx create mode 100644 src/content/docs/workflows/reference/index.mdx create mode 100644 src/content/docs/workflows/reference/limits.mdx create mode 100644 src/content/docs/workflows/reference/pricing.mdx create mode 100644 src/content/docs/workflows/reference/storage-options.mdx create mode 100644 src/content/docs/workflows/reference/wrangler-commands.mdx create mode 100644 src/content/docs/workflows/workflows-api.mdx create mode 100644 src/content/glossary/workflows.yaml create mode 100644 src/content/products/workflows.yaml diff --git a/src/content/changelogs/workflows.yaml b/src/content/changelogs/workflows.yaml new file mode 100644 index 000000000000000..e68ac49becfe398 --- /dev/null +++ b/src/content/changelogs/workflows.yaml @@ -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]. diff --git a/src/content/docs/workflows/build/dynamic-steps.mdx b/src/content/docs/workflows/build/dynamic-steps.mdx new file mode 100644 index 000000000000000..ec8550fc6f93405 --- /dev/null +++ b/src/content/docs/workflows/build/dynamic-steps.mdx @@ -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 { + 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 + }) + } + } +} +``` \ No newline at end of file diff --git a/src/content/docs/workflows/build/index.mdx b/src/content/docs/workflows/build/index.mdx new file mode 100644 index 000000000000000..b992b0ca9c67547 --- /dev/null +++ b/src/content/docs/workflows/build/index.mdx @@ -0,0 +1,11 @@ +--- +title: Build with Workflows +pcx_content_type: navigation +sidebar: + order: 1 + +--- + +import { DirectoryListing } from "~/components" + + diff --git a/src/content/docs/workflows/build/retrying.mdx b/src/content/docs/workflows/build/retrying.mdx new file mode 100644 index 000000000000000..1b6e6428efc0a2b --- /dev/null +++ b/src/content/docs/workflows/build/retrying.mdx @@ -0,0 +1,9 @@ +--- +title: Retrying +pcx_content_type: concept +sidebar: + order: 4 + +--- + +TODO \ No newline at end of file diff --git a/src/content/docs/workflows/build/rules-of-steps.mdx b/src/content/docs/workflows/build/rules-of-steps.mdx new file mode 100644 index 000000000000000..b912d4fa7b51b1e --- /dev/null +++ b/src/content/docs/workflows/build/rules-of-steps.mdx @@ -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 + diff --git a/src/content/docs/workflows/build/trigger-workflows.mdx b/src/content/docs/workflows/build/trigger-workflows.mdx new file mode 100644 index 000000000000000..5d82cddbffb5c14 --- /dev/null +++ b/src/content/docs/workflows/build/trigger-workflows.mdx @@ -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= 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 diff --git a/src/content/docs/workflows/build/typescript.mdx b/src/content/docs/workflows/build/typescript.mdx new file mode 100644 index 000000000000000..854fd9811f5bcd2 --- /dev/null +++ b/src/content/docs/workflows/build/typescript.mdx @@ -0,0 +1,9 @@ +--- +title: Dynamic steps +pcx_content_type: concept +sidebar: + order: 6 + +--- + +TODO - outline how to use TypeScript and \ No newline at end of file diff --git a/src/content/docs/workflows/build/workers-api.mdx b/src/content/docs/workflows/build/workers-api.mdx new file mode 100644 index 000000000000000..a431f53d249d6d2 --- /dev/null +++ b/src/content/docs/workflows/build/workers-api.mdx @@ -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 + +* run(events: WorkflowEvent<T>[], step: WorkflowStep): Promise<T> + +TODO + +```ts +export class MyWorkflow extends Workflow { + async run(events: WorkflowEvent[], step: WorkflowStep) { + // TODO + } +} +``` + + +## WorkflowStep + +### step + +TODO - into to steps + +* step.do(name: string, callback: (): RpcSerializable, config?: StepConfig): Promise<T> + + * TODO - describe each param + * TODO - + +TODO - show an example +TODO - show an example of dynamically creating a step + +* step.sleep(name: string, duration: WorkflowDuration): Promise<void> + + * TODO - + +TODO - show an example + + +## StepConfig + +TODO + +## NonRetriableError \ No newline at end of file diff --git a/src/content/docs/workflows/examples/automate-lifecycle-emails.mdx b/src/content/docs/workflows/examples/automate-lifecycle-emails.mdx new file mode 100644 index 000000000000000..f6457998b11e626 --- /dev/null +++ b/src/content/docs/workflows/examples/automate-lifecycle-emails.mdx @@ -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" diff --git a/src/content/docs/workflows/examples/index.mdx b/src/content/docs/workflows/examples/index.mdx new file mode 100644 index 000000000000000..b7030341362eabd --- /dev/null +++ b/src/content/docs/workflows/examples/index.mdx @@ -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 examples for D1. + + diff --git a/src/content/docs/workflows/examples/post-process-r2.mdx b/src/content/docs/workflows/examples/post-process-r2.mdx new file mode 100644 index 000000000000000..8e79f7b54f477cf --- /dev/null +++ b/src/content/docs/workflows/examples/post-process-r2.mdx @@ -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" diff --git a/src/content/docs/workflows/get-started/cli-quick-start.mdx b/src/content/docs/workflows/get-started/cli-quick-start.mdx new file mode 100644 index 000000000000000..ece4c6f34e26f74 --- /dev/null +++ b/src/content/docs/workflows/get-started/cli-quick-start.mdx @@ -0,0 +1,124 @@ +--- +title: CLI quick start +pcx_content_type: get-started +updated: 2038-01-19 +sidebar: + order: 3 + +--- + +import { Render, PackageManagers } from "~/components" + +:::note + +Workflows is in **public beta**, and any developer with a [free or paid Workers plan](/workers/platform/pricing/#workers) can start using Workflows immediately. + +To learn more about Workflows, read [the beta announcement blog](https://blog.cloudflare.com/THE-BLOG-SLUG-WILL-GO-HERE) and the [How Workflows Works](/workflows/build/how-workflows-works/) developer documentation. + +::: + +Workflows allow you to build durable, multi-step applications using the Workers platform. A Workflow can automatically retry, persist state, run for hours or days, and coordinate between third-party APIs. + +You can build Workflows to post-process file uploads to [R2 object storage](/r2/), automate generation of [Workers AI](/workers-ai/) embeddings into a [Vectorize](/vectorize/) vector database, or to trigger [user lifecycle emails](TODO) using your favorite email API. + +## Prerequisites + +:::note + +This guide is for users who are already familiar with Cloudflare Workers and [durable execution](/workflows/how-workflows-works/) programming models. + +If you're new to either, we recommend the [introduction to Workflows](/workflows/get-started/guide/) guide, which steps through how a Workflow is defined, how to persist state, deploy and manage Workflows. + +::: + +Before you continue, ensure you: + +1. Sign up for a [Cloudflare account](https://dash.cloudflare.com/sign-up/workers-and-pages) if you have not already. +2. Install [`npm`](https://docs.npmjs.com/getting-started). +3. Install [`Node.js`](https://nodejs.org/en/). Use a Node version manager like [Volta](https://volta.sh/) or [nvm](https://github.com/nvm-sh/nvm) to avoid permission issues and change Node.js versions. [Wrangler](/workers/wrangler/install-and-update/) requires a Node version of `16.17.0` or later. + +## 1. Create a Workflow + +Workflows are defined as part of a Worker script. + +To create a Workflow, use the `create cloudflare` (C3) CLI tool, specifying the Workflows starter template: + +```sh +npm create cloudflare@latest workflows-tutorial -- --template "cloudflare:workflows-tutorial" +``` + +This will create a new folder called `workflows-tutorial`, which contains two files: + +* `src/index.ts` - this is where your Worker script, including your Workflows definition, is defined. +* `wrangler.toml` - the configuration for your Workers project and your Workflow. + +Open the `src/index.ts` file in your text editor. This file contains the following code, which is the most basic instance of a Workflow definition: + +```ts title="src/index.ts" +// Import the Workflow definition +import { Workflow, WorkflowEvent, WorkflowStep } from "cloudflare:workflows" + +// Create your own class that implements a Workflow +export class MyFirstWorkflow implements Workflow { + // Define a run() method + async run(event: WorkflowEvent, step: WorkflowStep) { + // Define one or more steps that optionally return state. + let state = step.do("my first step", async () => { + + }) + + step.do("my second step", async () => { + + }) + } +} +``` + +Specifically: + +1. TODO - describe the Workflow class +2. TODO - how params are injected +3. TODO - how state is persisted +4. TODO - retries and config +5. TODO - triggering from a fetch handler + +```ts title="src/index.ts" + + +``` + +## 2. Deploy a Workflow + +Workflows are deployed via [`wrangler](/workers/wrangler/install-and-update/), which is installed when you first ran `npm create cloudflare`, above. Workflows are Workers scripts, and deployed the same way. + +```sh +npx wrangler@latest deploy +``` +```sh output +TODO +``` + +## 3. Running a Workflow + +TODO - basic trigger steps +```sh +npx wrangler@latest workflows trigger workflows-tutorial --params={"hello":"world"} +``` + +TODO - trigger from a Worker + +## 4. Managing Workflows + +TODO - managing via the CLI + +* Listing +* Showing running instances +* Inspecting an instances state + +## Next steps + +* TODO +* ALSO TODO +* ALSO ALSO TODO + +If you have any feature requests or notice any bugs, share your feedback directly with the Cloudflare team by joining the [Cloudflare Developers community on Discord](https://discord.cloudflare.com). diff --git a/src/content/docs/workflows/get-started/guide.mdx b/src/content/docs/workflows/get-started/guide.mdx new file mode 100644 index 000000000000000..c01b22c68d4accd --- /dev/null +++ b/src/content/docs/workflows/get-started/guide.mdx @@ -0,0 +1,384 @@ +--- +title: Guide +pcx_content_type: get-started +updated: 2038-01-19 +sidebar: + order: 1 + +--- + +import { Render, PackageManagers } from "~/components" + +:::note + +Workflows is in **public beta**, and any developer with a [free or paid Workers plan](/workers/platform/pricing/#workers) can start using Workflows immediately. + +To learn more about Workflows, read [the beta announcement blog](https://blog.cloudflare.com/THE-BLOG-SLUG-WILL-GO-HERE) and the [How Workflows Works](/workflows/build/how-workflows-works/) developer documentation. + +::: + +Workflows allow you to build durable, multi-step applications using the Workers platform. A Workflow can automatically retry, persist state, run for hours or days, and coordinate between third-party APIs. + +You can build Workflows to post-process file uploads to [R2 object storage](/r2/), automate generation of [Workers AI](/workers-ai/) embeddings into a [Vectorize](/vectorize/) vector database, or to trigger [user lifecycle emails](TODO) using your favorite email API. + +This guide will instruct you through: + +* Defining your first Workflow and publishing it +* Deploying the Workflow to your Cloudflare account +* Running (triggering) your Workflow and observing its output + +At the end of this guide, you should be able to author, deploy and debug your own Workflows applications. + +## Prerequisites + +To continue: + +1. Sign up for a [Cloudflare account](https://dash.cloudflare.com/sign-up/workers-and-pages) if you have not already. +2. Install [`npm`](https://docs.npmjs.com/getting-started). +3. Install [`Node.js`](https://nodejs.org/en/). Use a Node version manager like [Volta](https://volta.sh/) or [nvm](https://github.com/nvm-sh/nvm) to avoid permission issues and change Node.js versions. [Wrangler](/workers/wrangler/install-and-update/) requires a Node version of `16.17.0` or later. + +## 1. Define your Workflow + +To create your first Workflow, use the `create cloudflare` (C3) CLI tool, specifying the Workflows starter template: + +```sh +npx create cloudflare@latest workflows-tutorial -- --template "cloudflare:workflows-tutorial" +``` + +This will create a new folder called `workflows-tutorial`. + +Open the `src/index.ts` file in your text editor. This file contains the following code, which is the most basic instance of a Workflow definition: + +```ts title="src/index.ts" +// Import the Workflow definition +import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workflows" + +// Create your own class that implements a Workflow +export class MyWorkflow implements WorkflowEntrypoint { + // Define a run() method + 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 {} + }); + + await step.sleep('wait on something', '1 minute'); + + await step.do( + 'make a call to write that could maybe, just might, fail', + async () => { + // Do stuff here, with access to 'state' from the previous step + if (Math.random() > 0.5) { + throw new Error('API call to $STORAGE_SYSTEM failed'); + } + } + ); + } +} +``` + +A Workflow definition: + +1. Defines a `run` method that contains the primary logic for your workflow. +2. Has at least one or more calls to `step.do` that encapsulates the logic of your Workflow. +3. Allows steps to return (optional) state, allowing a Workflow to continue execution even if subsequent steps fail, without having to re-run all previous steps. + +A single Worker application can contain multiple Workflow definitions, as long as each Workflow has a unique class name. This can be useful for code re-use or to define Workflows are related to each other conceptually. + +Each Workflow is otherwise entirely independent: a Worker that defines multiple Workflows is no different from a set of Workers that define one Workflow each. + +## 2. Create your Workflows steps + +Each `step` in a Workflow is an independently retriable function. + +A `step` is what makes a Workflow powerful, as you can encapsulate errors and persist state as your Workflow progresses from step to step, avoiding your application from having to start from scratch on failure and ultimately build more reliable applications. + +* A step can execute code (`step.do`) or sleep a Workflow (`step.sleep`) +* If a step fails (throws an exception), it will be automatically be retried based on your retry logic. +* Ia step succeeds, any state it returns will be persisted within the Workflow. + +At it's most basic, a step looks like this: + +```ts title="src/index.ts" +// Import the Workflow definition +import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workflows" + +// Create your own class that implements a Workflow +export class MyWorkflow implements WorkflowEntrypoint { + // Define a run() method + async run(event: WorkflowEvent, step: WorkflowStep) { + // Define one or more steps that optionally return state. + let state = step.do("my first step", async () => { + + }) + + step.do("my second step", async () => { + + }) + } +} +``` + +Each call to `step.do` accepts three arguments: + +1. (Required) A step name, which identifies the step in logs and telemetry +2. (Required) A callback function that contains the code to run for your step, and any state you want the Workflow to persist +3. (Optional) A `StepConfig` that defines the retry configuration (max retries, delay, and backoff algorithm) for the step. + +When trying to decide whether to break code up into more than one step, a good rule of thumb is to ask "do I want _all_ of this code to run again if just one part of it fails?". In many cases, you do _not_ want to repeatedly call an API if the following data processing stage fails, or if you get an error when attempting to send a completion or welcome email. + +For example, each of the below tasks is ideally encapsulated in its own step, so that any failure β€” such as a file not existing, a third-party API being down or rate limited β€” does not cause your entire program to fail. + +* Reading or writing files from R2 +* Running an AI task using [Workers AI](/workers-ai/) +* Querying a D1 database or a database via [Hyperdrive](/hyperdrive/) +* Calling a third-party API + +If a subsequent step fails, your Workflow can retry from that step, using any state returned from a previous step. This can also help you avoid unnecessarily querying a database or calling an paid API repeatedly for data you've already fetched. + +:::note + +The term "Durable Execution" is widely used to describe this programming model. + +"Durable" describes the ability of the program (application) to implicitly persist state without you having to write to an external store or serialize program state manual + +::: + +## 3. Configure your Workflow + +Before you can deploy a Workflow, you need to configure it. + +Open the `wrangler.toml` file at the root of your `workflows-tutorial` folder, which contains the following `[[workflows]]` configuration: + +```toml title="wrangler.toml" +name = "workflows-tutorial" +main = "src/index.ts" +compatibility_date = "2024-08-20" + +[[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" +``` + +:::note + +If you have changed the name of the Workflow in your wrangler commands, the JavaScript class name, or the name of the project you created, ensure that you update the values above to match. + +::: + +This configuration tells the Workers platform which JavaScript class represents your Workflow, and sets a `binding` name that allows you to run the Workflow from other handlers or to call into Workflows from other Workers scripts. + +## 4. Bind to your Workflow + +We have a very basic Workflow definition, but now need to provide a way to call it from within our code. A Workflow can be triggered by: + +1. External HTTP requests via a `fetch()` handler +2. Messages from a [Queue](/queues/) +3. A schedule via [Cron Trigger](/workers/configuration/cron-triggers/) +4. Via the [Workflows REST API](TODO) or [wrangler CLI](/workers/wrangler/commands/#workflows) + +Return to the `src/index.ts` file we created in the previous step and add a `fetch` handler that _binds_ to our Workflow. This binding allows us to create new Workflow instances, fetch the status of an existing Workflow, pause and/or terminate a Workflow. + +```ts title="src/index.ts" +// This can be in the same file as our Workflow definition + +export default { + async fetch(req: Request, env: Env) { + // + const instanceId = new URL(req.url).searchParams.get("instanceId") + + // If an ?instanceId= query parameter is provided, fetch the status + // of an existing Workflow by its ID. + if (instanceId) { + let instance = await env.MYWORKFLOW.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.MYWORKFLOW.create(newId, {}); + return Response.json({ + id: instance.id, + details: await instance.status(), + }); + + return Response.json({ result }); + }, +}; +``` + +The code here exposes a HTTP endpoint that generates a random ID and runs the Workflow, returning the ID and the Workflow status. It also accepts an optional `instanceId` query parameter that retrieves the status of a Workflow instance by its ID. + +:::note + +In a production application, you might choose to put authentication in front of your endpoint so that only authorized users can run a Workflow. Alternatively, you could pass messages to a Workflow [from a Queue consumer](/queues/reference/how-queues-works/#consumers) in order to allow for long-running tasks. + +::: + +## 6. Deploy your Workflow + +Deploying a Workflow is identical to deploying a Worker. + +```sh +npx wrangler deploy +``` +```sh output +TODO +``` + +A Worker with a valid Workflow definition will be automatically registered by Workflows. You can list your current Workflows using wrangler: + +```sh +npx wrangler workflows list +``` +```sh output +TODO +``` + +TODO - describe the output, Workflows, instances, etc. + + +## 6. Run and observe your Workflow + +With your Workflow deployed, you can now run it. + +1. A Workflow can run in parallel: each unique invocation of a Workflow is an _instance_ of that Workflow. +2. An instance will run to completion (success or failure) +3. Deploying newer versions of a Workflow will cause all instances after that point to run the newest Workflow code. + +:::note + +Because Workflows can be long running, it's possible to have running instances that represent different versions of your Workflow code over time. + +::: + + + +To trigger our Workflow, we will use the `wrangler` CLI and pass in an optional `--payload`. The `payload` will be passed to your Workflow's `run` method handler as an `Event` + +```sh +npx wrangler workflows trigger my-workflow '{"hello":"world"}' +``` +```sh output +# Workflow instance "12dc179f-9f77-4a37-b973-709dca4189ba" has been queued successfully +``` + +To inspect the current status of the Workflow instance we just triggered, we can either reference it by ID or by using the keyword `latest`: + +```sh +npx wrangler@workflows workflows instances describe my-workflow latest +# Or by ID: +# npx wrangler@workflows workflows instances describe my-workflow 12dc179f-9f77-4a37-b973-709dca4189ba +``` +```sh output +Workflow Name: my-workflow +Instance Id: f72c1648-dfa3-45ea-be66-b43d11d216f8 +Version Id: cedc33a0-11fa-4c26-8a8e-7d28d381a291 +Status: βœ… Completed +Trigger: 🌎 API +Queued: 10/15/2024, 1:55:31 PM +Success: βœ… Yes +Start: 10/15/2024, 1:55:31 PM +End: 10/15/2024, 1:56:32 PM +Duration: 1 minute +Last Successful Step: make a call to write that could maybe, just might, fail-1 +Steps: + + Name: my first step-1 + Type: 🎯 Step + Start: 10/15/2024, 1:55:31 PM + End: 10/15/2024, 1:55:31 PM + Duration: 0 seconds + Success: βœ… Yes + Output: "{\"inputParams\":[{\"timestamp\":\"2024-10-15T13:55:29.363Z\",\"payload\":{\"hello\":\"world\"}}],\"files\":[\"doc_7392_rev3.pdf\",\"report_x29_final.pdf\",\"memo_2024_05_12.pdf\",\"file_089_update.pdf\",\"proj_alpha_v2.pdf\",\"data_analysis_q2.pdf\",\"notes_meeting_52.pdf\",\"summary_fy24_draft.pdf\",\"plan_2025_outline.pdf\"]}" +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Start β”‚ End β”‚ Duration β”‚ State β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ 10/15/2024, 1:55:31 PM β”‚ 10/15/2024, 1:55:31 PM β”‚ 0 seconds β”‚ βœ… Success β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + Name: some other step-1 + Type: 🎯 Step + Start: 10/15/2024, 1:55:31 PM + End: 10/15/2024, 1:55:31 PM + Duration: 0 seconds + Success: βœ… Yes + Output: "{\"result\":{\"ipv4_cidrs\":[\"173.245.48.0/20\",\"103.21.244.0/22\",\"103.22.200.0/22\",\"103.31.4.0/22\",\"141.101.64.0/18\",\"108.162.192.0/18\",\"190.93.240.0/20\",\"188.114.96.0/20\",\"197.234.240.0/22\",\"198.41.128.0/17\",\"162.158.0.0/15\",\"104.16.0.0/13\",\"104.24.0.0/14\",\"172.64.0.0/13\",\"131.0.72.0/22\"],\"ipv6_cidrs\":[\"2400:cb00::/32\",\"2606:4700::/32\",\"2803:f800::/32\",\"2405:b500::/32\",\"2405:8100::/32\",\"2a06:98c0::/29\",\"2c0f:f248::/32\"],\"etag\":\"38f79d050aa027e3be3865e495dcc9bc\"},\"success\":true,\"errors\":[],\"messages\":[]}" +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Start β”‚ End β”‚ Duration β”‚ State β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ 10/15/2024, 1:55:31 PM β”‚ 10/15/2024, 1:55:31 PM β”‚ 0 seconds β”‚ βœ… Success β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + Name: wait on something-1 + Type: πŸ’€ Sleeping + Start: 10/15/2024, 1:55:31 PM + End: 10/15/2024, 1:56:31 PM + Duration: 1 minute + + Name: make a call to write that could maybe, just might, fail-1 + Type: 🎯 Step + Start: 10/15/2024, 1:56:31 PM + End: 10/15/2024, 1:56:32 PM + Duration: 1 second + Success: βœ… Yes + Output: null +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Start β”‚ End β”‚ Duration β”‚ State β”‚ Error β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ 10/15/2024, 1:56:31 PM β”‚ 10/15/2024, 1:56:31 PM β”‚ 0 seconds β”‚ ❌ Error β”‚ Error: API call to $STORAGE_SYSTEM failed β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ 10/15/2024, 1:56:32 PM β”‚ 10/15/2024, 1:56:32 PM β”‚ 0 seconds β”‚ βœ… Success β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +From the output above, we can inspect: + +* The status (success, failure, running) of each step +* Any state emitted by the step +* Any `sleep` state, including when the Workflow will wake up +* Retries associated with each step. +* Errors, including exception messages + +:::note + +You do not have to wait for a Workflow instance to finish executing to inspect its current status. The `wrangler workflows instances describe` sub-command will show the status of an in-progress instance, including any persisted state, if it is sleeping, and any errors or retries. This can be especially useful when debugging a Workflow during development. + +::: + + +In the previous step, we also bound a Workers script to our Workflow. You can trigger a Workflow by visiting the (deployed) Workers script in a browser or with any HTTP client. + +```sh +# This must match the URL provided in step 6 +curl -s https://workflows-tutorial.YOUR_WORKERS_SUBDOMAIN.workers.dev/ +``` +```sh output +{"id":"16ac31e5-db9d-48ae-a58f-95b95422d0fa","details":{"status":"queued","error":null,"output":null}} +``` + +## 7. (Optional) Clean up + +TODO - delete the Workflow. + +--- + +## Next steps + +- learn more +- observability +- trigger workflows on a schedule or from a Queue + +If you have any feature requests or notice any bugs, share your feedback directly with the Cloudflare team by joining the [Cloudflare Developers community on Discord](https://discord.cloudflare.com). diff --git a/src/content/docs/workflows/get-started/index.mdx b/src/content/docs/workflows/get-started/index.mdx new file mode 100644 index 000000000000000..f318b640b29cb8d --- /dev/null +++ b/src/content/docs/workflows/get-started/index.mdx @@ -0,0 +1,11 @@ +--- +title: Get started +pcx_content_type: navigation +sidebar: + order: 1 + +--- + +import { DirectoryListing } from "~/components" + + diff --git a/src/content/docs/workflows/index.mdx b/src/content/docs/workflows/index.mdx new file mode 100644 index 000000000000000..cdf4ebab1499587 --- /dev/null +++ b/src/content/docs/workflows/index.mdx @@ -0,0 +1,103 @@ +--- +title: Overview +order: 0 +type: overview +pcx_content_type: overview +sidebar: + order: 1 +head: + - tag: title + content: Cloudflare D1 + +--- + +import { CardGrid, Description, Feature, LinkTitleCard, Plan, RelatedProduct } from "~/components" + + + + +Create new serverless SQL databases to query from your Workers and Pages projects. + + + + + + +D1 is Cloudflare’s native serverless database. D1 allows you to build applications that handle large amounts of users at no extra cost. With D1, you can restore your database to any minute within the last 30 days. + +Create your first D1 database by [following the Get started guide](/d1/get-started/), learn how to [import data into a database](/d1/build-with-d1/import-export-data/), and how to [interact with your database](/d1/build-with-d1/d1-client-api/) directly from [Workers](/workers/) or [Pages](/pages/functions/bindings/#d1-databases). + +*** + +## Features + + + +Create your first D1 database, establish a schema, import data and query D1 directly from an application [built with Workers](/workers/). + + + + + + +Execute SQL with SQLite's SQL compatibility and D1 Client API. + + + + + + +Time Travel is D1’s approach to backups and point-in-time-recovery, and allows you to restore a database to any minute within the last 30 days. + + + + +*** + +## Related products + + + +Build serverless applications and deploy instantly across the globe for exceptional performance, reliability, and scale. + + + + + + +Deploy dynamic front-end applications in record time. + + + + +*** + +## More resources + + + + +Learn about D1's pricing and how to estimate your usage. + + + +Learn about what limits D1 has and how to work within them. + + + +Browse what developers are building with D1. + + + +Learn more about the storage and database options you can build on with Workers. + + + +Connect with the Workers community on Discord to ask questions, show what you are building, and discuss the platform with other developers. + + + +Follow @CloudflareDev on Twitter to learn about product announcements, and what is new in Cloudflare Developer Platform. + + + diff --git a/src/content/docs/workflows/observability/index.mdx b/src/content/docs/workflows/observability/index.mdx new file mode 100644 index 000000000000000..a1d9cc8345878d0 --- /dev/null +++ b/src/content/docs/workflows/observability/index.mdx @@ -0,0 +1,11 @@ +--- +title: Observability +pcx_content_type: navigation +sidebar: + order: 5 + +--- + +import { DirectoryListing } from "~/components" + + diff --git a/src/content/docs/workflows/observability/metrics-analytics.mdx b/src/content/docs/workflows/observability/metrics-analytics.mdx new file mode 100644 index 000000000000000..b67c0160cb13e30 --- /dev/null +++ b/src/content/docs/workflows/observability/metrics-analytics.mdx @@ -0,0 +1,29 @@ +--- +pcx_content_type: concept +title: Metrics and analytics +sidebar: + order: 10 + +--- + +D1 exposes database analytics that allow you to inspect query volume, query latency, and storage size across all and/or each database in your account. + +The metrics displayed in the [Cloudflare dashboard](https://dash.cloudflare.com/) charts are queried from Cloudflare’s [GraphQL Analytics API](/analytics/graphql-api/). You can access the metrics [programmatically](#query-via-the-graphql-api) via GraphQL or HTTP client. + +## Metrics + +D1 currently exports the below metrics: + +| Metric | GraphQL Field Name | Description | +| ---------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| Read Queries (qps) | `readQueries` | The number of read queries issued against a database. This is the raw number of read queries, and is not used for billing. | +| Write Queries (qps) | `writeQueries` | The number of write queries issued against a database. This is the raw number of write queries, and is not used for billing. | +| Rows read (count) | `rowsRead` | The number of rows read (scanned) across your queries. See [Pricing](/d1/platform/pricing/) for more details on how rows are counted. | +| Rows written (count) | `rowsWritten` | The number of rows written across your queries. | +| Query Response (bytes) | `queryBatchResponseBytes` | The total response size of the serialized query response, including any/all column names, rows and metadata. Reported in bytes. | +| Query Latency (ms) | `queryBatchTimeMs` | The total query response time, including response serialization, on the server-side. Reported in milliseconds. | +| Storage (Bytes) | `databaseSizeBytes` | Maximum size of a database. Reported in bytes. | + +Metrics can be queried (and are retained) for the past 31 days. + +### Row count \ No newline at end of file diff --git a/src/content/docs/workflows/reference/changelog.mdx b/src/content/docs/workflows/reference/changelog.mdx new file mode 100644 index 000000000000000..1e63decb2fa0897 --- /dev/null +++ b/src/content/docs/workflows/reference/changelog.mdx @@ -0,0 +1,15 @@ +--- +pcx_content_type: changelog +title: Changelog +changelog_file_name: + - workflows +sidebar: + order: 99 + +--- + +import { ProductChangelog } from "~/components" + +{/* */} + + diff --git a/src/content/docs/workflows/reference/glossary.mdx b/src/content/docs/workflows/reference/glossary.mdx new file mode 100644 index 000000000000000..a00fee9cc25fbf9 --- /dev/null +++ b/src/content/docs/workflows/reference/glossary.mdx @@ -0,0 +1,13 @@ +--- +title: Glossary +pcx_content_type: glossary +sidebar: + order: 10 + +--- + +import { Glossary } from "~/components" + +Review the definitions for terms used across Cloudflare's Workflows documentation. + + diff --git a/src/content/docs/workflows/reference/how-workflows-works.mdx b/src/content/docs/workflows/reference/how-workflows-works.mdx new file mode 100644 index 000000000000000..43aad05f0a3b1ea --- /dev/null +++ b/src/content/docs/workflows/reference/how-workflows-works.mdx @@ -0,0 +1,27 @@ +--- +title: How Workflows Works +pcx_content_type: concept +sidebar: + order: 1 + +--- + +TODO + +## Data model + +- Workflow +- Version +- Instances + +## Workflow + +TODO + +## Version + +TODO + +## Instance + +TODO \ No newline at end of file diff --git a/src/content/docs/workflows/reference/index.mdx b/src/content/docs/workflows/reference/index.mdx new file mode 100644 index 000000000000000..8516bf0f828bd96 --- /dev/null +++ b/src/content/docs/workflows/reference/index.mdx @@ -0,0 +1,11 @@ +--- +pcx_content_type: navigation +title: Platform +sidebar: + order: 8 + +--- + +import { DirectoryListing } from "~/components" + + diff --git a/src/content/docs/workflows/reference/limits.mdx b/src/content/docs/workflows/reference/limits.mdx new file mode 100644 index 000000000000000..d376d97bf53cac1 --- /dev/null +++ b/src/content/docs/workflows/reference/limits.mdx @@ -0,0 +1,33 @@ +--- +pcx_content_type: concept +title: Limits +sidebar: + order: 4 + +--- + +import { Render } from "~/components" + +Limits that apply to authoring, deploying and running Workflows are detailed below. + +Many limits are inherited from those applied to Workers scripts and as documented in the [Workers limits](/workers/platform/limits/) documentation. + +| Feature | Workers Free | Workers Paid | +| ----------------------------------------- | ----------------------- | --------------------- | +| Workflow class definitions per script | 1MB max script size per [Worker size limits](/workers/platform/limits/#account-plan-limits) | 1MB max script size per [Worker size limits](/workers/platform/limits/#account-plan-limits) +| Total scripts per account | 100 | 500 (shared with [Worker script limits](/workers/platform/limits/#account-plan-limits) | +| Compute time per Workflow | 10 seconds | 30 seconds of [active CPU time](/workers/platform/limits/#cpu-time) | +| Duration (wall clock) per `step` | Unlimited | Unlimited - e.g. waiting on network I/O calls or querying a database | +| Maximum persisted state per step | 1MB (1e6 bytes) | 1MB (1e6 bytes) | +| Maximum state that can be persisted per Workflow instance | 100MB | 1GB | +| Maximum `step.sleep` duration | 365 days (1 year) beta | +| Maximum steps per Workflow | 256 beta | +| Maximum Workflow executions | 100,000 per day [shared with Workers daily limit](/workers/platform/limits/#worker-limits) | Unlimited | +| Concurrent Workflow instances (executions) | 25 | 1,000 beta | +| Retention limit for completed Workflow state | 3 days | 30 days 1 | + +beta This limit will be reviewed and revised during the open beta for Workflows, and we'll update this page and our changelog. + +1 Workflow state and logs will be retained for 3 days on the Workers Free plan and 30 days on the Workers Paid plan. + + diff --git a/src/content/docs/workflows/reference/pricing.mdx b/src/content/docs/workflows/reference/pricing.mdx new file mode 100644 index 000000000000000..520fdc921bc603c --- /dev/null +++ b/src/content/docs/workflows/reference/pricing.mdx @@ -0,0 +1,44 @@ +--- +pcx_content_type: concept +title: Pricing +sidebar: + order: 2 + +--- + +import { Render } from "~/components" + +# Pricing + +:::note + +Workflows is included in both the Free and Paid [Workers plans](/workers/platform/pricing/#workers). + +::: + +Workflows pricing is identical to [Workers Standard pricing](/workers/platform/pricing/#workers) and are billed on two dimensions: + +* **CPU time**: the total amount of compute (measured in milliseconds) consumed by a given Workflow. +* **Requests** (invocations): the number of Workflow invocations. [Subrequests](/workers/platform/limits/#subrequests) made from a Workflow do not incur additional request costs. + +A Workflow that is waiting on a response to an API call, paused as a result of calling `step.sleep`, or otherwise idle does not incur CPU time. + +## Frequently Asked Questions + +Frequently asked questions related to Workflows pricing: + +- Are there additional costs for Workflows? + +No. Workflows are priced based on the same compute (CPU time) and requests (invocations) as Workers. + +- Is Workflows available on the [Workers Free](/workers/platform/pricing/#workers) plan? + +Yes. + +- How does Workflows show up on my bill? + +Workflows are billed as Workers, and share the same CPU time and request SKUs. + +- Are there any limits to Workflows? + +Refer to the published [limits](/workflows/reference/limits/) documentation. diff --git a/src/content/docs/workflows/reference/storage-options.mdx b/src/content/docs/workflows/reference/storage-options.mdx new file mode 100644 index 000000000000000..312ac6fdd1cbdd3 --- /dev/null +++ b/src/content/docs/workflows/reference/storage-options.mdx @@ -0,0 +1,8 @@ +--- +pcx_content_type: navigation +title: Choose a data or storage product +external_link: /workers/platform/storage-options/ +sidebar: + order: 90 + +--- diff --git a/src/content/docs/workflows/reference/wrangler-commands.mdx b/src/content/docs/workflows/reference/wrangler-commands.mdx new file mode 100644 index 000000000000000..7253dd6bea29f10 --- /dev/null +++ b/src/content/docs/workflows/reference/wrangler-commands.mdx @@ -0,0 +1,8 @@ +--- +pcx_content_type: navigation +title: Wrangler commands +external_link: /workers/wrangler/commands/#workflows +sidebar: + order: 80 + +--- diff --git a/src/content/docs/workflows/workflows-api.mdx b/src/content/docs/workflows/workflows-api.mdx new file mode 100644 index 000000000000000..a61fb4f3c00ebff --- /dev/null +++ b/src/content/docs/workflows/workflows-api.mdx @@ -0,0 +1,8 @@ +--- +pcx_content_type: navigation +title: Workflows REST API +external_link: /api/operations/cloudflare-d1-create-database +sidebar: + order: 10 + +--- diff --git a/src/content/glossary/workflows.yaml b/src/content/glossary/workflows.yaml new file mode 100644 index 000000000000000..67692867cd73eef --- /dev/null +++ b/src/content/glossary/workflows.yaml @@ -0,0 +1,22 @@ +--- +productName: Workflows +entries: +- term: "Workflow" + general_definition: |- + The named Workflow definition, associated with a single Workers script. + +- term: "instance" + general_definition: |- + A specific instance (running, paused, errored) of a Workflow. A Workflow can have a potentially infinite number of instances. + +- term: "Step" + general_definition: |- + A 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 can have one or more steps up to the [step limit](/workflows/reference/limits/). + +- term: "Event" + general_definition: |- + The event that triggered the Workflow instance. A `WorkflowEvent` may contain optional parameters (data) that a Workflow can operate on. + +- term: "Durable Execution" + general_definition: |- + "Durable Execution" is a programming model that allows applications to execute reliably, automatically persist state, retry, and be resistant to errors caused by API, network or even machine/infrastructure failures. Cloudflare Workflows provides a way to build and deploy applications that align with this model. diff --git a/src/content/products/workflows.yaml b/src/content/products/workflows.yaml new file mode 100644 index 000000000000000..3ca59672433c4a6 --- /dev/null +++ b/src/content/products/workflows.yaml @@ -0,0 +1,33 @@ +name: Workflows + +product: + title: Workflows + url: /workflows/ + group: Developer platform + preview_tryout: true + +meta: + title: Cloudflare Workflows docs + description: Build durable, multi-step applications using the Workers platform + author: '@cloudflare' + +resources: + community: https://community.cloudflare.com/c/developers/workers/40 + dashboard_link: https://dash.cloudflare.com/?to=/:account/workers + learning_center: https://www.cloudflare.com/learning/serverless/what-is-serverless/ + discord: https://discord.com/invite/cloudflaredev + +externals: + - title: Workers home + url: https://workers.cloudflare.com + - title: Playground + url: https://workers.cloudflare.com/playground + - title: Pricing + url: https://workers.cloudflare.com/#plans + - title: Discord + url: https://discord.cloudflare.com + +algolia: + index: developers-cloudflare2 + apikey: 4edb0a6cef3338ff4bcfbc6b3d2db56b + product: workflows