quickstarts/tutorials/workflow/python/combined-patterns
Marc Duiker bde040a9e4
Update tutorials/workflow/python/combined-patterns/dapr.yaml
Co-authored-by: Alice Gibbons <alicejgibbons@gmail.com>
Signed-off-by: Marc Duiker <marcduiker@users.noreply.github.com>
2025-05-20 07:52:29 +02:00
..
resources Add combined patterns (WIP) 2025-05-09 18:52:24 +02:00
shipping_app Clean up 2025-05-14 11:35:51 +00:00
workflow_app Fix workflow serialization 2025-05-15 11:00:56 +00:00
README.md Update log output 2025-05-15 07:50:31 +00:00
dapr.yaml Update tutorials/workflow/python/combined-patterns/dapr.yaml 2025-05-20 07:52:29 +02:00
makefile Add combined patterns (WIP) 2025-05-09 18:52:24 +02:00
order-workflow.http Update log output 2025-05-15 07:50:31 +00:00

README.md

Combined Workflow Patterns

This tutorial demonstrates how several workflow patterns can be combined in a single, more realistic, workflow. Some of the workflow activities are using other Dapr APIs, such as state management, service invocation, and Pub/Sub.

Inspect the code

The demo consist of two applications:

  • workflow_app is the main application that orchestrates an order process in the order_workflow.
  • shipping_app is a supporting service that is being called by the order_workflow.

The order_workflow combines task chaining, fan-out/fan-in, and waiting for external event patterns. The workflow contains a number of activities for order processing including checking inventory, register shipment, process payment and more with a final order status being returned with the results of the order. It uses compensating logic in case the shipment fails to get registered and the customer needs to be reimbursed for the payment.

graph LR
   SW((Start
   Workflow))
   EW((End
    Workflow))
   subgraph order_workflow
   direction LR
    CHKI[Check inventory]
    CHKD[Check shipping
    destination]
    IF1{Success?}
    PAY[Process
    payment]
    UPD[Update
    inventory]
    REG[Register
    shipment]
    WAIT[Wait for
    confirmation]
    IF2{Success?}
    RI[Reimburse
    customer]
   end
   subgraph Shipping
    direction LR
    REG2[register_shipment]
    CHKD2[check_destination]
   end
    SW --> CHKI
    SW --> CHKD <--> CHKD2
    CHKI --> IF1
    CHKD --> IF1
    IF1 --> PAY
    PAY --> UPD
    UPD --> REG -.->|pub/sub| REG2
    REG2 -.->|pub/sub| WAIT
    REG --> WAIT
    WAIT --> IF2
    IF2 -->|Yes| EW
    IF2 -->|No| RI
    RI --> EW

Run the tutorial

  1. Use a terminal to navigate to the tutorials/workflow/python/combined-patterns folder.

  2. Install the dependencies using pip:

    cd workflow_app
    pip3 install -r requirements.txt
    cd ..
    cd shipping_app
    pip3 install -r requirements.txt
    cd ..
    
  3. Use the Dapr CLI to run the Dapr Multi-App run file. This starts both applications order-workflow and shipping with the Dapr components in the resources folder.

    ```bash
    

    dapr run -f .

    <!-- END_STEP -->
    
    
  4. Use the POST request in the order-workflow.http file to start the workflow, or use this cURL command:

    curl -i --request POST \
    --url http://localhost:5260/start \
    --header 'content-type: application/json' \
    --data '{"id": "b0d38481-5547-411e-ae7b-255761cce17a","order_item" : {"product_id": "RBD001","product_name": "Rubber Duck","quantity": 10,"total_price": 15.00},"customer_info" : {"id" : "Customer1","country" : "The Netherlands"}}'
    

    The input for the workflow is an Order object:

    {
        "id": "b0d38481-5547-411e-ae7b-255761cce17a",
        "order_item" : {
            "product_id": "RBD001",
            "product_name": "Rubber Duck",
            "quantity": 10,
            "total_price": 15.00
        },
        "customer_info" : {
            "id" : "Customer1",
            "country" : "The Netherlands"
        }
    }
    

    The app logs should come from both services executing all activities as follows:

    == APP - order-workflow == start: Received input: id='b0d38481-5547-411e-ae7b-255761cce17a' order_item=OrderItem(product_id='RBD001', product_name='Rubber Duck', quantity=10, total_price=15.0) customer_info=CustomerInfo(id='Customer1', country='The Netherlands')
    == APP - order-workflow == order_workflow: Received order id: b0d38481-5547-411e-ae7b-255761cce17a.
    == APP - order-workflow == check_shipping_destination: Received input: id='Customer1' country='The Netherlands'.
    == APP - order-workflow == check_inventory: Received input: product_id='RBD001' product_name='Rubber Duck' quantity=10 total_price=15.0.
    == APP - order-workflow == get_inventory_item: product_id='RBD001' product_name='Rubber Duck' quantity=50
    == APP - shipping == checkDestination: Received input: id='Customer1' country='The Netherlands'.
    == APP - order-workflow == process_payment: Received input: id='b0d38481-5547-411e-ae7b-255761cce17a' order_item=OrderItem(product_id='RBD001', product_name='Rubber Duck', quantity=10, total_price=15.0) customer_info=CustomerInfo(id='Customer1', country='The Netherlands').
    == APP - order-workflow == order_workflow: Payment result: is_success=True.
    == APP - order-workflow == update_inventory: Received input: product_id='RBD001' product_name='Rubber Duck' quantity=10 total_price=15.0.
    == APP - order-workflow == get_inventory_item: product_id='RBD001' product_name='Rubber Duck' quantity=50
    == APP - order-workflow == register_shipment: Received input: id='b0d38481-5547-411e-ae7b-255761cce17a' order_item=OrderItem(product_id='RBD001', product_name='Rubber Duck', quantity=10, total_price=15.0) customer_info=CustomerInfo(id='Customer1', country='The Netherlands').
    == APP - shipping == registerShipment: Received input: id='b0d38481-5547-411e-ae7b-255761cce17a' order_item=OrderItem(product_id='RBD001', product_name='Rubber Duck', quantity=10, total_price=15.0) customer_info=CustomerInfo(id='Customer1', country='The Netherlands').
    == APP - order-workflow == shipmentRegistered: Received input: order_id='b0d38481-5547-411e-ae7b-255761cce17a' is_success=True message=None.
    
  5. Use the GET request in the order-workflow.http file to get the status of the workflow, or use this cURL command:

    curl --request GET --url http://localhost:3560/v1.0/workflows/dapr/b0d38481-5547-411e-ae7b-255761cce17a
    

    The expected serialized output of the workflow is:

    {\"is_success\":true,\"message\":\"Order b0d38481-5547-411e-ae7b-255761cce17a processed successfully.\"}"
    

    If the order-workflow.http is used, the order_id is generated when making the request and is different each time.

  6. Stop the Dapr Multi-App run process by pressing Ctrl+C.