The Rust client is async on tokio, with a builder chain that runs when you await it. It needs
Rust 1.86 and speaks reqwest with rustls: no OpenSSL on the host, no cmake in the build.
It is the only SDK that shares its wire types with the broker, through crates/queen-protocol. A
field that drifts on either side fails the broker’s own round-trip tests instead of reaching a
client.
[dependencies]
queen-mq = "1.0.0"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
serde_json = "1"use queen_mq::{Config, Queen};
let queen = Queen::connect(Config::new("http://localhost:6632"))?;Queen is cheap to clone: every clone shares one connection pool, one load balancer and one set
of push buffers, so build it once and pass clones around. connect validates the configuration
and the TLS setup but opens no socket, so a bad URL or an unusable bearer token fails here rather
than on the first call. Config::urls(["http://broker-a:6632", "http://broker-b:6632"]) takes
several brokers, with failover and consistent-hash affinity already on.
Push
let res = q
.queue("orders")
.partition("customer-42")
.push(serde_json::json!({ "orderId": 9137, "amount": 99.5 }))
.await
.unwrap();push takes anything serde::Serialize, push_many an iterator of them, and push_items
fully-formed PushItem values for when the transaction id matters. Each entry of the result
carries a status: Queued, Duplicate, Error, Buffered or Failed. A transaction_id you
do not supply is minted client-side as a UUIDv7, unique per call and therefore not idempotent.
Consume
let summary = q
.queue("orders")
.group("billing")
.subscription_mode(SubscriptionMode::All)
.limit(1)
.consume(|message| async move {
println!("{}", message.data);
Ok::<_, std::convert::Infallible>(())
})
.await
.unwrap();The handler’s return settles the message: Ok acks, Err nacks, and the error’s Display
becomes the DLQ reason when the nack exhausts the retry budget. consume_batch hands the handler
the whole claimed batch and settles it with one ack, a round-trip cheaper for vectorised work.
A Cancel stops a consumer between messages, never mid-handler.
Acknowledge
queen.ack(&msg).await?;
queen.nack(&msg, "could not reach the payment provider").await?;
queen.ack_all(&msgs).await?;The consumer group and the lease come from the message itself, so a forgotten group cannot ack the
wrong cursor. ack_all sends one request, and mixing groups in it is refused client-side rather
than half-applied. A rejected ack arrives as HTTP 200 with success: false on the item: check the
returned AckResult, not the absence of an error.
What differs here
popreturnsErrwhen the call fails, where JavaScript, Python and C++ return an empty list.limitcounts across all workers, not per worker as in JavaScript and Python.PushItemcarries no trace id; inside a transaction,TxnPushItem::trace_iddoes work.- Signal handling is opt-in behind the
signalsfeature: callqueen.close().await?to flush the buffers. - A
Hostset throughheadersis rejected at construction; usehost_headerbehind a proxy.
Config and its defaults, every builder method, transactions, the admin surface, the error type
and the streams DSL are in the Rust reference.
Tutorials
Five programs under examples/tutorials/rust build up from a single push to a streaming
aggregation, each one asserting its own outcome. Start at
Hello world.