pusu

Crates.iopusu
lib.rspusu
version0.1.6
created_at2025-12-20 03:09:21.344515+00
updated_at2025-12-20 21:41:14.230255+00
descriptionHigh-performance, fully static, event-driven architecture for Rust services
homepage
repository
max_upload_size
id1995934
size30,623
François Gibier (FrancoisGib)

documentation

README

pusu

pusu is a publisher - subscriber event-driven rust crate to send different messages across topics.

Build status Release status Crates.io Documentation

It is heavily inspired by kafka but will be much lighter. The goal of the project is to have a convenient way to configure a cluster of brokers, publishers and subscribers with rust proc macros. I wanted to generate all the "topics" in a static way to avoid dynamic traits.

I'm doing this project mostly to learn proc macros and also because I wanted to make my own event-driven architecture.

For now, producers can send messages to registered consumers, the initialization methods, will be improved in the future.

Example

struct AppState {
    counter: u64,
}

#[consumer]
struct MyConsumer {
    #[topic("user_handler")]
    user: User,

    #[topic("book_handler")]
    book: Book,

    #[state("state")]
    #[topic("count_handler")]
    count: (),

    state: Arc<Mutex<AppState>>,
}

#[derive(Debug, Serialize, Deserialize)]
struct User {
    username: String,
    age: u8,
}

#[derive(Debug, Serialize, Deserialize)]
struct Book {
    name: String,
    author: String,
}

fn user_handler(v: User) {
    println!("user: {}, {}", v.username, v.age);
}

fn book_handler(v: Book) {
    println!("book: {}, {}", v.name, v.author);
}

fn count_handler(state: Arc<Mutex<AppState>>) {
    let mut lock = state.lock().unwrap();
    lock.counter += 1;
    println!("count: {}", lock.counter);
}

#[producer]
struct MyProducer {
    user: User,

    book: Book,

    count: (),
}

fn main() -> Result<()> {   
    let c = MyConsumer {
        state: Arc::new(Mutex::new(AppState { counter: 0 })),
    };
    c.run(8080)?;

    let mut producer = MyProducer::new();
    let id = 1;
    let addr = "localhost:8080";

    producer.add_receiver(MyProducerTopic::User, id, addr);
    producer.add_receiver(MyProducerTopic::Book, id, addr);
    producer.add_receiver(MyProducerTopic::Count, id, addr);
    // or
    producer.user.add_receiver(id, addr);
    producer.book.add_receiver(id, addr);
    producer.count.add_receiver(id, addr);
    

    producer.produce_user(User { username: "Username".to_string(), age: 25 })?;
    producer.produce_book(Book { name: "Dune".to_string(), author: "Frank Herbert".to_string() })?;
    producer.produce_count()?;

    Ok(())
}

TODO

  • Fault tolerance and replication on brokers (with abstraction on pub sub sides)
  • Logging for debugging purpose
  • Async runtime with tokio, for now it is an os threads scheduling for projects without tokio
  • Configuration with yaml or toml format to not have to add receivers by hand and configure the runtime.
Commit count: 0

cargo fmt