Skip to main content

Tiny anyio-based concurrency primitives: Channel, Clock (wall + sim), Daemon, Supervisor.

Project description

chrono-daemon

CI PyPI Python 3.11+ License: MIT

chrono-daemon is a small Python library for long-running async components whose time can be replayed deterministically. It wraps anyio with four primitives:

  • Channel[T]: typed single-producer / single-consumer queues.
  • Clock: real time with WallClock, virtual time with SimClock.
  • Daemon: a lifecycle unit with on_start, run, and on_stop.
  • Supervisor: a structured-concurrency root for hosting daemons.

The practical payoff is simple: production daemons sleep on ctx.clock; tests swap in SimClock and advance seconds of work without waiting for wall time.

Quick Example

from chrono_daemon import Channel, Context, SimClock, Supervisor, daemon, open_channel

@daemon
async def producer(ctx: Context, out: Channel[int]) -> None:
    for i in range(10):
        await ctx.clock.sleep(0.1)
        await out.send.send(i)
    await out.send.aclose()

@daemon
async def consumer(ctx: Context, src: Channel[int]) -> None:
    async for item in src.recv:
        ctx.logger.info("got %d", item)

async def main() -> None:
    ch: Channel[int] = open_channel(maxsize=4)
    clock = SimClock()
    async with Supervisor(clock=clock) as sup:
        sup.add(producer(ch))
        sup.add(consumer(ch))
        await clock.advance(1.5)  # replay 1.5 s of work immediately

Why Use It

  • Time-dependent async code is testable without sleeps, polling, or fake task schedulers.
  • Wiring is explicit. Every edge is a named SPSC channel, so ownership and backpressure stay visible.
  • Lifecycle behavior is structured. Daemons get startup, shutdown, logging, cancellation, and error policy in one place.
  • The core runtime is small: pure Python, anyio underneath, and no runtime dependency beyond anyio.

Core API

What it is
Channel[T] typed bounded SPSC queue, the only inter-daemon communication primitive
Clock WallClock (real time) or SimClock (deterministic, burst advance(dt) / advance_to(t))
Daemon long-running async unit; on_start / run / on_stop hooks. Use a subclass or the @daemon decorator
Supervisor async with Supervisor(...) structured-concurrency root; hosts daemons, dispatches errors (shutdown / restart / ignore)

See docs/concepts.md for details.

Scope

chrono-daemon is for in-process async systems where explicit wiring and deterministic time matter: evaluation loops, agent pipelines, robotics-style control mocks, and testable service internals.

It is intentionally not a topic broker, service registry, RPC framework, parameter server, CLI launcher, network runtime, or continuous-time numerical simulator.

Install / dev

uv sync --dev --extra zmq
make check        # ruff + pyrefly
make test         # pytest on asyncio + trio
make all          # format + check + test

Python 3.11+. Only runtime dependency is anyio>=4; --extra zmq installs the optional transport dependencies needed for the full test suite. Remote ZMQ channels are optional:

pip install "chrono-daemon[zmq]"

Where to look next

  • docs/concepts.md: what each primitive is and the invariants the test suite pins.
  • docs/adr/: why each decision looks the way it does (Topic-less, on-error-shutdown by default, anyio-only).
  • docs/recipes.md: patterns kept off the core surface but importable under chrono_daemon.recipes.*, grouped as routing, coordination, state, buffering, and hosting helpers under src/chrono_daemon/recipes/.
  • examples/: runnable System 2/1/0 demos and notes.

Status

Early. In-process channels are the default and keep zero runtime dependencies beyond anyio. ZMQ remote channels are available as an optional extra (chrono-daemon[zmq]) for asyncio-backed deployments.

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

chrono_daemon-0.1.0.tar.gz (112.0 kB view details)

Uploaded Source

Built Distribution

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

chrono_daemon-0.1.0-py3-none-any.whl (37.4 kB view details)

Uploaded Python 3

File details

Details for the file chrono_daemon-0.1.0.tar.gz.

File metadata

  • Download URL: chrono_daemon-0.1.0.tar.gz
  • Upload date:
  • Size: 112.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for chrono_daemon-0.1.0.tar.gz
Algorithm Hash digest
SHA256 79845ed5ade533dc362f14307154e495b7bfec82aeaa41b2175aaa2ad4a49120
MD5 977c20affc040f66741a9ea2beea7623
BLAKE2b-256 4bc9aa0198aaa5cc73f853244caccabcb973ff4d44b2a72553889de6b175b6bd

See more details on using hashes here.

File details

Details for the file chrono_daemon-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: chrono_daemon-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 37.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for chrono_daemon-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c8fe78cb7a8e04fba20e4c79e6b69e14e82e2cd68f270d13bc4958c1efd5157f
MD5 790fe154892cd312941064739d963005
BLAKE2b-256 cca3e23c804cd5d061b13fbea0973ba91b25ba5d6d1e5827a20acdb422e0915e

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