Demos applications that use the Dapr Workflow building block.
-
A REST client, such as cURL, or the VSCode REST client extension.
The VSCode REST client is configured as a recommended extension when opening this repo in VSCode.
The Hello World Workflow sample is a very basic workflow with just one activity that returns a random greeting. The workflow takes a name as input and returns a greeting with the name as output.
graph TD
A[Start]
B[CreateGreetingActivity]
C[End]
A -->|"input: {name}"| B -->|"output: Hi {name}"| C
-
Change to the HelloWorld directory and build the ASP.NET app:
cd HelloWorld dotnet build
-
Run the app using the Dapr CLI:
dapr run --app-id hello-world --app-port 5065 --dapr-http-port 3500 dotnet run
Ensure the --app-port is the same as the port specified in the launchSettings.json file.
-
Start the
HelloWorldWorkflow
via the Workflow HTTP API using cURL, or use the helloworld.http file if you're using VSCode with the REST client:curl -i -X POST http://localhost:3500/v1.0-alpha1/workflows/dapr/HelloWorldWorkflow/1234a/start \ -H "Content-Type: application/json" \ -d '{ "input" : "Marc"}'
Note that
1234a
in the URL is the workflow instance ID. This can be any string you want.Expected result:
{ "instance_id": "<WORKFLOW_ID>" }
-
Check the workflow status via Workflow HTTP API:
curl -i -X GET http://localhost:3500/v1.0-alpha1/workflows/dapr/HelloWorldWorkflow/1234a/status
Expected result:
{ "WFInfo": { "instance_id": "<WORKFLOW_ID>" }, "start_time": "2023-05-01T12:15:45Z", "metadata": { "dapr.workflow.custom_status": "", "dapr.workflow.input": "\"Marc"\", "dapr.workflow.last_updated": "2023-05-01T12:15:45Z", "dapr.workflow.name": "HelloWorldWorkflow", "dapr.workflow.output": "\"Hi Marc"\", "dapr.workflow.runtime_status": "COMPLETED" } }
The OrderService Workflow sample is a workflow that processes an order. The workflow takes an order payload as input and returns an order result as output. The workflow uses these activities:
NotifyActivity
: Notifies the customer of the progress of the order.CheckInventoryActivity
: Checks if the inventory is sufficient.ProcessPaymentActivity
: Processes the payment.UpdateInventoryActivity
: Updates the inventory after checking it again.RefundPaymentActivity
: Refunds the payment if theUpdateInventoryActivity
throws an exception.
graph TD
A[Start]
B[NotifyActivity]
C[CheckInventoryActivity]
X{Sufficient Inventory?}
D[ProcessPaymentActivity]
E[UpdateInventoryActivity]
F[RefundPaymentActivity]
BB[NotifyActivity]
BBB[NotifyActivity]
XX{Sufficient Inventory?}
Z[End]
A --> |OrderPayload| B --> C
C --> X
X -->|Yes| D
X -->|"No - OrderResult(Processed:false)"| Z
D --> E --> XX
XX -->|Yes| BB --> |"OrderResult(Processed:true)"| Z
XX -->|No| BBB --> F --> |"OrderResult(Processed:false)"| Z
The CheckInventoryActivity
and UpdateInventoryActivity
classes use Dapr's state management building block to manage the inventory in a Redis state store.
Next to the workflow, this application has an InventoryController
with the following endpoints:
GET http://localhost:5064/inventory
: retrieves the inventoryDELETE http://localhost:5064/inventory
: clears the inventoryPOST http://localhost:5064/inventory/restock
: restocks the inventory
The InventoryController
also uses Dapr's state management building block.
-
Change to the OrderService directory and build the ASP.NET app:
cd OrderService dotnet build
-
Run the app using the Dapr CLI:
dapr run --app-id order-processor --app-port 5064 --dapr-http-port 3500 --resources-path ./Resources dotnet run
Ensure the --app-port is the same as the port specified in the launchSettings.json file.
-
Check the inventory using cURL, or use the OrderService.http file if you're using VSCode with the REST client:
curl -X POST http://localhost:5064/inventory/restock
If the quantity of the items is not 0, clear the inventory by running:
curl -X POST http://localhost:5064/inventory/clear
-
Try ordering 100 paperclips while the inventory is not sufficient. Start the
OrderProcessingWorkflow
via the Workflow HTTP API:curl -i -X POST http://localhost:3500/v1.0-alpha1/workflows/dapr/OrderProcessingWorkflow/1234a/start \ -H "Content-Type: application/json" \ -d '{ "input" : {"Name": "Paperclips", "Quantity": 100}}'
Note that
1234a
in the URL is the workflow instance ID. This can be any string you want.Expected result:
{ "instance_id": "<WORKFLOW_ID>" }
Pay attention to the console output. A message will appear that indicates the inventory is insufficient.
-
Check the workflow status via Workflow HTTP API:
curl -i -X GET http://localhost:3500/v1.0-alpha1/workflows/dapr/OrderProcessingWorkflow/1234a/status
Expected result:
{ "WFInfo": { "instance_id": "<WORKFLOW_ID>" }, "start_time": "2023-05-01T12:15:45Z", "metadata": { "dapr.workflow.custom_status": "\"Stopped order process due to insufficient inventory.\"", "dapr.workflow.input": "{\"Name\":\"Paperclips\",\"Quantity\":100}", "dapr.workflow.last_updated": "2023-05-01T12:15:45Z", "dapr.workflow.name": "OrderProcessingWorkflow", "dapr.workflow.output": "{\"Processed\":false}", "dapr.workflow.runtime_status": "COMPLETED" } }
Depending on how quick the status is retrieved after starting the workflow, the
dapr.workflow.runtime_status
could still be"RUNNING"
. Repeat the GET status request until the status is"COMPLETED"
. -
Restock the inventory:
curl -X POST http://localhost:5064/inventory/restock
Expected result:
HTTP 200 OK
-
Try ordering paperclips again, now within the limits of the inventory. Start the
OrderProcessingWorkflow
via the Workflow HTTP API:curl -i -X POST http://localhost:3500/v1.0-alpha1/workflows/dapr/OrderProcessingWorkflow/1234b/start \ -H "Content-Type: application/json" \ -d '{ "input" : {"Name": "Paperclips", "Quantity": 100}}'
Note that
1234b
in the URL is the workflow instance ID. This can be any string you want.Expected result:
{ "instance_id": "<WORKFLOW_ID>" }
Pay attention to the console output. Messages will appear that indicate the inventory is sufficient and payment has been processed successfully.
-
Check the workflow status via Workflow HTTP API:
curl -i -X GET http://localhost:3500/v1.0-alpha1/workflows/dapr/OrderProcessingWorkflow/1234b/status
Expected result:
{ "WFInfo": { "instance_id": "<WORKFLOW_ID>" }, "start_time": "2023-05-01T12:22:25Z", "metadata": { "dapr.workflow.custom_status": "", "dapr.workflow.input": "{\"Name\":\"Paperclips\",\"Quantity\":100}", "dapr.workflow.last_updated": "2023-05-01T12:22:37Z", "dapr.workflow.name": "OrderProcessingWorkflow", "dapr.workflow.output": "{\"Processed\":true}", "dapr.workflow.runtime_status": "COMPLETED" } }
-
Inspect the logs in ZipKin:
localhost:9411/zipkin
. Find the entry markedorder-processor:create_orchestration||orderprocessingworkflow
and show the details. You'll now see a timeline of the workflow at the top, and the activities underneath.
Any questions or comments about this sample? Join the Dapr discord and post a message the #workflow
channel.
Have you made something with Dapr? Post a message in the #show-and-tell
channel, we love to see your creations!