Skip to main content

Python SDK for the Duroxide durable execution runtime

Project description

duroxide-python

Python SDK for the Duroxide durable execution runtime.

Write durable workflows as Python generators. The Rust runtime handles replay, persistence, and fault tolerance.

Features

  • Generator-based orchestrationsyield task descriptors, Rust handles DurableFutures
  • Activities — regular Python functions for side effects (I/O, network calls)
  • Timers — durable delays that survive process restarts
  • Events — wait for external signals
  • Sub-orchestrations — compose workflows hierarchically
  • Fan-out/Fan-inctx.all() for parallel execution, ctx.race() for first-to-complete
  • Continue-as-new — long-running orchestrations with bounded history
  • Deterministic replay — safe resume after crashes
  • SQLite & PostgreSQL — pluggable storage providers
  • Admin APIs — instance management, metrics, pruning
  • Activity client accessctx.get_client() lets activities start new orchestrations
  • Runtime metricsmetrics_snapshot() for orchestration/activity counters

Installation

pip install duroxide

Quick Start

from duroxide import SqliteProvider, Client, Runtime

# Create provider and runtime
provider = SqliteProvider.in_memory()
runtime = Runtime(provider)

# Register an activity
@runtime.register_activity("greet")
def greet(ctx, input):
    return f"Hello, {input['name']}!"

# Register an orchestration (generator function)
@runtime.register_orchestration("GreetWorkflow")
def greet_workflow(ctx, input):
    result = yield ctx.schedule_activity("greet", input)
    return result

# Start runtime and run orchestration
import threading
runtime.start()

client = Client(provider)
client.start_orchestration("greet-1", "GreetWorkflow", {"name": "World"})
status = client.wait_for_orchestration("greet-1", 10000)
print(status.output)  # "Hello, World!"

runtime.shutdown()

Orchestrations

Orchestrations are Python generator functions. They must be deterministic — no I/O, no randomness, no time.time(). Use only ctx.* methods for side effects.

@runtime.register_orchestration("MyWorkflow")
def my_workflow(ctx, input):
    # Schedule activities
    result = yield ctx.schedule_activity("DoWork", input)

    # Fan-out / Fan-in
    results = yield ctx.all([
        ctx.schedule_activity("TaskA", {"id": 1}),
        ctx.schedule_activity("TaskB", {"id": 2}),
    ])

    # Timer
    yield ctx.schedule_timer(5000)  # 5 seconds

    # Wait for external event
    approval = yield ctx.wait_for_event("approval")

    # Sub-orchestration
    sub_result = yield ctx.schedule_sub_orchestration("SubWorkflow", input)

    # Race (first to complete wins)
    winner = yield ctx.race(
        ctx.schedule_activity("Fast", None),
        ctx.schedule_timer(10000),
    )

    return {"result": result, "winner": winner}

Activities

Activities are regular Python functions that perform side effects. They run outside the replay engine and are safe for I/O operations.

@runtime.register_activity("SendEmail")
def send_email(ctx, input):
    ctx.trace_info(f"Sending email to {input['to']}")
    # ... actual email sending ...
    return {"sent": True}

PostgreSQL Provider

from duroxide import PostgresProvider, Client, Runtime

provider = PostgresProvider.connect("postgresql://user:pass@localhost:5432/mydb")
# or with custom schema:
provider = PostgresProvider.connect_with_schema("postgresql://...", "duroxide_python")

runtime = Runtime(provider)
client = Client(provider)

Admin APIs

client = Client(provider)

# Metrics
metrics = client.get_system_metrics()
depths = client.get_queue_depths()

# Instance management
instances = client.list_all_instances()
info = client.get_instance_info("instance-1")
tree = client.get_instance_tree("instance-1")

# Cleanup
client.delete_instance("instance-1", force=True)
client.prune_executions("instance-1", PyPruneOptions(keep_last=5))

Development

# Create and activate a virtual environment
python3 -m venv .venv
source .venv/bin/activate

# Install build tools and test dependencies
pip install maturin pytest

# Build the native extension and install in development mode
maturin develop

# Run all 54 tests
pytest

# Run tests with verbose output
pytest -v

# Run a single test file
pytest tests/test_e2e.py -v

# Run a single test
pytest tests/test_e2e.py::test_hello_world

# Stop on first failure
pytest -v -x

# Build release wheel
maturin build --release

After Rust source changes (src/*.rs), re-run maturin develop to rebuild. Python-only changes (python/duroxide/, tests/) take effect immediately.

Changelog

See CHANGELOG.md for release notes.

Documentation

  • User Guide — orchestration patterns, activities, providers, tracing, determinism rules
  • Architecture — PyO3 interop, GIL deadlock fix, generator driver, tracing internals

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

duroxide-0.1.2.tar.gz (71.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

duroxide-0.1.2-cp39-cp39-macosx_11_0_arm64.whl (4.4 MB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file duroxide-0.1.2.tar.gz.

File metadata

  • Download URL: duroxide-0.1.2.tar.gz
  • Upload date:
  • Size: 71.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.11.5

File hashes

Hashes for duroxide-0.1.2.tar.gz
Algorithm Hash digest
SHA256 df920c0ad9e123c2a6c0bdc1a53f95070bd4875d9f1a4ecad3de2b18468466d3
MD5 58721d9b8a24bae2d52c8e95ec3d5fa1
BLAKE2b-256 21644b21b70e7cead9b6c6e534e902cf17aa633c83bd41b9f504efcaf8a82d4b

See more details on using hashes here.

File details

Details for the file duroxide-0.1.2-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for duroxide-0.1.2-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5ccda38138b59f731f74889b2f84efa626a9ce29a8bd07e58b3f8159a7e09e30
MD5 30c93f0f848759cfe1e2e54092a0ac55
BLAKE2b-256 cf733f30730470871ed54cec9b06ee051a95f7c0b3cf8db4e54b1e0cb7bb1d9f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page