A Python package that provides an elegant orchestration layer for managing multiple python-statemachine instances, enabling seamless communication and coordination between state machines.
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.
- 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
pip install statemachines-orchestrator
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)
Use the Orchestrator
class to coordinate your state machines:
from statemachines_orchestrator import Orchestrator
class ECommerceOrchestrator(Orchestrator):
order: OrderStateMachine
payment: PaymentStateMachine
# 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'
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 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()
TODO
TODO
- Add tests
- Add documentation
- Publish to PyPI
- Setup GitHub Actions
- Setup Codecov
- Support Python < 3.11
- Support multiple versions of
python-statemachine
(not tested)
- Python 3.11+
- python-statemachine
- python-statemachine - The underlying state machine library this orchestrator extends
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.