topmesys
An embeddable topic-based message broker.
What it does
topmesys is an in-process publish/subscribe event bus for tokio applications. It lets loosely coupled parts of an application exchange messages through hierarchical topics instead of calling each other directly.
- Topic-based routing — messages carry a routing key like
orders.eu.created; consumers subscribe with patterns and only receive matching messages. - Flexible patterns — subscription topics support literal segments (
orders), wildcards (orders.*.created), selections (orders.[eu,us].paid) and tail matching (orders.*matchesorders.eu,orders.eu.created, ...). - Multi-topic consumers — a consumer declares several subscriptions, each identified by a
value of its own
Topictype (typically an enum), and handles every message knowing which subscription it arrived on. - Independent subscriptions — every subscription has its own bounded inbox and worker with
configurable concurrency; a concurrency of
1handles messages strictly in order. - Retries and dead letters — failed deliveries are retried with fixed, linear or exponential
backoff; permanent failures, exhausted retries and overflowing inboxes end up in a
DeadLetterSink. - Transport handles — messages bridged in from NATS, Kafka and the like can carry their transport's handle. Consumers can access it, and the broker settles it exactly once with the outcome of every subscription, so the bridge can ack, nak or terminate the message upstream.
- Typestate lifecycle — invalid states are unrepresentable: an
EventTopicmust be turned into a routing key or a subscription pattern before use, and messages can only be sent to anEventBroker<Running>. - Batched, cancel-safe submission — the
EventEmittertrait submits single messages or batches through channel permits. - Graceful shutdown — stopping the broker drains all buffered messages and waits for
in-flight deliveries, including pending retries; stopping on Ctrl-C can be opted into with
with_ctrl_c_handling().
Matching messages are delivered to every matching subscription; messages with no matching
subscription are dropped silently. When a subscription's inbox is full, routing waits for it by
default (Overflow::Block), which means a subscription busy retrying holds up all others once its
inbox fills. Subscriptions depending on unreliable systems can use Overflow::DeadLetter instead.
Quick start
use Duration;
use mpsc;
use ;
// Identifies the subscriptions of the consumer below.
// A consumer subscribes to topic patterns and handles matching events per subscription.
;
// An emitter wraps a sender obtained from the running broker.
async
Errors returned from handle_event are retried according to the subscription's RetryPolicy;
return HandlerError::permanent(error) for errors retrying won't fix. Messages a subscription
gives up on are handed to the DeadLetterSink set with EventBroker::with_dead_letter_sink or
Subscription::with_dead_letter_sink, and logged and dropped without one.
Bridging other messaging systems
A message received from another messaging system can carry the transport's handle. The broker settles it once, after every subscription the message was routed to finished, e.g. for NATS JetStream:
;
let message = new?
.with_transport;
Consumers and dead letter sinks get the handle back with transport::<JetStreamHandle>().
Complete, runnable scenarios live in examples/:
Benchmarks for topic parsing, subscription matching and end-to-end dispatch:
Development
ℹ️ Make sure just, git-cliff and cargo-llvm-cov are installed:
Common operations related to development and release can be found in the justfile. For an overview of available recipes, run:
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.