Skip to main content

🌊 hexastack-flow

Hexagonal workflow engine adapter integrating hexaflow with Hexastack CQRS, Relational Persistence, and Event Streaming.


🎯 Architectural Intent

hexastack-flow provides first-class hexagonal adapters connecting the lightweight hexaflow workflow engine to Hexastack:

  1. CQRS Bridge: CommandStep and QueryStep allow workflow steps to dispatch typed commands and queries directly onto the CommandBus and QueryBus, inheriting all CQRS middleware (auth, tracing, logging, metrics, retries).
  2. Durable Distributed Sagas: Workflows natively subsume the Saga pattern by pairing forward command execution stages with compensating rollback stages, backed by durable checkpoints.
  3. Enterprise Persistence: SqlAlchemyWorkflowStore persists workflow execution records and step checkpoints directly to PostgreSQL/SQLite/MySQL within transactional boundaries.
  4. Event Streaming: Emits domain events (WorkflowStartedEvent, WorkflowStepCompletedEvent, WorkflowSuspendedEvent, WorkflowCompletedEvent, WorkflowAbortedEvent) wrapped in standard CloudEventEnvelopes through hexastack-events.
  5. DevTools Visualizer: Backing engine for NiceGUI and Textual DAG monitoring.

🔄 Implementing the Saga Pattern as a Workflow

Historically, the Saga Pattern structures a distributed business transaction across multiple microservices or bounded contexts as a sequence of local transactions:

  • Forward transactions: $T_1, T_2, \dots, T_n$
  • Compensating transactions: $C_{k-1}, \dots, C_1$ executed in reverse (LIFO) order if step $k$ fails.

In hexastack-flow, you do not need a separate, restricted saga engine. A Saga is simply a workflow DAG that dispatches CQRS commands and executes compensating commands on failure.

Example: Trip Booking Saga with CQRS & Hexaflow

from hexaflow import Workflow
from hexastack_cqrs.ports.buses import CommandBusPort
from hexastack_flow.adapters.cqrs.runner import CqrsWorkflowRunner
from hexastack_flow.adapters.cqrs.steps import as_command_step

# 1. Define CQRS commands for forward actions & compensations
from my_domain.commands import (
    BookFlightCommand,
    CancelFlightCommand,
    BookHotelCommand,
    CancelHotelCommand,
    ChargePaymentCommand,
)

def build_trip_booking_workflow(bus: CommandBusPort, customer_id: str) -> Workflow:
    """Construct a durable distributed saga as a hexaflow Workflow."""
    workflow = (
        Workflow("trip-booking-saga")
        # Step 1: Reserve Flight
        .stage(
            "flight",
            as_command_step(
                lambda ctx: BookFlightCommand(customer_id=customer_id, destination="JFK"),
                bus,
                name="book_flight",
            ),
        )
        # Step 2: Reserve Hotel (runs after flight is confirmed)
        .stage(
            "hotel",
            as_command_step(
                lambda ctx: BookHotelCommand(customer_id=customer_id, room_type="deluxe"),
                bus,
                name="book_hotel",
            ),
            depends_on=["flight"],
        )
        # Step 3: Process Payment
        .stage(
            "payment",
            as_command_step(
                lambda ctx: ChargePaymentCommand(customer_id=customer_id, amount_cents=50000),
                bus,
                name="charge_payment",
            ),
            depends_on=["hotel"],
        )
    )
    return workflow

# 2. Execute via CqrsWorkflowRunner (with durable DB checkpoints)
runner = CqrsWorkflowRunner(engine=engine)
result = await runner.run(workflow.build())

Why Workflows are Superior to Linear Sagas

Feature Legacy In-Memory Saga hexastack-flow Workflow
Execution Topologies Strictly sequential ($T_1 \to T_2 \to T_3$) Arbitrary DAGs (e.g. reserve Flight & Hotel in parallel)
Crash Recovery In-memory only (lost if process restarts) Durable Checkpoints (SqlAlchemyWorkflowStore)
Step Retries Manual loop or fail immediately Configurable RetryPolicy (exponential backoff, jitter)
Observability Console logs CloudEvents (WorkflowStepCompletedEvent) + OTel spans
Human-in-the-Loop Not supported Pause / Resume (engine.suspend(), engine.resume())

📦 Installation

pip install hexastack[flow]

Or standalone:

pip install hexastack-flow

📄 License

Apache 2.0

Metadata

Release files for hexastack-flow 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hexastack-flow 0.6.0
File Size Uploaded
hexastack_flow-0.6.0.tar.gz 13.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hexastack-flow 0.6.0
File Interpreter ABI Platform
hexastack_flow-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.1 kB

Release files / hexastack_flow-0.6.0.tar.gz

Download URL hexastack_flow-0.6.0.tar.gz
Size 13.1 kB
Tags Source
SHA-256 checksum
How to use checksums
5d3301b3180a291c0b113821a8d62541752bd989b107f55fbc109bf7a04e2de5
BLAKE2b-256 checksum
How to use checksums
1c77772da53ac93d62cf3a0260af8616c0b1fc7c03ab9ec2488482b208f488b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / hexastack_flow-0.6.0-py3-none-any.whl

Download URL hexastack_flow-0.6.0-py3-none-any.whl
Size 21.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2f896bc23a3278023c6e94224b29a29f182e93eb9841d42994a68f225c68ac7c
BLAKE2b-256 checksum
How to use checksums
05c26197d48c9550b54626889ea69badcd322571d775efb6583fe269af606577
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

0.8.0

2 release files

0.7.0

2 release files

This release

0.6.0 This release

2 release files

0.5.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page