#tokio #events #rpc #async

ioevent

Transform Any tokio Async I/O into Event-Driven Architecture with Low Overhead

1 unstable release

Uses new Rust 2024

new 0.1.0-rc.1 Apr 18, 2025

#74 in #rpc

Unlicense

51KB
700 lines

IOEVENT

GitHub License GitHub Issues or Pull Requests Crates.io Version

Transform Any tokio Async I/O into Event-Driven Architecture with Low Overhead.

A lightweight Rust crate built on Tokio's async runtime, providing a flexible event bus abstraction for asynchronous I/O operations. Perfect for building decoupled, event-driven systems with optimized performance.

Features ✨

  • 🚀 Event-driven Architecture: Convert async I/O operations into unified event streams
  • 🔗 Tokio-powered: Seamless integration with Tokio's async ecosystem
  • 🧩 Extensible: Custom event types and handler registration
  • 🔄 Bi-directional Communication: Support both event emission and response handling

Usage 🚀

See The Examples

Define Events

#[derive(Deserialize, Serialize, Event)]
struct EventA {
    foo: String,
    bar: i64,
}

#[derive(Deserialize, Serialize, Debug, Event)]
struct EventB {
    foo: i64,
    bar: String,
}

Create & Collect Subscribers

static SUBSCRIBERS: &[Subscriber<()>] = &[
    create_subscriber!(echo),
    create_subscriber!(print_b)
];

#[subscriber]
async fn echo<T>(s: State<T>, e: EventA) -> Result {
    s.bus.emit(&EventB {
        foo: e.bar,
        bar: e.foo,
    })?;
    Ok(())
}
// outher side: without state or ret
#[subscriber]
async fn print_b(e: EventB) {
    // by default, the host does not receive events sent by itself
    println!("{:?}", e);
}
// custom event query
// ... see example
// merge event and state
// ... see example

Create a Bus

let subscribes = Subscribers::init(SUBSCRIBERS);
let mut builder = BusBuilder::new(subscribes);
builder.add_pair(IoPair::stdio());
let Bus {
    mut subscribe_ticker,
    mut effect_ticker,
    effect_wright,
} = builder.build();

Create a State

let state = State::new((), effect_wright.clone());

Tick the Bus

loop {
    select! {
        _ = subscribe_ticker.tick(&state) => {},
        _ = effect_ticker.tick() => {},
    }
}
// ... and effect see example

Procedure Call

See The Examples

todo

  • middleware support
  • custom serializer & deserializer
  • procedure call

Dependencies

~6–12MB
~127K SLoC