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.1.tar.gz (88.4 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.1-py3-none-any.whl (37.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: chrono_daemon-0.1.1.tar.gz
  • Upload date:
  • Size: 88.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • 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":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for chrono_daemon-0.1.1.tar.gz
Algorithm Hash digest
SHA256 bd79c8bc3f28252e5d987d2f86b467074aa9bad2ae3f6c742aef25155ca061f7
MD5 172880c05bac6e937bdb4ba349458d28
BLAKE2b-256 6e3a05b75fb572ff6fe849a94ce0de0b9a45c4ed95a6a18b23c54a170868e891

See more details on using hashes here.

File details

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

File metadata

  • Download URL: chrono_daemon-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 37.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • 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":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for chrono_daemon-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 49060d43c0f982269fea7af3866bb5ed5b19a71d8de8dd4db98ca3865b2606f3
MD5 f6076fb3b38bab4807401433c1556bef
BLAKE2b-256 fe5e39521bff055860357e02bb7bcc17ae3ddc01950bd86734e6c1dfd28b880e

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