Add fundamentals example for Python

Signed-off-by: Marc Duiker <marcduiker@users.noreply.github.com>
This commit is contained in:
Marc Duiker 2025-05-06 15:42:26 +02:00
parent 412303d15c
commit 757d318d8a
No known key found for this signature in database
GPG Key ID: 6A36EA7754473DD7
7 changed files with 151 additions and 0 deletions

View File

@ -0,0 +1,80 @@
# Workflow Basics
This tutorial covers the fundamentals of authoring Dapr Workflows. For more information about the fundamentals of Dapr Workflows, see the [Dapr docs](https://docs.dapr.io/developing-applications/building-blocks/workflow/workflow-features-concepts/).
## Inspect the code
Open the `basic_workflow.py` file in the `tutorials/workflow/python/fundamentals/basic` folder. This file contains the definition for the workflow.
The workflow consists of two activities: `activity1` and `activity2`, which are called in sequence, where the result of `activity1` is used as an input for `activity2`. You can find the activity definitions below the workflow definition.
```mermaid
graph LR
SW((Start
Workflow))
A1[activity1]
A2[activity2]
EW((End
Workflow))
SW --> A1
A1 --> A2
A2 --> EW
```
## Run the tutorial
1. Use a terminal to navigate to the `tutorials/workflow/python/fundamentals/basics` folder.
2. Install the dependencies using pip:
```bash
pip3 install -r requirements.txt
```
3. Navigate one level back to the `fundamentals` folder and use the Dapr CLI to run the Dapr Multi-App run file
<!-- STEP
name: Run multi app run template
expected_stdout_lines:
- 'Started Dapr with app id "basic"'
expected_stderr_lines:
working_dir: .
output_match_mode: substring
background: true
sleep: 15
timeout_seconds: 30
-->
```bash
dapr run -f .
```
<!-- END_STEP -->
4. Use the POST request in the [`fundamentals.http`](./fundamentals.http) file to start the workflow, or use this cURL command:
```bash
curl -i --request POST http://localhost:5254/start/One
```
Note the `instance_id` property in the response. This property contains the workflow instance ID. You can use this ID to get the status of the workflow instance you just started.
The input for the workflow is a string with the value `One`. The expected app logs are as follows:
```text
== APP - basic == activity1: Received input: One.
== APP - basic == activity2: Received input: One Two.
```
5. Use the GET request in the [`fundamentals.http`](./fundamentals.http) file to get the status of the workflow, or use this cURL command:
```bash
curl --request GET --url http://localhost:3554/v1.0/workflows/dapr/<INSTANCEID>
```
Where `<INSTANCEID>` is the workflow instance ID you received in the `Location` header in the previous step.
The expected serialized output of the workflow is:
```txt
"\"One Two Three\""
```
6. Stop the Dapr Multi-App run process by pressing `Ctrl+C`.

View File

@ -0,0 +1,23 @@
from fastapi import FastAPI, status
from dapr.ext.workflow import DaprWorkflowClient
from basic_workflow import wf_runtime, basic_workflow
import uvicorn
app = FastAPI()
@app.post("/start/{input}", status_code=status.HTTP_202_ACCEPTED)
async def start_workflow(input: str):
"""
The DaprWorkflowClient is the API to manage workflows.
Here it is used to schedule a new workflow instance.
"""
wf_client = DaprWorkflowClient()
instance_id = wf_client.schedule_new_workflow(
workflow=basic_workflow,
input=input
)
return {"instance_id": instance_id}
if __name__ == "__main__":
wf_runtime.start()
uvicorn.run(app, host="0.0.0.0", port=5254)

View File

@ -0,0 +1,21 @@
from dapr.ext.workflow import DaprWorkflowContext, WorkflowActivityContext, WorkflowRuntime
wf_runtime = WorkflowRuntime()
@wf_runtime.workflow(name='basic_workflow')
def basic_workflow(ctx: DaprWorkflowContext, wf_input: str):
result1 = yield ctx.call_activity(activity1, input=wf_input)
result2 = yield ctx.call_activity(activity2, input=result1)
return result2
@wf_runtime.activity(name='activity1')
def activity1(ctx: WorkflowActivityContext, input):
print(f'activity1: Received input: {input}.')
return f"{input} Two"
@wf_runtime.activity(name='activity2')
def activity2(ctx: WorkflowActivityContext, input):
print(f'activity2: Received input: {input}.')
return f"{input} Three"

View File

@ -0,0 +1,2 @@
dapr>=1.15.0
dapr-ext-workflow>=1.15.0

View File

@ -0,0 +1,11 @@
version: 1
common:
resourcesPath: ../../resources
apps:
- appID: basic
appDirPath: basic
appPort: 5254
daprHTTPPort: 3554
command: ["python3", "app.py"]
appLogDestination: console
daprdLogDestination: console

View File

@ -0,0 +1,12 @@
@apphost=http://localhost:5254
### Start the basic workflow
# @name startWorkflowRequest
@input=One
POST {{ apphost }}/start/{{ input }}
@instanceId={{startWorkflowRequest.response.body.instance_id}}
@daprHost=http://localhost:3554
### Get the workflow status
GET {{ daprHost }}/v1.0/workflows/dapr/{{ instanceId }}

View File

@ -0,0 +1,2 @@
include ../../../../docker.mk
include ../../../../validate.mk