Distributed Durable Functions in Python
Project description
Stent
Distributed durable functions for Python. Write reliable, stateful workflows using async/await.
pip install stent
Quick Example
import asyncio
from stent import Stent, Result
@Stent.durable()
async def process_order(order_id: str) -> dict:
await asyncio.sleep(1) # Simulate work
return {"order_id": order_id, "status": "processed"}
@Stent.durable()
async def order_workflow(order_ids: list[str]) -> Result[list, Exception]:
results = []
for order_id in order_ids:
result = await process_order(order_id)
results.append(result)
return Result.Ok(results)
async def main():
backend = Stent.backends.SQLiteBackend("workflow.db")
await backend.init_db()
executor = Stent(backend=backend)
worker = asyncio.create_task(executor.serve())
exec_id = await executor.dispatch(order_workflow, ["ORD-001", "ORD-002"])
result = await executor.wait_for(exec_id)
print(result.value)
asyncio.run(main())
Why Stent?
| Feature | Temporal | Celery | Prefect | Airflow | Stent |
|---|---|---|---|---|---|
| Durable Execution | Yes | No | Partial | No | Yes |
| Setup Complexity | High | Medium | Medium | High | Very Low |
| Infrastructure | Server cluster | Broker | Server | Multi-component | SQLite/Postgres |
| Native Async | Yes | No | Yes | Limited | Yes |
Stent fills the gap between simple task queues (Celery) and enterprise platforms (Temporal):
- vs Temporal: Same durability guarantees, fraction of the infrastructure
- vs Celery/Dramatiq: True workflow durability, not just task retries
- vs Prefect/Airflow: Application workflows, not batch data pipelines
See full comparison for details.
Features
- Durable Execution - Workflow state survives crashes and restarts
- Automatic Retries - Configurable retry policies with exponential backoff
- Distributed Workers - Scale horizontally across multiple processes
- Parallel Execution - Fan-out/fan-in with
asyncio.gatherandStent.map - Rate Limiting - Control concurrent executions per function
- External Signals - Coordinate workflows with external events
- Dead Letter Queue - Inspect and replay failed tasks
- Idempotency & Caching - Prevent duplicate work
- Multiple Backends - SQLite (dev) or PostgreSQL (production)
- OpenTelemetry - Distributed tracing support
Key Concepts
from stent import Stent, RetryPolicy
# Configurable retry policies
@Stent.durable(
retry_policy=RetryPolicy(max_attempts=5, initial_delay=1.0),
queue="high_priority",
max_concurrent=10, # Rate limiting
idempotent=True, # Prevent duplicate execution
)
async def my_activity(data: dict) -> dict:
...
# Durable sleep (doesn't block workers)
await Stent.sleep("30m")
# Parallel execution
results = await asyncio.gather(*[process(item) for item in items])
# Or optimized for large batches:
results = await Stent.map(process, items)
# External signals
payload = await Stent.wait_for_signal("approval")
await executor.send_signal(exec_id, "approval", {"approved": True})
Backends
# SQLite (development)
backend = Stent.backends.SQLiteBackend("stent.db")
# PostgreSQL (production)
backend = Stent.backends.PostgresBackend("postgresql://user:pass@host/db")
# Optional: Redis for low-latency notifications
executor = Stent(
backend=backend,
notification_backend=Stent.notifications.RedisBackend("redis://localhost")
)
CLI
stent list # List executions
stent show <exec_id> # Show execution details
stent dlq list # List dead-lettered tasks
stent dlq replay <task_id> # Replay failed task
Documentation
Full documentation available in docs/:
- Getting Started | Core Concepts | Comparison
- Guides: Durable Functions | Orchestration | Error Handling | Parallel Execution | Signals | Workers | Monitoring
- Patterns: Saga | Batch Processing
- Reference: API | Configuration | Deployment
Examples
See examples/ for complete workflows:
simple_flow.py- Basic workflowsaga_trip_booking.py- Saga pattern with compensationbatch_processing.py- Fan-out/fan-inmedia_pipeline.py- Complex multi-stage pipeline
Requirements
- Python 3.12+
aiosqliteorasyncpg(backend)redis(optional, for notifications)
License
MIT
Project details
Release history Release notifications | RSS feed
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 stent-1.0.0.tar.gz.
File metadata
- Download URL: stent-1.0.0.tar.gz
- Upload date:
- Size: 79.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d0dc3c8d184d36c2b11102a23b1d5667c7bf04513e24752fca7c3f050ddf72d
|
|
| MD5 |
bf731eb5309234eccc67e43e77be31f8
|
|
| BLAKE2b-256 |
261baa98b9a56857544012c3beb967b1c4f5b4e9bfe42e76ee732cd00af13d2a
|
File details
Details for the file stent-1.0.0-py3-none-any.whl.
File metadata
- Download URL: stent-1.0.0-py3-none-any.whl
- Upload date:
- Size: 99.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1342b79cdeb61bc7aead488d7debde3e075105a633a4996d3b0820be939c3e4f
|
|
| MD5 |
67584f1fbe69ce653bb80ed2b703a4e9
|
|
| BLAKE2b-256 |
6defa8936bef655a53fa12f1bf07dd6f64b1af10f824a184aaf66ba3323f4c2a
|