### RustRabbitError Examples Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Illustrates how to instantiate various `RustRabbitError` types, including connection, serialization, and consumer errors. These examples show practical usage for creating specific error instances. ```rust use rust_rabbit::RustRabbitError; // Connection error let conn_error = RustRabbitError::Connection( "Failed to connect to amqp://localhost:5672".to_string() ); // Serialization error let ser_error = RustRabbitError::Serialization( "Failed to deserialize Order: missing field 'id'".to_string() ); // Consumer error let consumer_error = RustRabbitError::Consumer( "Message processing failed: database timeout".to_string() ); ``` -------------------------------- ### Install and Enable RabbitMQ Delayed Message Exchange Plugin Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md Provides instructions for installing and enabling the `rabbitmq_delayed_message_exchange` plugin. This includes downloading the plugin, copying it to the RabbitMQ plugins directory, enabling it via the command line, and restarting the RabbitMQ server. ```bash # For RabbitMQ 3.8+ # Download plugin from: # https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases # Or install via package manager # Ubuntu/Debian: sudo apt-get install rabbitmq-delayed-message-exchange # Or manually download and copy to plugins directory: wget https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.13.0/rabbitmq_delayed_message_exchange-3.13.0.ez sudo cp rabbitmq_delayed_message_exchange-3.13.0.ez /usr/lib/rabbitmq/plugins/ # Enable plugin rabbitmq-plugins enable rabbitmq_delayed_message_exchange # Restart RabbitMQ sudo systemctl restart rabbitmq-server # Verify plugin is enabled rabbitmq-plugins list | grep delayed # Should show: [E*] rabbitmq_delayed_message_exchange ``` -------------------------------- ### Rust RabbitMQ Routing Key Patterns Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Shows examples of effective routing key patterns using structured, dot-separated keys. This improves message routing clarity and maintainability compared to unstructured or camelCase keys. ```rust // Good "order.created.us" "user.updated.premium" "payment.failed.retry" // Avoid "orderCreatedUS" "user_update" "payment-fail" ``` -------------------------------- ### Install rust-rabbit and Dependencies Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/README.md Add the rust-rabbit crate and its necessary dependencies, tokio and serde, to your project's Cargo.toml file. This setup is required for using the RabbitMQ client and asynchronous operations. ```toml [dependencies] rust-rabbit = "1.2" tokio = { version = "1.0", features = ["full"] } serde = { version = "1.0", features = ["derive"] } ``` -------------------------------- ### Production Setup for Rust Rabbit with Consumers and Producers Source: https://context7.com/nghiaphamln/rust-rabbit/llms.txt Illustrates a production-ready setup for Rust Rabbit, including initializing tracing, establishing a connection, setting up multiple consumers with retry configurations, and a publisher for testing. It also demonstrates graceful shutdown and collecting statistics. ```rust use rust_rabbit::{Connection, Consumer, Publisher, PublishOptions, RetryConfig}; use serde::{Deserialize, Serialize}; use std::sync::Arc; use std::time::Duration; use tokio::sync::RwLock; #[derive(Serialize, Deserialize, Debug, Clone)] struct OrderEvent { order_id: String, user_id: String, amount: f64, event_type: String, } #[derive(Default)] struct Stats { orders_processed: u64, errors: u64, } #[tokio::main] async fn main() -> Result<(), Box> { rust_rabbit::init_tracing(); let connection = Connection::new("amqp://guest:guest@localhost:5672").await?; let stats = Arc::new(RwLock::new(Stats::default())); // Start order processor with exponential retry let stats_clone = stats.clone(); let conn_clone = connection.clone(); tokio::spawn(async move { let consumer = Consumer::builder(conn_clone, "orders") .with_retry(RetryConfig::exponential_default()) .with_prefetch(10) .build(); consumer.consume(move |msg: OrderEvent| { let stats = stats_clone.clone(); async move { println!("Processing order {}: ${}", msg.order_id, msg.amount); // Simulate processing tokio::time::sleep(Duration::from_millis(100)).await; // Update stats let mut s = stats.write().await; s.orders_processed += 1; Ok(()) } }).await }); // Start message producer for testing let publisher = Publisher::new(connection.clone()); tokio::spawn(async move { let mut counter = 1; loop { tokio::time::sleep(Duration::from_secs(5)).await; let order = OrderEvent { order_id: format!("ORD-{:06}", counter), user_id: format!("user-{}", counter % 100), amount: (counter as f64) * 99.99, event_type: "created".to_string(), }; let options = if counter % 10 == 0 { Some(PublishOptions::new().priority(9)) } else { None }; let _ = publisher.publish_to_queue("orders", &order, options).await; counter += 1; } }); // Wait for shutdown signal println!("Press Ctrl+C to stop"); tokio::signal::ctrl_c().await?; // Print final stats let s = stats.read().await; println!("Final stats - Orders: {}, Errors: {}", s.orders_processed, s.errors); Ok(()) } ``` -------------------------------- ### Delayed Message Exchange Plugin Installation and Verification Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md Provides instructions for installing and enabling the `rabbitmq_delayed_message_exchange` plugin on Ubuntu/Debian systems and within a Docker environment. It also includes a command to verify the plugin's installation status. ```bash sudo apt-get install rabbitmq-delayed-message-exchange rabbitmq-plugins enable rabbitmq_delayed_message_exchange sudo systemctl restart rabbitmq-server ``` ```yaml services: rabbitmq: image: rabbitmq:3.13-management environment: RABBITMQ_PLUGINS: rabbitmq_delayed_message_exchange ``` ```bash rabbitmq-plugins list | grep delayed # Output: [E*] rabbitmq_delayed_message_exchange ``` -------------------------------- ### RabbitMQ Exchange Types Quick Guide (Rust) Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Demonstrates publishing and binding for Direct, Topic, and Fanout exchange types in Rust. Direct exchanges require exact routing key matches, Topic exchanges use wildcard patterns (* and #), and Fanout exchanges broadcast messages to all bound queues. ```rust // Direct Exchange - exact routing key match publisher.publish_to_exchange("direct_ex", "order.new", &msg, None).await?; consumer.bind_to_exchange("direct_ex", "order.new") // Topic Exchange - pattern matching with wildcards publisher.publish_to_exchange("topic_ex", "order.created.us", &msg, None).await?; consumer.bind_to_exchange("topic_ex", "order.*.us") // * = one word consumer.bind_to_exchange("topic_ex", "order.#") // # = zero or more words // Fanout Exchange - broadcast to all queues publisher.publish_to_exchange("fanout_ex", "", &msg, None).await?; consumer.bind_to_exchange("fanout_ex", "") ``` -------------------------------- ### Rust RabbitMQ Exchange Naming Conventions Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Provides examples of good and bad naming conventions for RabbitMQ exchanges. Good names are clear, hierarchical, and descriptive, while bad names are generic and uninformative. ```rust // Good "order.events" "user.commands" "payment.notifications" // Avoid "exchange1" "temp" "test" ``` -------------------------------- ### Consumer Auto-Declaration and Binding in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Illustrates how rust-rabbit's Consumer can automatically declare a queue and an exchange, and then bind them together. This simplifies setup for common messaging scenarios. ```rust use rust_rabbit::Consumer; // Auto-creates queue and exchange, binds them together let consumer = Consumer::builder(connection, "order_queue") .bind_to_exchange("order_exchange", "new.order") .build(); ``` -------------------------------- ### Rust Error Context Best Practice Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Highlights the best practice of providing rich context in error messages. The example contrasts a good error message including order and customer IDs with a vague, unhelpful one. ```rust // Good Err(format!( "Failed to process order {} for customer {}: {}", order.id, customer.id, error ).into()) // Avoid Err("Processing failed".into()) ``` -------------------------------- ### Rust Retry Configuration Examples Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md Demonstrates various retry configurations using the Rust `RetryConfig` struct, including exponential backoff, linear retry, custom delays, and no retry. These configurations are crucial for managing message processing and error handling in RabbitMQ. ```rust RetryConfig::exponential_default() .with_delay_strategy(DelayStrategy::DelayedExchange) .with_dlq_ttl(Duration::from_secs(86400)) ``` ```rust RetryConfig::linear(3, Duration::from_secs(10)) ``` ```rust RetryConfig::custom(vec![ Duration::from_secs(1), Duration::from_secs(5), Duration::from_secs(30), ]) ``` ```rust RetryConfig::no_retry() ``` -------------------------------- ### RabbitMQ Delayed Message Exchange Docker Setup Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md Demonstrates how to set up RabbitMQ with the delayed message exchange plugin using Docker. This involves using a RabbitMQ image that supports management plugins and potentially copying the plugin into the container. ```dockerfile FROM rabbitmq:3.13-management # Additional commands to install/enable plugin if not included in the base image ``` -------------------------------- ### Topic Exchange Routing with Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Demonstrates Topic Exchange routing in rust-rabbit using wildcards for pattern matching. Publishers send messages with routing keys, and consumers bind using patterns like '*' and '#'. ```rust # Publisher sends with routing key publisher.publish_to_exchange("topic_exchange", "order.created.eu", &message, None).await?; # Consumer binds with pattern # * matches exactly one word # # matches zero or more words let consumer = Consumer::builder(connection, "eu_orders") .bind_to_exchange("topic_exchange", "order.*.eu") .build(); let consumer2 = Consumer::builder(connection, "all_orders") .bind_to_exchange("topic_exchange", "order.#") .build(); ``` -------------------------------- ### Routing Pattern with Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Demonstrates the Routing Pattern in rust-rabbit using a Direct Exchange. Publishers send messages with specific routing keys, and consumers bind to queues that match those keys or patterns. ```rust # Publisher with routing key publisher.publish_to_exchange("logs", "error", &error_log, None).await?; publisher.publish_to_exchange("logs", "info", &info_log, None).await?; # Consumer for errors only let error_consumer = Consumer::builder(connection, "error_logs") .bind_to_exchange("logs", "error") .build(); # Consumer for all logs let all_consumer = Consumer::builder(connection, "all_logs") .bind_to_exchange("logs", "#") .build(); ``` -------------------------------- ### Rust Basic Consumer Error Handling Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Provides a basic example of error handling within a rust-rabbit consumer. Returning `Err` signals a retry, while `Ok` acknowledges the message, demonstrating fundamental consumer error management. ```rust use rust_rabbit::{Connection, Consumer}; consumer.consume(|msg: Order| async move { // Return Err to trigger retry if msg.amount <= 0.0 { return Err("Invalid amount".into()); } // Return Ok to ACK message Ok(()) }).await?; ``` -------------------------------- ### Configure Multiple Bindings for a Queue in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Demonstrates how to bind a single queue to multiple exchanges and routing key patterns. This allows a queue to receive messages from various sources based on defined rules. ```rust let consumer = Consumer::builder(connection, "urgent_orders") .bind_to_exchange("orders", "order.urgent.#") .bind_to_exchange("orders", "order.*.high_value") .build(); ``` -------------------------------- ### Implement Timeouts for Order Processing in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Illustrates how to add a timeout to the order processing future using `tokio::time::timeout`. This prevents the consumer from getting stuck indefinitely on slow or unresponsive operations. ```rust use tokio::time::{timeout, Duration}; consumer.consume(|msg: Order| async move { match timeout(Duration::from_secs(30), process_order(&msg)).await { Ok(Ok(_)) => Ok(()), Ok(Err(e)) => Err(format!("Processing failed: {}", e).into()), Err(_) => Err("Processing timeout after 30s".into()), } }).await?; ``` -------------------------------- ### Rust RabbitMQ Queue Naming Conventions Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Illustrates recommended naming conventions for RabbitMQ queues. Descriptive names that indicate the queue's purpose are preferred over generic or temporary names. ```rust // Good "order_processor" "email_sender" "payment_validator" // Avoid "queue1" "worker" "temp_queue" ``` -------------------------------- ### Direct Exchange Routing with Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Shows how to use a Direct Exchange in rust-rabbit for simple routing. Publishers send messages with a specific routing key, and consumers bind to queues with exact matching routing keys. ```rust # Publisher sends to specific routing key publisher.publish_to_exchange("direct_exchange", "order.new", &message, None).await?; # Consumer binds queue to specific routing key let consumer = Consumer::builder(connection, "new_orders") .bind_to_exchange("direct_exchange", "order.new") .build(); ``` -------------------------------- ### Rust Unit Tests for Message Handlers Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/best-practices.md Provides example unit tests for message handling logic using `#[tokio::test]`. These tests verify the correct processing of valid `Order` structs and the expected error handling for invalid orders. ```rust #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn test_order_processing() { let order = Order { id: 123, amount: 99.99, }; let result = process_order(order).await; assert!(result.is_ok()); } #[tokio::test] async fn test_invalid_order() { let order = Order { id: 0, amount: -10.0, }; let result = process_order(order).await; assert!(result.is_err()); } } ``` -------------------------------- ### Command Queue Pattern in Rust RabbitMQ Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Illustrates the command queue pattern for sending commands to specific services. A publisher sends commands directly to a queue, and a dedicated consumer processes them. ```rust // Send commands to specific service publisher.publish_to_queue("order_service.commands", &command, None).await?; // Service processes commands let consumer = Consumer::builder(connection, "order_service.commands") .with_prefetch(5) .build(); ``` -------------------------------- ### Microservice Messaging Patterns in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/best-practices.md Illustrates common patterns for service-to-service communication using rust-rabbit, including event publishing, command sending, and event consumption with retry mechanisms and prefetching. This enables robust microservice architectures. ```rust // Event publishing async fn publish_order_created(bus: &MessageBus, order: &Order) -> Result<()> { bus.publish_event("order.created", order).await } // Command sending async fn send_command(bus: &MessageBus, service: &str, command: &T) -> Result<()> where T: serde::Serialize, { let queue = format!("{}.commands", service); bus.publisher.publish_to_queue(&queue, command, None).await } // Event consumption async fn start_consumer(bus: &MessageBus) -> Result<()> { let consumer = Consumer::builder(bus.connection.clone(), "order_service") .bind_to_exchange("domain.events", "order.#") .with_retry(RetryConfig::exponential_default()) .with_prefetch(10) .build(); consumer.consume(|msg: OrderEvent| async move { handle_order_event(msg).await }).await } ``` -------------------------------- ### Fanout Exchange Broadcasting with Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Illustrates broadcasting messages to all bound queues using a Fanout Exchange in rust-rabbit. Publishers send messages (routing key is ignored), and all connected consumers receive them. ```rust # Publisher ignores routing key (can be empty) publisher.publish_to_exchange("fanout_exchange", "", &message, None).await?; # All consumers receive the message let consumer1 = Consumer::builder(connection, "logger_queue") .bind_to_exchange("fanout_exchange", "") .build(); let consumer2 = Consumer::builder(connection, "analytics_queue") .bind_to_exchange("fanout_exchange", "") .build(); ``` -------------------------------- ### Multiple Queue Bindings for Flexible Routing in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Demonstrates binding a single queue to multiple routing keys across exchanges. This allows a queue to efficiently receive messages matching various patterns, such as priority orders. ```rust // Single queue receives messages from multiple patterns let consumer = Consumer::builder(connection, "priority_orders") .bind_to_exchange("orders", "order.urgent.*") .bind_to_exchange("orders", "order.*.high_value") .bind_to_exchange("orders", "order.vip.#") .with_prefetch(10) .build(); consumer.consume(|msg: Order| async move { println!("Processing priority order: {}", msg.id); Ok(()) }).await?; // Note: Call `bind_to_exchange()` multiple times on the same builder to add multiple bindings. ``` -------------------------------- ### Single Consumer Pattern with Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Implements the Single Consumer Pattern in rust-rabbit for simple point-to-point messaging. A producer publishes to a queue, and a single consumer listens to that queue. ```rust # Producer publisher.publish_to_queue("orders", &order, None).await?; # Consumer let consumer = Consumer::builder(connection, "orders") .build(); ``` -------------------------------- ### Publisher Auto-Declaration in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Demonstrates how rust-rabbit's Publisher automatically declares queues and exchanges when publishing messages. It shows publishing to a queue and an exchange, highlighting the auto-creation behavior. ```rust use rust_rabbit::Publisher; let publisher = Publisher::new(connection); // Auto-creates "order_queue" if it doesn't exist publisher.publish_to_queue("order_queue", &message, None).await?; // Uses existing exchange or fails if not found publisher.publish_to_exchange("order_exchange", "new.order", &message, None).await?; ``` -------------------------------- ### Handle Panics in Rust Consumer Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Shows how to use `AssertUnwindSafe` and `catch_unwind` to gracefully handle panics during order processing, preventing the consumer from crashing. This ensures the consumer remains available. ```rust use std::panic::AssertUnwindSafe; use futures::FutureExt; consumer.consume(|msg: Order| async move { let result = AssertUnwindSafe(process_order(&msg)) .catch_unwind() .await; match result { Ok(Ok(_)) => Ok(()), Ok(Err(e)) => Err(e.to_string().into()), Err(_) => { log::error!("Panic while processing order {}", msg.id); Err("Processing panicked".into()) } } }).await?; ``` -------------------------------- ### Secure RabbitMQ Connection with TLS in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/best-practices.md Demonstrates how to establish a secure connection to RabbitMQ using TLS/SSL. It shows direct connection string usage with `amqps` and loading credentials from environment variables for better security practices. ```rust // Use TLS // let connection = Connection::new("amqps://user:pass@host:5671").await?; // Load credentials from environment // let user = std::env::var("RABBITMQ_USER")?; // let pass = std::env::var("RABBITMQ_PASS")?; // let host = std::env::var("RABBITMQ_HOST")?; // let url = format!("amqps://{}:{}@{}:5671", user, pass, host); // let connection = Connection::new(&url).await?; ``` -------------------------------- ### Publish-Subscribe Pattern with Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Implements the Publish-Subscribe Pattern using a Fanout Exchange in rust-rabbit. A publisher sends a message to the exchange, and multiple subscribers (consumers) receive a copy. ```rust # Publisher publisher.publish_to_exchange("events", "", &event, None).await?; # Multiple subscribers let logger = Consumer::builder(connection, "log_queue") .bind_to_exchange("events", "") .build(); let analytics = Consumer::builder(connection, "analytics_queue") .bind_to_exchange("events", "") .build(); ``` -------------------------------- ### RabbitMQ Prefetch Configuration in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/best-practices.md Shows how to configure the prefetch count for consumers in rust-rabbit to balance throughput and fairness. Different prefetch values are suitable for various processing speeds and system loads. ```rust // Low throughput, fair distribution let consumer = Consumer::builder(connection, "orders") .with_prefetch(1) .build(); // Medium throughput, balanced let consumer = Consumer::builder(connection, "orders") .with_prefetch(10) .build(); // High throughput, may cause uneven distribution let consumer = Consumer::builder(connection, "orders") .with_prefetch(100) .build(); ``` -------------------------------- ### Log Order Processing Status in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Demonstrates how to use different log levels (info, warn, error) to report the outcome of processing an order message. This helps in monitoring and debugging. ```rust consumer.consume(|msg: Order| async move { match process_order(&msg).await { Ok(_) => { log::info!("Successfully processed order {}", msg.id); Ok(()) } Err(e) if e.is_retryable() => { log::warn!("Retryable error for order {}: {}", msg.id, e); Err(e.to_string().into()) } Err(e) => { log::error!("Fatal error for order {}: {}", msg.id, e); Err(e.to_string().into()) } } }).await?; ``` -------------------------------- ### Event Sourcing Pattern with Rust RabbitMQ Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Illustrates the event sourcing pattern using rust-rabbit. Events are published to a topic exchange, and multiple consumers can subscribe to different event patterns using wildcard routing keys. ```rust // Publish events to topic exchange publisher.publish_to_exchange( "domain.events", "order.created", &event, None ).await?; // Consumers subscribe to event patterns let order_consumer = Consumer::builder(connection, "order_service") .bind_to_exchange("domain.events", "order.#") .build(); let analytics_consumer = Consumer::builder(connection, "analytics") .bind_to_exchange("domain.events", "#") .build(); ``` -------------------------------- ### Shared Connection Management in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/best-practices.md Demonstrates how to create and manage a shared connection and publisher using Arc for thread-safe access in Rust. This pattern is crucial for reusing connections across an application, improving efficiency and reducing overhead. ```rust use rust_rabbit::{Connection, Publisher}; use std::sync::Arc; #[derive(Clone)] struct MessageBus { connection: Arc, publisher: Publisher, } impl MessageBus { async fn new(url: &str) -> Result> { let connection = Connection::new(url).await?; let publisher = Publisher::new(connection.clone()); Ok(Self { connection, publisher, }) } async fn publish_event(&self, event_type: &str, event: &T) -> Result<(), Box> where T: serde::Serialize, { self.publisher.publish_to_exchange( "domain.events", event_type, event, None ).await?; Ok(()) } } ``` -------------------------------- ### Rust Consumer Database Save with Retry Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Demonstrates implementing a custom retry loop within a consumer for database operations. It attempts to save data multiple times with delays before ultimately failing, showcasing error recovery. ```rust use tokio::time::{sleep, Duration}; consumer.consume(|msg: Order| async move { let mut attempts = 0; loop { match save_to_database(&msg).await { Ok(_) => return Ok(()), Err(e) if attempts < 3 => { attempts += 1; sleep(Duration::from_millis(100)).await; continue; } Err(e) => { return Err(format!("Database save failed after {} attempts: {}", attempts, e).into()); } } } }).await?; ``` -------------------------------- ### Rust Consumer Error with Context Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Illustrates how to add detailed context to errors returned from a consumer. By formatting error messages with relevant details like `msg.id`, it aids in debugging and understanding failure reasons. ```rust consumer.consume(|msg: Order| async move { match process_order(&msg).await { Ok(_) => Ok(()), Err(e) => { let error_msg = format!( "Failed to process order {}: {}", msg.id, e ); Err(error_msg.into()) } } }).await?; ``` -------------------------------- ### RabbitMQ Multiple Bindings Pattern (Rust) Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Illustrates how to configure a single consumer queue in Rust to bind to multiple routing patterns on a specified exchange. This allows a single queue to receive messages matching various criteria. ```rust // Single queue, multiple routing patterns Consumer::builder(connection, "priority_queue") .bind_to_exchange("orders", "order.urgent.*") .bind_to_exchange("orders", "order.*.high_value") .bind_to_exchange("orders", "order.vip.#") .build() ``` -------------------------------- ### Structured Logging with `tracing` Crate in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/best-practices.md Implements structured logging using the `tracing` crate for better observability. The `process_order` function is instrumented with `#[instrument]` and logs key details like `order_id` and `amount` in a structured format. ```rust use tracing::{info, warn, error, instrument}; #[instrument(skip(msg))] async fn process_order(msg: Order) -> Result<()> { info( order_id = msg.id, amount = msg.amount, "Processing order" ); match save_order(&msg).await { Ok(_) => { info!(order_id = msg.id, "Order saved successfully"); Ok(()) } Err(e) => { error( order_id = msg.id, error = %e, "Failed to save order" ); Err(e) } } } ``` -------------------------------- ### Publisher Connection Pooling in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/best-practices.md Implements a connection pool for publishers in Rust using tokio's RwLock to manage a collection of Publisher instances. This pattern is essential for high-volume publishing scenarios to maintain performance and resource efficiency. ```rust use std::sync::Arc; use tokio::sync::RwLock; struct PublisherPool { publishers: Arc>>, current: Arc>, } impl PublisherPool { async fn new(connection: Connection, size: usize) -> Self { let publishers = (0..size) .map(|_| Publisher::new(connection.clone())) .collect(); Self { publishers: Arc::new(RwLock::new(publishers)), current: Arc::new(RwLock::new(0)), } } async fn publish(&self, queue: &str, message: &T) -> Result<()> where T: serde::Serialize, { let publishers = self.publishers.read().await; let mut current = self.current.write().await; let publisher = &publishers[*current]; *current = (*current + 1) % publishers.len(); publisher.publish_to_queue(queue, message, None).await } } ``` -------------------------------- ### Configure DelayedExchange Strategy in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md Configures the delay strategy to use the `rabbitmq_delayed_message_exchange` plugin for precise message delays. This strategy requires the plugin to be installed and enabled on the RabbitMQ server. ```rust use rust_rabbit::{RetryConfig, DelayStrategy}; let config = RetryConfig::exponential_default() .with_delay_strategy(DelayStrategy::DelayedExchange); ``` -------------------------------- ### Publish Messages to RabbitMQ using rust-rabbit Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/README.md Demonstrates how to establish a connection to RabbitMQ and publish messages using the rust-rabbit library. It shows publishing to both a specified exchange with a routing key and directly to a queue. Requires serde for message serialization. ```rust use rust_rabbit::{Connection, Publisher}; use serde::Serialize; #[derive(Serialize)] struct Order { id: u32, amount: f64, } #[tokio::main] async fn main() -> Result<(), Box> { let connection = Connection::new("amqp://localhost:5672").await?; let publisher = Publisher::new(connection); let order = Order { id: 123, amount: 99.99 }; // Publish to exchange publisher.publish_to_exchange("orders", "new.order", &order, None).await?; // Publish to queue publisher.publish_to_queue("order_queue", &order, None).await?; Ok(()) } ``` -------------------------------- ### Run Rust Rabbit Tests Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/README.md Instructions for running tests for the Rust Rabbit project. This includes commands for running standard tests and integration tests that require a running RabbitMQ instance, typically managed via Docker. ```bash cargo test ``` ```bash # Start RabbitMQ with Docker docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management # Run tests cargo test ``` -------------------------------- ### Configure Publisher Options in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/README.md Shows how to configure advanced options for publishing messages in Rust using `PublishOptions`. This includes setting the `mandatory` flag and message `priority` for more fine-grained control over message delivery. ```rust use rust_rabbit::PublishOptions; let options = PublishOptions::new() .mandatory() .priority(5); publisher.publish_to_queue("orders", &message, Some(options)).await?; ``` -------------------------------- ### Initialize Tracing with Defaults in Rust Source: https://context7.com/nghiaphamln/rust-rabbit/llms.txt Initializes the tracing system with recommended defaults. This configuration filters out noisy logs from the 'lapin' library, setting its level to 'warn', while allowing application logs to be displayed at the 'info' level. It respects the RUST_LOG environment variable for further customization. The function `init_tracing` is provided by the `rust-rabbit` crate. ```rust use rust_rabbit::init_tracing; #[tokio::main] async fn main() -> Result<(), Box> { // Initialize tracing with recommended settings: // - info level for application logs // - warn level for lapin (suppresses spurious ERROR logs from io_loop) // - Respects RUST_LOG environment variable for custom config init_tracing(); // Now use tracing macros tracing::info!("Application starting"); tracing::debug!("Debug information"); tracing::warn!("Warning message"); // Your application code... let connection = rust_rabbit::Connection::new("amqp://localhost:5672").await?; tracing::info!("Connected to RabbitMQ"); Ok(()) } // Custom log levels via environment variable: // RUST_LOG=debug,lapin=warn cargo run // RUST_LOG=rust_rabbit=trace cargo run ``` -------------------------------- ### Install Delayed Message Exchange Plugin for RabbitMQ Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md This snippet shows how to enable the delayed message exchange plugin for RabbitMQ, either directly via the command line or by configuring it in a docker-compose file. This plugin is essential for implementing delayed message delivery. ```shell RUN rabbitmq-plugins enable rabbitmq_delayed_message_exchange ``` ```yaml version: '3.8' services: rabbitmq: image: rabbitmq:3.13-management ports: - "5672:5672" - "15672:15672" environment: RABBITMQ_PLUGINS: rabbitmq_delayed_message_exchange ``` -------------------------------- ### Configure Consumer with Exchange Binding and Prefetch in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/README.md Demonstrates comprehensive consumer configuration in Rust, including setting up retry mechanisms, binding the consumer to a specific exchange with a routing key, and configuring the prefetch count for efficient message handling. ```rust let consumer = Consumer::builder(connection, "order_queue") .with_retry(RetryConfig::exponential_default()) .bind_to_exchange("order_exchange", "new.order") .with_prefetch(10) .build(); ``` -------------------------------- ### Configure Consumer Prefetch Count in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/queues-exchanges.md Sets the number of unacknowledged messages a consumer can hold. A lower count ensures fairer distribution but reduces throughput, while a higher count maximizes throughput at the cost of potentially uneven distribution. This example sets the prefetch count to 10. ```rust let consumer = Consumer::builder(connection, "orders") .with_prefetch(10) // Process up to 10 messages concurrently .build(); ``` -------------------------------- ### Configure Exponential Backoff Retry in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md Sets up exponential backoff for message retries. The default configuration provides 5 retries with delays starting at 1 second and doubling up to a maximum cap. Custom configurations allow specifying the number of retries, base delay, and maximum delay. ```rust use rust_rabbit::RetryConfig; use std::time::Duration; // Default: 1s, 2s, 4s, 8s, 16s (5 retries) let config = RetryConfig::exponential_default(); // Custom with base delay and max cap let config = RetryConfig::exponential( 10, // max retries Duration::from_millis(500), // base delay Duration::from_secs(30) // max delay ); // Delays: 500ms, 1s, 2s, 4s, 8s, 16s, 30s, 30s, 30s, 30s ``` -------------------------------- ### Basic Dead Letter Queue (DLQ) Configuration in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md Configures a consumer with a default exponential retry strategy. Messages that exceed the retry limit will be sent to a Dead Letter Queue (DLQ) named '{queue_name}.dlq' for manual inspection. This setup does not include automatic cleanup for DLQ messages. ```rust let config = RetryConfig::exponential_default(); let consumer = Consumer::builder(connection, "orders") .with_retry(config) .build(); ``` -------------------------------- ### Production Configuration: Exponential Retry, Delayed Exchange, DLQ TTL in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md A comprehensive production configuration for a RabbitMQ consumer using Rust. It employs an exponential retry strategy, utilizes the delayed message exchange for retries, and sets a 1-day TTL for the Dead Letter Queue. This setup is designed for reliability and performance in high-volume scenarios. ```rust use rust_rabbit::{Connection, Consumer, RetryConfig, DelayStrategy}; use std::time::Duration; #[tokio::main] async fn main() -> Result<(), Box> { let connection = Connection::new("amqp://localhost:5672").await?; let retry_config = RetryConfig::exponential( 5, // max 5 retries Duration::from_secs(1), // start with 1s Duration::from_secs(60) // cap at 60s ) .with_delay_strategy(DelayStrategy::DelayedExchange) .with_dlq_ttl(Duration::from_secs(86400)); // 1 day retention let consumer = Consumer::builder(connection, "orders") .with_retry(retry_config) .with_prefetch(10) .bind_to_exchange("order_events", "order.*") .build(); consumer.consume(|msg: Order| async move { process_order(msg).await }).await?; Ok(()) } ``` -------------------------------- ### Publish Messages to MassTransit Services in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/README.md Illustrates how to publish messages from Rust to C# services using MassTransit. It utilizes `PublishOptions` to specify MassTransit integration, ensuring compatibility with MassTransit's message contracts. ```rust use rust_rabbit::PublishOptions; publisher.publish_to_exchange( "order-exchange", "order.created", &order, Some(PublishOptions::new().with_masstransit("Contracts:OrderCreated")) ).await?; ``` -------------------------------- ### Rust Connection Error Check Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Shows how to specifically check for connection-related errors using the `is_connection_error()` method. This allows for targeted recovery strategies, such as attempting to re-establish a connection. ```rust if error.is_connection_error() { println!("Connection issue detected"); // Maybe try reconnecting } ``` -------------------------------- ### Rust Error Retryability Check Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/error-handling.md Demonstrates how to check if a `RustRabbitError` is retryable using the `is_retryable()` method. This is crucial for implementing automatic retry mechanisms based on error classification. ```rust use rust_rabbit::RustRabbitError; fn handle_error(error: &RustRabbitError) { if error.is_retryable() { println!("This error might resolve itself, will retry"); } else { println!("Permanent error, will not retry"); } } ``` -------------------------------- ### Consume Messages from RabbitMQ using rust-rabbit Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/README.md Illustrates how to set up a consumer to receive messages from a RabbitMQ queue using the rust-rabbit library. This example includes configuring retry mechanisms and binding to an exchange. It requires serde for message deserialization. ```rust use rust_rabbit::{Connection, Consumer, RetryConfig}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Clone)] struct Order { id: u32, amount: f64, } #[tokio::main] async fn main() -> Result<(), Box> { let connection = Connection::new("amqp://localhost:5672").await?; let consumer = Consumer::builder(connection, "order_queue") .with_retry(RetryConfig::exponential_default()) .bind_to_exchange("orders", "new.order") .with_prefetch(5) .build(); consumer.consume(|msg: Order| async move { println!("Processing order {}: ${}", msg.id, msg.amount); if msg.amount > 1000.0 { return Err("Amount too high".into()); } Ok(()) }).await?; Ok(()) } ``` -------------------------------- ### Disable Retries in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/docs/retry-guide.md Disables the retry mechanism entirely. When retry is disabled, any message processing failure will result in the message being sent directly to the Dead Letter Queue without any retries. ```rust let config = RetryConfig::no_retry(); ``` -------------------------------- ### Implement Message Delay Strategies in Rust Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/README.md Demonstrates how to configure message delay strategies using Rust Rabbit. The TTL strategy is the default and requires no additional plugins. The DelayedExchange strategy offers more precise timing but necessitates the `rabbitmq_delayed_message_exchange` plugin. ```rust use rust_rabbit::{RetryConfig, DelayStrategy}; // TTL strategy (default) let config = RetryConfig::exponential_default() .with_delay_strategy(DelayStrategy::TTL); // Delayed exchange strategy (requires plugin) let config = RetryConfig::exponential_default() .with_delay_strategy(DelayStrategy::DelayedExchange); ``` -------------------------------- ### Configure Retry Mechanisms in rust-rabbit Source: https://github.com/nghiaphamln/rust-rabbit/blob/main/README.md Provides examples of configuring different retry strategies for message consumption in rust-rabbit. It covers exponential backoff, linear retries, custom delay sequences, and disabling retries. ```rust use rust_rabbit::RetryConfig; use std::time::Duration; // Exponential backoff: 1s, 2s, 4s, 8s, 16s let exponential = RetryConfig::exponential_default(); // Custom exponential with base and max delay let custom_exp = RetryConfig::exponential( 5, Duration::from_secs(2), Duration::from_secs(60) ); // Linear retry: same delay for each attempt let linear = RetryConfig::linear(3, Duration::from_secs(10)); // Custom delays for each retry let custom = RetryConfig::custom(vec![ Duration::from_secs(1), Duration::from_secs(5), Duration::from_secs(30), ]); // No retries let no_retry = RetryConfig::no_retry(); ```