tiny-pubsub 0.1.0

In-process publish/subscribe message bus with hierarchical topics and deferred or synchronous delivery.
Documentation
  • Coverage
  • 100%
    21 out of 21 items documented1 out of 20 items with examples
  • Size
  • Source code size: 65.75 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 445.04 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 2s Average build duration of successful builds.
  • all releases: 3s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • hey-jj/tiny-pubsub
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • hey-jj

tiny-pubsub

In-process, topic-based publish/subscribe message bus for Rust. Hierarchical topics, deferred or synchronous delivery, no dependencies.

Install

[dependencies]
tiny-pubsub = "0.1"

Use

use tiny_pubsub::PubSub;
use std::cell::Cell;
use std::rc::Rc;

let bus: PubSub<&str> = PubSub::new();
let hits = Rc::new(Cell::new(0));
let h = hits.clone();

// Subscribe a callback. You get back a token for later removal.
let token = bus.subscribe("car.engine", move |topic, data| {
    h.set(h.get() + 1);
    println!("{topic}: {data}");
});

// Synchronous publish runs every matching subscriber before it returns.
assert!(bus.publish_sync("car.engine", "start"));
assert_eq!(hits.get(), 1);

bus.unsubscribe(&token);

Topics are hierarchical

Topics are dot-delimited. Publishing a leaf notifies the leaf and every ancestor prefix, then the wildcard *. Children and siblings are never notified.

Publishing a.b.c reaches subscribers of a.b.c, then a.b, then a, then *. An ancestor subscriber receives the original leaf topic as its first argument, not the ancestor it matched.

use tiny_pubsub::PubSub;

let bus: PubSub<&str> = PubSub::new();
bus.subscribe("a", |topic, _| assert_eq!(topic, "a.b.c"));
bus.subscribe("a.b.c", |topic, _| assert_eq!(topic, "a.b.c"));
assert!(bus.publish_sync("a.b.c", "data"));

Deferred delivery

publish queues delivery and returns at once. Subscribers run when you call process_deferred. This models a non-blocking publisher.

use tiny_pubsub::PubSub;
use std::cell::Cell;
use std::rc::Rc;

let bus: PubSub<()> = PubSub::new();
let fired = Rc::new(Cell::new(false));
let f = fired.clone();
bus.subscribe("ping", move |_, _| f.set(true));

bus.publish("ping", ());
assert!(!fired.get());      // nothing has run yet
bus.process_deferred();     // drain the queue
assert!(fired.get());

Both publish and publish_sync return true when the topic had at least one matching subscriber (direct, ancestor, or *), computed before any subscriber runs.

Removing subscriptions

  • unsubscribe(&token) removes one subscription. It returns the token on a match, None otherwise.
  • unsubscribe_topic(topic) removes a topic and every descendant, by string prefix. It returns true when the prefix matched a topic.
  • clear_subscriptions(prefix) and clear_all_subscriptions() clear in bulk.

Rust closures cannot be compared by identity, so removal by function value has no analogue. The token covers single-subscription removal.

Panics during delivery

By default a panicking subscriber does not block the others. Delivery finishes, then the first panic is re-raised. Call set_immediate_exceptions(true) to stop at the first panic and propagate it, skipping the rest.

License

MIT.