Skip to content

An extension to `python-statemachines` that allows connecting several machines together, with typechecking & IDE completions !

License

Notifications You must be signed in to change notification settings

Neikow/statemachines_orchestrator

Repository files navigation

State Machines Orchestrator

Pypi Version License Supported Python Versions Actions status pre-commit.ci status

A Python package that provides an elegant orchestration layer for managing multiple python-statemachine instances, enabling seamless communication and coordination between state machines.

Overview

The State Machines Orchestrator extends the powerful python-statemachine library by providing a declarative way to manage multiple state machines that need to interact with each other. Instead of manually wiring up communication between state machines, this orchestrator handles the coordination automatically.

Key Features

  • Automatic Dependency Injection: State machines callbacks automatically receive access to the orchestrator
  • Type-Safe: Full typing support with dataclass-like transformation
  • Clean Architecture: Separation of concerns between individual state machines and their coordination

Installation

pip install statemachines-orchestrator

Quick Start

1. Define Your State Machines

First, create your individual state machines using the standard python-statemachine approach:

from statemachine import StateMachine, State

class OrderStateMachine(StateMachine):
    # States
    pending = State(initial=True)
    processing = State()
    shipped = State()
    delivered = State(final=True)
    cancelled = State(final=True)

    # Transitions
    process = pending.to(processing)
    ship = processing.to(shipped)
    deliver = shipped.to(delivered)
    cancel = pending.to(cancelled) | processing.to(cancelled)

class PaymentStateMachine(StateMachine):
    # States
    unpaid = State(initial=True)
    authorized = State()
    captured = State(final=True)
    failed = State(final=True)
    refunded = State(final=True)

    # Transitions
    authorize = unpaid.to(authorized)
    capture = authorized.to(captured)
    fail = unpaid.to(failed) | authorized.to(failed)
    refund = captured.to(refunded)

2. Create an Orchestrator

Use the Orchestrator class to coordinate your state machines:

from statemachines_orchestrator import Orchestrator

class ECommerceOrchestrator(Orchestrator):
    order: OrderStateMachine
    payment: PaymentStateMachine

3. Use the Orchestrator

# Initialize the orchestrator with state machine instances
order_sm = OrderStateMachine()
payment_sm = PaymentStateMachine()

orchestrator = ECommerceOrchestrator(
    order=order_sm,
    payment=payment_sm
)

# Access individual machines
print(orchestrator.order.current_state)  # pending
print(orchestrator.payment.current_state)  # unpaid

# State machines can now communicate through the orchestrator.
# The orchestrator instance is automatically available in callbacks
# and other `python-statemachine` handlers

# For example, after an order is processed, the payment can be authorized:
class OrderStateMachine(StateMachine):
    ...
    def after_process(self, orc: ECommerceOrchestrator):
        orc.payment.authorize() # will move the payment state machine to 'authorized' if it's in 'unpaid'

Advanced Usage

Custom Orchestrator Name

You can customize the name used to access the orchestrator within state machine callbacks:

class ECommerceOrchestrator(Orchestrator, orchestrator_name="coordinator"):
    order: OrderStateMachine
    payment: PaymentStateMachine

# Now accessible as 'coordinator' in callbacks instead of default 'orc'

State Machine Communication

State machines can interact with each other through the orchestrator context that's automatically injected:

class OrderStateMachine(StateMachine):
    pending = State(initial=True)
    processing = State()
    done = State()

    process = pending.to(processing)
    complete = processing.to(done)

    def before_processing(self, orc: ECommerceOrchestrator):
        # Access other state machines through orchestrator
        if orc.payment.current_state.id == 'authorized':
            orc.payment.capture()

Why Use This Orchestrator?

TODO

Rationale

TODO

TODOs

  • Add tests
  • Add documentation
  • Publish to PyPI
  • Setup GitHub Actions
  • Setup Codecov
  • Support Python < 3.11
  • Support multiple versions of python-statemachine (not tested)

Requirements

Related Projects

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

An extension to `python-statemachines` that allows connecting several machines together, with typechecking & IDE completions !

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages