Skip to main content

No project description provided

Project description

🌀 Duron

Duron is a Python library that makes async work replayable. You can pause, resume, or rerun async functions without redoing completed steps. Wrap your side effects once, keep orchestration deterministic, and Duron logs every result so repeated runs stay safe.

Why Duron?

  • 🔁 Restart-safe — Rerun a job and Duron replays prior results automatically. No duplicate work.
  • 🧵 Async-first — Write async def functions and orchestrate them with familiar await syntax.
  • 🔍 Typed & traceable — Decorators capture type hints so inputs and outputs serialize cleanly.
  • 🗄️ Storage-agnostic — Start with file-based logging or plug in your own backend to match your stack.
  • 🚀 Drop-in ready — Works in CLI tools, web backends, or long-lived agents—no special runtime or extra dependencies required.

Install

Duron requires Python 3.10+.

pip install git+https://github.com/brian14708/duron.git

Quickstart

Duron defines two kinds of functions:

  • @duron.durable — deterministic orchestration. It replays from logs, ensuring that control flow only advances when every prior step is known.
  • @duron.effect — side effects. Wrap anything that touches the outside world (APIs, databases, file I/O). Duron records its return value so it runs once per unique input.
import asyncio
import random
from pathlib import Path

import duron
from duron.contrib.storage import FileLogStorage


@duron.effect
async def work(name: str) -> str:
    print("⚡ Preparing to greet...")
    await asyncio.sleep(2)  # Simulate I/O
    print("⚡ Greeting...")
    return f"Hello, {name}!"


@duron.effect
async def generate_lucky_number() -> int:
    print("⚡ Generating lucky number...")
    await asyncio.sleep(1)  # Simulate I/O
    return random.randint(1, 100)


@duron.durable
async def greeting_flow(ctx: duron.Context, name: str) -> str:
    message, lucky_number = await asyncio.gather(
        ctx.run(work, name), ctx.run(generate_lucky_number)
    )
    return f"{message} Your lucky number is {lucky_number}."


async def main():
    async with greeting_flow.invoke(FileLogStorage(Path("log.jsonl"))) as job:
        await job.start("Alice")
        result = await job.wait()
    print(result)


if __name__ == "__main__":
    asyncio.run(main())

To see Duron handle live input and external events, check out examples/agent.py.

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

duron-0.0.1.tar.gz (29.9 kB view details)

Uploaded Source

Built Distribution

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

duron-0.0.1-py3-none-any.whl (41.8 kB view details)

Uploaded Python 3

File details

Details for the file duron-0.0.1.tar.gz.

File metadata

  • Download URL: duron-0.0.1.tar.gz
  • Upload date:
  • Size: 29.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.3

File hashes

Hashes for duron-0.0.1.tar.gz
Algorithm Hash digest
SHA256 0d6b0b01c477b77c8a559db9211a29c20aa8fd38a7c405567c723a5928aa7fb3
MD5 4ab5acb856b6f8928886ec0e3a246f64
BLAKE2b-256 4ef365d2b03956d3475beb077fee8581aa4ab88ab591aa415b8e510c609cc5b5

See more details on using hashes here.

File details

Details for the file duron-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: duron-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 41.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.3

File hashes

Hashes for duron-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 016cabc965029d422795e6f2229ce5a637b2ed9c775636e606d1bad7c26f19d8
MD5 1e94cdf7ffbc3eec04939229fdaf267a
BLAKE2b-256 242947a493597088a2c8a781ba74d2f25d352e93aba6afcd166feb0bda3769d0

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