ruststream_lapin/exchange.rs
1//! The exchange half of a queue binding descriptor.
2
3use lapin::ExchangeKind;
4
5/// Describes the exchange side of a [`RabbitQueue`](crate::RabbitQueue) binding.
6///
7/// Like every descriptor in this crate it only records the EXPECTED topology; nothing is
8/// declared unless the broker was built with
9/// [`declare_topology(true)`](crate::LapinBroker::declare_topology).
10///
11/// # Examples
12///
13/// ```
14/// use ruststream_lapin::RabbitExchange;
15///
16/// let events = RabbitExchange::topic("events").durable(true);
17/// assert_eq!(events.name(), "events");
18/// ```
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct RabbitExchange {
21 name: String,
22 kind: ExchangeKind,
23 durable: bool,
24 auto_delete: bool,
25}
26
27impl RabbitExchange {
28 fn new(name: impl Into<String>, kind: ExchangeKind) -> Self {
29 Self {
30 name: name.into(),
31 kind,
32 durable: true,
33 auto_delete: false,
34 }
35 }
36
37 /// A direct exchange: routes on an exact routing-key match.
38 #[must_use]
39 pub fn direct(name: impl Into<String>) -> Self {
40 Self::new(name, ExchangeKind::Direct)
41 }
42
43 /// A topic exchange: routes on dot-separated routing-key patterns (`order.*`).
44 #[must_use]
45 pub fn topic(name: impl Into<String>) -> Self {
46 Self::new(name, ExchangeKind::Topic)
47 }
48
49 /// A fanout exchange: routes every message to every bound queue.
50 #[must_use]
51 pub fn fanout(name: impl Into<String>) -> Self {
52 Self::new(name, ExchangeKind::Fanout)
53 }
54
55 /// A headers exchange: routes on header attributes instead of the routing key.
56 #[must_use]
57 pub fn headers(name: impl Into<String>) -> Self {
58 Self::new(name, ExchangeKind::Headers)
59 }
60
61 /// An exchange of a plugin-provided type, for example `"x-delayed-message"`.
62 #[must_use]
63 pub fn custom(name: impl Into<String>, kind: impl Into<String>) -> Self {
64 Self::new(name, ExchangeKind::Custom(kind.into()))
65 }
66
67 /// A consistent-hash exchange (the `x-consistent-hash` type from the
68 /// [`rabbitmq_consistent_hash_exchange`](https://github.com/rabbitmq/rabbitmq-server/tree/main/deps/rabbitmq_consistent_hash_exchange)
69 /// plugin): distributes messages across the queues bound to it by hashing the routing key,
70 /// so partition-like fan-out is a server-side concern rather than a client one.
71 ///
72 /// Each queue binds with a routing key that is its integer weight (`"1"`, `"2"`, ...); the
73 /// broker splits the hash space proportionally. Requires the plugin to be enabled on the
74 /// broker, so it lives behind the `plugin-consistent-hash` feature.
75 ///
76 /// # Examples
77 ///
78 /// ```
79 /// use ruststream_lapin::{RabbitExchange, RabbitQueue};
80 ///
81 /// let hashed = RabbitExchange::consistent_hash("orders-by-key");
82 /// // Bind a queue with its weight as the routing key:
83 /// let shard = RabbitQueue::new("shard-a").bind(hashed, "1");
84 /// # let _ = shard;
85 /// ```
86 #[cfg(feature = "plugin-consistent-hash")]
87 #[must_use]
88 pub fn consistent_hash(name: impl Into<String>) -> Self {
89 Self::new(name, ExchangeKind::Custom("x-consistent-hash".to_owned()))
90 }
91
92 /// Whether the exchange survives a broker restart. Defaults to `true`.
93 #[must_use]
94 pub fn durable(mut self, durable: bool) -> Self {
95 self.durable = durable;
96 self
97 }
98
99 /// Whether the exchange is deleted when its last binding is removed. Defaults to `false`.
100 #[must_use]
101 pub fn auto_delete(mut self, auto_delete: bool) -> Self {
102 self.auto_delete = auto_delete;
103 self
104 }
105
106 /// The exchange name.
107 #[must_use]
108 pub fn name(&self) -> &str {
109 &self.name
110 }
111
112 pub(crate) fn kind(&self) -> &ExchangeKind {
113 &self.kind
114 }
115
116 pub(crate) fn is_durable(&self) -> bool {
117 self.durable
118 }
119
120 pub(crate) fn is_auto_delete(&self) -> bool {
121 self.auto_delete
122 }
123}