tokio-reactor-trait

Implements reactor-trait's Reactor, TimeReactor, and TcpReactor interfaces on top of Tokio, letting runtime-agnostic async libraries plug in Tokio as their backend.

Library
Cargo
v4.1.1
3stars
Apache-2.0 OR MIT

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
17/100Needs Attention
Development Activity0
Maintenance0
Community8
Maturity60
Momentum0

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
51/100Fair
Architecture72
Code Quality55
Innovation45
Learning Curve30

tokio-reactor-trait is the Tokio backend for the reactor-trait crate, a small set of async-runtime-agnostic traits (Reactor, TimeReactor, TcpReactor, AsyncToSocketAddrs) built so that libraries such as lapin, the async AMQP client, can work across multiple async runtimes without hard-coding one. The crate exposes a single Tokio struct that wraps an optional tokio::runtime::Handle and implements each reactor-trait interface using Tokio’s own timer, TCP, and (on Unix) AsyncFd-based I/O registration primitives.

It ships as part of the amqp-rs/reactor-trait Cargo workspace alongside a sibling async-io/async-std backend, async-reactor-trait, so consumers pick whichever crate matches their runtime and get an interchangeable reactor implementation without touching their own code.

What You Get

  • Tokio struct - A Tokio(Option<Handle>) wrapper that implements reactor-trait’s Reactor, TimeReactor, and TcpReactor traits.
  • Unix AsyncFd registration - On Unix, Reactor::register wraps a raw IOHandle in a tokio::io::unix::AsyncFd-backed AsyncRead/AsyncWrite adapter.
  • Timer support - TimeReactor::sleep and TimeReactor::interval map directly onto tokio::time::sleep and tokio::time::interval.
  • TCP connect helper - TcpReactor::connect opens a tokio::net::TcpStream and wraps it as an AsyncIOHandle via tokio-util’s compat layer.

Common Use Cases

  • Runtime-agnostic async libraries - Crate authors who depend on reactor-trait’s traits, rather than importing Tokio directly, plug in tokio-reactor-trait so downstream users can choose their runtime.
  • AMQP clients on Tokio - Consumers of the amqp-rs ecosystem (e.g. lapin) select tokio-reactor-trait to run their AMQP connection I/O on Tokio instead of async-std/smol.
  • Migrating from async-io to Tokio - Projects already using reactor-trait’s async-io backend can swap in tokio-reactor-trait with no changes to code written against the shared trait interfaces.

Under The Hood

Architecture The crate is a thin adapter layer with no internal layering beyond a single lib.rs file. It defines a zero-cost Tokio newtype wrapping Option<Handle>, and implements three trait interfaces defined in the sibling reactor-trait crate (Reactor for Unix-only IOHandle registration via tokio::io::unix::AsyncFd, TimeReactor for sleep/interval via tokio::time, and TcpReactor for outbound TCP via tokio::net::TcpStream wrapped through tokio-util’s compat layer to bridge Tokio’s I/O traits to futures-io’s). Data flow is direct pass-through: callers hold a Tokio instance, call trait methods, and results are wrapped in boxed trait objects (Box<dyn AsyncIOHandle + Send>) so the reactor-trait crate can remain executor-agnostic. If the core reactor_trait::Reactor/TimeReactor/TcpReactor trait signatures changed, this crate’s implementations would need corresponding updates, since it exists purely to satisfy those interfaces.

Tech Stack Rust 2021 edition, depending on tokio (no default features, only net, rt, and time), tokio-stream for IntervalStream, tokio-util’s compat feature to bridge futures-io traits, async-trait for async trait methods, futures-core/futures-io for the Stream/AsyncRead/AsyncWrite abstractions being implemented, and a path dependency on the sibling reactor-trait crate that defines the traits themselves. Build tooling is plain cargo inside a Cargo workspace, alongside the sibling async-reactor-trait crate; there is no build script, no database, and it is deployed as a published crates.io library rather than a runnable service.

Code Quality No #[test] blocks or tests/ directory exist in this crate or its sibling; CI runs cargo test --all --all-features across the workspace, but this crate contributes no test cases of its own and relies on compile-time trait-conformance checking instead. Error handling uses standard io::Result throughout, and the Unix AsyncFd read/write loop handles Poll::Pending/Ready explicitly with no silent swallowing. Naming is idiomatic Rust, matching each trait’s semantic purpose. rustfmt --check and clippy both run in CI. The absence of unit tests for a crate whose entire job is correctness-critical async I/O wiring is a real gap.

API Design The public API is intentionally tiny: a single Tokio struct with two constructors (with_handle, current) and no other configuration, so getting started requires no boilerplate beyond Tokio::current(). Method names mirror their Tokio equivalents almost one-to-one (sleep, interval, connect, register), so anyone familiar with Tokio can predict this crate’s behavior, though full understanding still requires cross-referencing the parent reactor-trait crate’s docs. This is a standard adapter/bridge pattern, mirroring async-reactor-trait’s shape for async-io, rather than a novel technical approach.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search