Skip to main content

Chained Multi-Domain Workflows

Welcome to the Chained Multi-Domain Workflows documentation!

While unit tests isolate individual functions, true integration testing verifies that independent microservices can communicate correctly in production. Rumour excels at orchestrating these multi-domain workflows by seamlessly passing state from one API boundary to another.

In this example, we will simulate an e-commerce checkout flow spanning three different microservices: a Users API, an Inventory API, and a Payments API.

1. The Scenario Structure

Assume we have an integration test folder set up like this:

ecommerce_integration/
├── 1_register_user.toml
├── 2_reserve_inventory.toml
├── 3_process_payment.toml
└── workspace.env.toml

Our environment file points to the three distinct microservices:

workspace.env.toml:

users_api = "https://users.swahira.internal"
inventory_api = "https://inventory.swahira.internal"
payments_api = "https://payments.swahira.internal"

2. Defining the Workflow

Step 1: User Registration

First, we interact with the Users API to create a new customer.

1_register_user.toml:

name = "Register Customer"

[request]
method = "POST"
url = "{{users_api}}/register"

[body]
type = "json"
raw = '{"email": "customer_{{random}}@swahira.io"}'

[extract]
customer_id = "json.id"

[assert]
status = 201

Step 2: Inventory Reservation

Next, we interact with the Inventory API. We must wait for customer_id from the previous step to attach the reservation to the correct user.

2_reserve_inventory.toml:

name = "Reserve Product"

[dependencies]
"1_register_user.toml" = "customer_id"

[request]
method = "POST"
url = "{{inventory_api}}/reserve"

[body]
type = "json"
raw = '{"customer_id": "{{customer_id}}", "product_sku": "SWA-PRO-1"}'

[extract]
reservation_id = "json.reservation_id"
total_amount = "json.price"

[assert]
status = 200

Step 3: Payment Processing

Finally, we call the Payments API. This node requires two dependencies: it needs the customer_id from Step 1, and the reservation_id and total_amount from Step 2.

3_process_payment.toml:

name = "Process Checkout"

[dependencies]
"1_register_user.toml" = "customer_id"
"2_reserve_inventory.toml" = ["reservation_id", "total_amount"]

[request]
method = "POST"
url = "{{payments_api}}/charge"

[body]
type = "json"
raw = '{"customer_id": "{{customer_id}}", "reservation_id": "{{reservation_id}}", "amount": {{total_amount}}}'

[assert]
status = 200
"json.payment_status" = { equal = "SUCCESS" }

3. Workflow Execution

When you execute this suite, Rumour automatically connects the dots across the different API domains, transferring the output of one microservice into the payload of the next.

rumour run ./ecommerce_integration/ -v

Execution Trace

POST https://users.swahira.internal/register
✓ SUCCESS: ./ecommerce_integration/1_register_user.toml (112ms)
POST https://inventory.swahira.internal/reserve
✓ SUCCESS: ./ecommerce_integration/2_reserve_inventory.toml (215ms)
POST https://payments.swahira.internal/charge
✓ SUCCESS: ./ecommerce_integration/3_process_payment.toml (410ms)

╭──────────────────────────────────────────────────────────────────────────╮
│ RUMOUR EXECUTION REPORT │
├──────────────────────────────────────────────────────────────────────────┤
│ Total Requests: 3
│ Successful: 3
│ Failed: 0
│ Skipped: 0
│ Success Rate: 100.0% │
│ Total Time: 737ms │
╰──────────────────────────────────────────────────────────────────────────╯

✓ Successful Requests:
- ./ecommerce_integration/1_register_user.toml [201] [112ms]
- ./ecommerce_integration/2_reserve_inventory.toml [200] [215ms]
- ./ecommerce_integration/3_process_payment.toml [200] [410ms]

By chaining workflows in this manner, you can simulate incredibly complex, asynchronous business logic in a readable, maintainable format.