update per Ryan quickstart pr and add diagram

Signed-off-by: Hannah Hunter <hannahhunter@microsoft.com>
This commit is contained in:
Hannah Hunter 2023-02-07 17:17:09 -06:00
parent 92721d33df
commit caa8db80c4
4 changed files with 216 additions and 123 deletions

View File

@ -9,7 +9,7 @@ description: "Learn how to develop and author workflows"
This article provides a high-level overview of how to author workflows that are executed by the Dapr Workflow engine.
{{% alert title="Note" color="primary" %}}
If you haven't already, [try out the workflow quickstart](todo) for a quick walk-through on how to use workflows.
If you haven't already, [try out the workflow quickstart]({{< ref workflow-quickstart.md >}}) for a quick walk-through on how to use workflows.
{{% /alert %}}

View File

@ -93,8 +93,8 @@ Want to put workflows to the test? Walk through the following quickstart and tut
| Quickstart/tutorial | Description |
| ------------------- | ----------- |
| [Workflow quickstart](link) | Description of the quickstart. |
| [Workflow tutorial](link) | Description of the tutorial. |
| [Workflow quickstart]({{< ref workflow-quickstart.md >}}) | Run a .NET workflow application with four workflow activities to see Dapr Workflow in action |
| [Workflow .NET SDK example](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow) | Learn how to create a Dapr Workflow and invoke it using ASP.NET Core web APIs. |
### Start using workflows directly in your app

View File

@ -6,70 +6,29 @@ weight: 77
description: Get started with the Dapr Workflow building block
---
Let's take a look at the Dapr [Workflow building block]({{< ref pubsub >}}). In this Quickstart, you will write workflow activities, write and register a workflow, and manage a workflow to demonstrate how Dapr enables a workflow pattern.
{{% alert title="Note" color="primary" %}}
Dapr Workflow is currently in alpha.
{{% /alert %}}
<img src="/images/pubsub-quickstart/pubsub-diagram.png" width=800 style="padding-bottom:15px;">
Let's take a look at the Dapr [Workflow building block]({{< ref workflow >}}). In this Quickstart, you'll create a simple console application to demonstrate Dapr's workflow programming model and the workflow management APIs.
Select your preferred language-specific Dapr SDK before proceeding with the Quickstart.
The `order-processor` console app starts and manages the lifecycle of the `OrderProcessingWorkflow` workflow that stores and retrieves data in a Dapr state store. The workflow consists of four workflow activities, or tasks:
- `NotifyActivity`
- `ReserveInventoryActivity`
- `ProcessPaymentActivity`
- `UpdateInventoryActivity`
{{< tabs "Python" "JavaScript" ".NET" "Java" "Go" >}}
<!-- Python -->
{{% codetab %}}
In this guide, you'll:
### Step 1: Pre-requisites
- Run the order processor application.
- Start the workflow and watch the workflow activites/tasks execute.
- Unpack the workflow logic and the workflow activities and how they're represented in the code.
For this example, you will need:
<img src="/images/workflow-quickstart-overview.png" width=800 style="padding-bottom:15px;">
- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started).
- [Python 3.7+ installed](https://www.python.org/downloads/).
<!-- IGNORE_LINKS -->
- [Docker Desktop](https://www.docker.com/products/docker-desktop)
<!-- END_IGNORE -->
Currently, you can experience Dapr Workflows using the .NET SDK.
### Step 2: Set up the environment
Clone the [sample provided in the Quickstarts repo](todo).
```bash
git clone https://github.com/dapr/quickstarts.git
```
### Step 3:
### Step 4:
### Step 5:
{{% /codetab %}}
<!-- JavaScript -->
{{% codetab %}}
### Step 1: Pre-requisites
For this example, you will need:
- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started).
- [Latest Node.js installed](https://nodejs.org/download/).
<!-- IGNORE_LINKS -->
- [Docker Desktop](https://www.docker.com/products/docker-desktop)
<!-- END_IGNORE -->
### Step 2: Set up the environment
Clone the [sample provided in the Quickstarts repo](todo).
```bash
git clone https://github.com/dapr/quickstarts.git
```
### Step 3:
### Step 4:
### Step 5:
{{% /codetab %}}
{{< tabs ".NET" >}}
<!-- .NET -->
{{% codetab %}}
@ -86,81 +45,219 @@ For this example, you will need:
### Step 2: Set up the environment
Clone the [sample provided in the Quickstarts repo](todo).
Clone the [sample provided in the Quickstarts repo](https://github.com/dapr/quickstarts/workflows).
```bash
git clone https://github.com/dapr/quickstarts.git
```
### Step 3:
### Step 4:
### Step 5:
{{% /codetab %}}
<!-- Java -->
{{% codetab %}}
### Step 1: Pre-requisites
For this example, you will need:
- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started).
- Java JDK 11 (or greater):
- [Oracle JDK](https://www.oracle.com/java/technologies/downloads), or
- OpenJDK
- [Apache Maven](https://maven.apache.org/install.html), version 3.x.
<!-- IGNORE_LINKS -->
- [Docker Desktop](https://www.docker.com/products/docker-desktop)
<!-- END_IGNORE -->
### Step 2: Set up the environment
Clone the [sample provided in the Quickstarts repo](todo).
In a new terminal window, navigate to the `order-processor` directory:
```bash
git clone https://github.com/dapr/quickstarts.git
cd workflows/csharp/sdk/order-processor
```
### Step 3:
### Step 4:
### Step 5:
{{% /codetab %}}
<!-- Go -->
{{% codetab %}}
### Step 1: Pre-requisites
For this example, you will need:
- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started).
- [Latest version of Go](https://go.dev/dl/).
<!-- IGNORE_LINKS -->
- [Docker Desktop](https://www.docker.com/products/docker-desktop)
<!-- END_IGNORE -->
### Step 2: Set up the environment
Clone the [sample provided in the Quickstarts repo](todo).
Install the dependencies:
```bash
git clone https://github.com/dapr/quickstarts.git
dotnet restore
dotnet build
```
### Step 3:
### Step 3: Run the order processor app
In the terminal, start the order processor app alongside a Dapr sidecar:
```bash
dapr run --app-id order-processor dotnet run
```
This starts the `order-processor` ID and triggers the workflow activities.
Expected output:
```
== APP == Starting workflow 6d2abcc9 purchasing 10 Cars
== APP == info: Microsoft.DurableTask.Client.Grpc.GrpcDurableTaskClient[40]
== APP == Scheduling new OrderProcessingWorkflow orchestration with instance ID '6d2abcc9' and 47 bytes of input data.
== APP == info: WorkflowConsoleApp.Activities.NotifyActivity[0]
== APP == Received order 6d2abcc9 for 10 Cars at $15000
== APP == info: WorkflowConsoleApp.Activities.ReserveInventoryActivity[0]
== APP == Reserving inventory for order 6d2abcc9 of 10 Cars
== APP == info: WorkflowConsoleApp.Activities.ReserveInventoryActivity[0]
== APP == There are: 100, Cars available for purchase
== APP == Your workflow has started. Here is the status of the workflow: Dapr.Workflow.WorkflowState
== APP == info: WorkflowConsoleApp.Activities.ProcessPaymentActivity[0]
== APP == Processing payment: 6d2abcc9 for 10 Cars at $15000
== APP == info: WorkflowConsoleApp.Activities.ProcessPaymentActivity[0]
== APP == Payment for request ID '6d2abcc9' processed successfully
== APP == info: WorkflowConsoleApp.Activities.UpdateInventoryActivity[0]
== APP == Checking Inventory for: Order# 6d2abcc9 for 10 Cars
== APP == info: WorkflowConsoleApp.Activities.UpdateInventoryActivity[0]
== APP == There are now: 90 Cars left in stock
== APP == info: WorkflowConsoleApp.Activities.NotifyActivity[0]
== APP == Order 6d2abcc9 has completed!
== APP == Workflow Status: Completed
```
### What happened?
When you ran `dapr run dotnet run`:
1. A unique order ID for the workflow is generated (in the above example, `6d2abcc9`) and the workflow is scheduled.
1. The `NotifyActivity` workflow activity sends a notification saying an order for 10 cars has been received.
1. The `ReserveInventoryActivity` workflow activity checks the inventory data, determines if you can supply the ordered item, and responds with the number of cars in stock.
1. Your workflow starts and notifies you of its status.
1. The `ProcessPaymentActivity` workflow activity begins processing payment for order `6d2abcc9` and confirms if successful.
1. The `UpdateInventoryActivity` workflow activity updates the inventory with the current available cars after the order has been processed.
1. The `NotifyActivity` workflow activity sends a notification saying that order `6d2abcc9` has completed.
1. The workflow terminates as completed.
The workflow and its activities are defined in the following sample files:
#### `order-processor/Program.cs`
In the application's program file:
- The unique order ID is generated
- The workflow is scheduled
- The workflow status is retrieved
- The workflow and the workflow activities it invokes are registered
```csharp
using Dapr.Client;
using Dapr.Workflow;
//...
{
services.AddDaprWorkflow(options =>
{
// Note that it's also possible to register a lambda function as the workflow
// or activity implementation instead of a class.
options.RegisterWorkflow<OrderProcessingWorkflow>();
// These are the activities that get invoked by the workflow(s).
options.RegisterActivity<NotifyActivity>();
options.RegisterActivity<ReserveInventoryActivity>();
options.RegisterActivity<ProcessPaymentActivity>();
options.RegisterActivity<UpdateInventoryActivity>();
});
};
//...
// Generate a unique ID for the workflow
string orderId = Guid.NewGuid().ToString()[..8];
string itemToPurchase = "Cars";
int ammountToPurchase = 10;
//...
// Start the workflow
Console.WriteLine("Starting workflow {0} purchasing {1} {2}", orderId, ammountToPurchase, itemToPurchase);
await workflowClient.ScheduleNewWorkflowAsync(
name: nameof(OrderProcessingWorkflow),
instanceId: orderId,
input: orderInfo);
//...
WorkflowState state = await workflowClient.GetWorkflowStateAsync(
instanceId: orderId,
getInputsAndOutputs: true);
Console.WriteLine("Your workflow has started. Here is the status of the workflow: {0}", state);
//...
Console.WriteLine("Workflow Status: {0}", state.RuntimeStatus);
```
#### `order-processor/Workflows/OrderProcessingWorkflow.cs`
In `OrderProcessingWorkflow.cs`, the workflow is defined as a class with all of its associated tasks (determined by workflow activities).
```csharp
using Dapr.Workflow;
//...
class OrderProcessingWorkflow : Workflow<OrderPayload, OrderResult>
{
public override async Task<OrderResult> RunAsync(WorkflowContext context, OrderPayload order)
{
string orderId = context.InstanceId;
// Notify the user that an order has come through
await context.CallActivityAsync(
nameof(NotifyActivity),
new Notification($"Received order {orderId} for {order.Quantity} {order.Name} at ${order.TotalCost}"));
string requestId = context.InstanceId;
// Determine if there is enough of the item available for purchase by checking the inventory
InventoryResult result = await context.CallActivityAsync<InventoryResult>(
nameof(ReserveInventoryActivity),
new InventoryRequest(RequestId: orderId, order.Name, order.Quantity));
// If there is insufficient inventory, fail and let the user know
if (!result.Success)
{
// End the workflow here since we don't have sufficient inventory
await context.CallActivityAsync(
nameof(NotifyActivity),
new Notification($"Insufficient inventory for {order.Name}"));
return new OrderResult(Processed: false);
}
// There is enough inventory available so the user can purchase the item(s). Process their payment
await context.CallActivityAsync(
nameof(ProcessPaymentActivity),
new PaymentRequest(RequestId: orderId, order.Name, order.Quantity, order.TotalCost));
try
{
// There is enough inventory available so the user can purchase the item(s). Process their payment
await context.CallActivityAsync(
nameof(UpdateInventoryActivity),
new PaymentRequest(RequestId: orderId, order.Name, order.Quantity, order.TotalCost));
}
catch (TaskFailedException)
{
// Let them know their payment was processed
await context.CallActivityAsync(
nameof(NotifyActivity),
new Notification($"Order {orderId} Failed! You are now getting a refund"));
return new OrderResult(Processed: false);
}
// Let them know their payment was processed
await context.CallActivityAsync(
nameof(NotifyActivity),
new Notification($"Order {orderId} has completed!"));
// End the workflow with a success result
return new OrderResult(Processed: true);
}
}
```
#### `order-processor/Activities` directory
The `Activities` directory holds the four workflow activities used by the workflow, defined in the following files:
- `NotifyActivity.cs`
- `ReserveInventoryActivity.cs`
- `ProcessPaymentActivity.cs`
- `UpdateInventoryActivity.cs`
### Step 4:
### Step 5:
{{% /codetab %}}
{{< /tabs >}}
## Tell us what you think!
@ -170,12 +267,8 @@ Join the discussion in our [discord channel](https://discord.com/channels/778680
## Next steps
- Set up Workflow using HTTP instead of an SDK.
- [Python](todo)
- [JavaScript](todo)
- [.NET](todo)
- [Java](todo)
- [Go](todo)
- Set up Workflow with any programming language using [HTTP instead of an SDK]({{< ref howto-manage-workflow.md >}})
- Walk through a more in-depth [.NET SDK example workflow](https://github.com/dapr/dotnet-sdk/tree/master/examples/Workflow)
- Learn more about [Workflow as a Dapr building block]({{< ref workflow-overview >}})
{{< button text="Explore Dapr tutorials >>" page="getting-started/tutorials/_index.md" >}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB