larzstate
Durable workflows, sagas, and state machines. Pure Python, zero dependencies.
Two complementary tools for modelling processes that must stay correct even when things crash:
Workflow— an ordered pipeline of steps with durable, resumable execution. Progress is checkpointed after every step, so an interrupted run resumes exactly where it stopped. Steps retry on failure, and a failed workflow compensates (rolls back) its completed steps in reverse — the saga pattern.StateMachine— a finite state machine with guards, actions, and enter/exit callbacks, defined as plain data.
No broker and no database required — bring your own checkpoint store (memory or file, or plug in larzdb).
from larzstate import Workflow
wf = Workflow("checkout")
@wf.step(retries=3)
def reserve(ctx):
ctx["reservation"] = reserve_stock(ctx["items"])
@reserve.compensate
def _(ctx):
release_stock(ctx["reservation"])
@wf.step()
def charge(ctx):
ctx["charge_id"] = charge_card(ctx["amount"])
result = wf.run("order-123", {"items": [...], "amount": 100})
result.status # "completed" — or WorkflowFailed (after rollback)
Why
- Crash-resumable. Kill the process mid-workflow and call
run(run_id)again — completed steps are skipped, execution continues from the first unfinished one. State is checkpointed (and fsync'd, withFileStore) after every step. - Sagas built in. When something fails partway through, the compensations of already-completed steps run in reverse to undo their effects — the standard way to get "all-or-nothing" across systems that don't share a transaction.
- Retries per step. Set
retries(and optionalretry_delay) per step. - Zero dependencies, no infrastructure. No Temporal server, no queue, no DB. A directory (or memory) is enough.
- A clean state machine too. Guards, actions, enter/exit hooks, wildcard transitions, history — as plain, inspectable data.
Install
pip install larzstate
Durable workflows
from larzstate import Workflow, FileStore, WorkflowFailed
wf = Workflow("payment", store=FileStore("workflows/"))
@wf.step(retries=2)
def authorize(ctx): ctx["auth"] = gateway.authorize(ctx["amount"])
@authorize.compensate
def _(ctx): gateway.void(ctx["auth"])
@wf.step()
def capture(ctx): ctx["capture"] = gateway.capture(ctx["auth"])
try:
wf.run("txn-42", {"amount": 5000})
except WorkflowFailed as e:
e.step # which step failed
e.cause # the exception
e.compensated # whether rollback ran
- The shared, mutable
ctxdict flows through every step and is part of the checkpoint, so resumed runs see the same state. - On resume, pass just the
run_id— the checkpointed context is authoritative.
State machines
from larzstate import StateMachine
sm = StateMachine(initial="draft", transitions=[
{"event": "submit", "from": "draft", "to": "review"},
{"event": "approve", "from": "review", "to": "published",
"guard": lambda m, **k: k["by"] == "editor"},
{"event": "archive", "from": "*", "to": "archived"},
])
sm.trigger("submit") # -> "review"
sm.can("approve") # True
sm.trigger("approve", by="editor") # guard passes -> "published"
sm.history # ["draft", "review", "published"]
Supports guard, action, on_enter/on_exit callbacks, wildcard from: "*",
and allowed_events().
Scope
larzstate runs workflows in-process — it's the durable orchestration core, not a distributed cluster. Pair it with larztask to run workflows off a queue, or larzdb as a store. It gives you exactly-once-ish step semantics via checkpointing and idempotent resume — the hard part — without any infrastructure.
Tests
python -m unittest discover -s tests -v # 16 tests incl. crash-resume + saga
The Larz stack
Pure-Python, zero-dependency building blocks:
- larz — money-native web framework
- larzchain — from-scratch PoW blockchain
- larzmoney — exact, penny-perfect money
- larzcrypt — pure-Python cryptography toolkit
- larzdb — crash-safe embedded database
- larzagent — zero-dep AI agent framework
- larzchart — data to inline SVG charts
- larzmark — Markdown + SEO static sites
- larztask — durable background job queue
- larzvault — encrypted secrets manager
- larzvm — deterministic gas-metered VM
- larzcache — LRU/TTL/tiered caching
- larzvalidate — schema validation
- larzid — decentralized identity
- larzrpc — JSON-RPC over HTTP
- larzstate — this library
License
MIT © larz-scripter
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file larzstate-0.1.0.tar.gz.
File metadata
- Download URL: larzstate-0.1.0.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a868d01cfd6b16f2b82c3921bf553c458c9d6819e39dd73da4f6a71d62c8f3f1
|
|
| MD5 |
b5e57c25c3c2eb4243b0f4a3b1a34623
|
|
| BLAKE2b-256 |
b20826e9c9fc6674d6e30aebb4a3f4fe08d89c131cd0d0b257ff21bf91271441
|
File details
Details for the file larzstate-0.1.0-py3-none-any.whl.
File metadata
- Download URL: larzstate-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ecfd5c8fbb5d720a85a60c6b9f011d0cf507d8ebeb54b5f98a1203f50d745d6
|
|
| MD5 |
78523b6f01c5037d69fcaf17f32eb1de
|
|
| BLAKE2b-256 |
c29499131fb6ea7bc070300d986b9e550ca12ab9317a6c07bfc9db0c9125cad7
|