Ниже показан английский оригинал.
bind_with
bind_with binds a queue to a headers exchange by x-match and the headers to match, all of them or any one.
A headers exchange ignores the routing key and routes on the message's headers.
bind_with(exchange, routing_key, arguments) gives the binding an argument table, a FieldTable of AMQPValue entries.
The entry x-match decides the rule: all takes a message that carries every other entry of the table with the same value, and any takes a message that carries at least one.
The other entries are the headers to match, and the routing key of the binding is usually empty.
A plain bind to a headers exchange sends an empty table, and all of no headers is true of every message, so such a queue gets everything the exchange gets.
The publishing side sets the headers on the message, and they ride the AMQP header table the exchange reads.
bind_with also serves a plugin exchange that routes on binding arguments.
Example
The EU gold queue matches both headers, and the EU-or-gold queue matches either one.
- Macros
- Manual
/// The binding arguments: how to match, then the headers matched on.
fn gold_in_eu(x_match: &str) -> FieldTable {
let mut arguments = FieldTable::default();
arguments.insert("x-match".into(), AMQPValue::LongString(x_match.into()));
arguments.insert("region".into(), AMQPValue::LongString("eu".into()));
arguments.insert("tier".into(), AMQPValue::LongString("gold".into()));
arguments
}
/// Gold orders from the EU: both headers have to match.
#[subscriber(RabbitQueue::new("orders.eu-gold")
.bind_with(RabbitExchange::headers("orders"), "", gold_in_eu("all")))]
async fn expedite(order: &Order) -> HandlerOutcome {
tracing::info!(order.id, "expedited");
HandlerOutcome::ack()
}
/// Orders from the EU or of the gold tier: one header is enough.
#[subscriber(RabbitQueue::new("orders.eu-or-gold")
.bind_with(RabbitExchange::headers("orders"), "", gold_in_eu("any")))]
async fn review(order: &Order) -> HandlerOutcome {
tracing::info!(order.id, "reviewed");
HandlerOutcome::ack()
}
/// The binding arguments: how to match, then the headers matched on.
fn gold_in_eu(x_match: &str) -> FieldTable {
let mut arguments = FieldTable::default();
arguments.insert("x-match".into(), AMQPValue::LongString(x_match.into()));
arguments.insert("region".into(), AMQPValue::LongString("eu".into()));
arguments.insert("tier".into(), AMQPValue::LongString("gold".into()));
arguments
}
struct Expedite;
impl Handle<Order> for Expedite {
fn handle(
&self,
order: &Order,
_outs: &(),
_ctx: &mut Context<'_>,
) -> impl Future<Output = Result<(), HandlerOutcome>> {
tracing::info!(order.id, "expedited");
ready(Ok(()))
}
}
struct Review;
impl Handle<Order> for Review {
fn handle(
&self,
order: &Order,
_outs: &(),
_ctx: &mut Context<'_>,
) -> impl Future<Output = Result<(), HandlerOutcome>> {
tracing::info!(order.id, "reviewed");
ready(Ok(()))
}
}
/// Gold orders from the EU, where both headers have to match, and orders from the EU or of the
/// gold tier, where one header is enough.
fn bound() -> (RabbitQueue, RabbitQueue) {
let orders = RabbitExchange::headers("orders");
let all = RabbitQueue::new("orders.eu-gold").bind_with(orders.clone(), "", gold_in_eu("all"));
let any = RabbitQueue::new("orders.eu-or-gold").bind_with(orders, "", gold_in_eu("any"));
(all, any)
}