@@ -7,6 +7,9 @@ Please read the [Introduction](intro.md) before reading this provider documentat
77- [ Configuration] ( #configuration )
88 - [ Producers] ( #producers )
99 - [ Consumers] ( #consumers )
10+ - [ Routing Keys and Wildcard Support] ( #routing-keys-and-wildcard-support )
11+ - [ Basic Routing Keys] ( #basic-routing-keys )
12+ - [ Wildcard Routing Keys] ( #wildcard-routing-keys )
1013 - [ Acknowledgment Mode] ( #acknowledgment-mode )
1114 - [ Consumer Error Handling] ( #consumer-error-handling )
1215 - [ Dead Letter Exchange] ( #dead-letter-exchange )
@@ -148,6 +151,79 @@ We can specify defaults for all consumers on the bus level:
148151});
149152```
150153
154+ #### Routing Keys and Wildcard Support
155+
156+ RabbitMQ routing keys are used by exchanges to determine which queues should receive a message. SlimMessageBus fully supports RabbitMQ's routing key semantics, including ** wildcard routing keys** for topic exchanges.
157+
158+ ##### Basic Routing Keys
159+
160+ For direct and topic exchanges, you can specify exact routing keys when binding consumers:
161+
162+ ``` cs
163+ mbb .Consume <OrderEvent >(x => x
164+ .Queue (" orders-queue" )
165+ .ExchangeBinding (" orders-exchange" , routingKey : " orders.created" )
166+ .WithConsumer <OrderCreatedConsumer >());
167+ ```
168+
169+ ##### Wildcard Routing Keys
170+
171+ For topic exchanges, SlimMessageBus supports RabbitMQ's wildcard routing key patterns:
172+
173+ - ** ` * ` (asterisk)** - matches exactly one segment
174+ - ** ` # ` (hash)** - matches zero or more segments
175+ - Segments are separated by ` . ` (dot)
176+
177+ ** Examples:**
178+
179+ ``` cs
180+ services .AddSlimMessageBus (mbb =>
181+ {
182+ // Producer sends messages with specific routing keys
183+ mbb .Produce <RegionEvent >(x => x
184+ .Exchange (" regions" , exchangeType : ExchangeType .Topic )
185+ .RoutingKeyProvider ((m , p ) => $" regions.{m .Country }.cities.{m .City }" ));
186+
187+ // Consumer 1: Match all cities in North America
188+ mbb .Consume <RegionEvent >(x => x
189+ .Queue (" na-cities-queue" )
190+ .ExchangeBinding (" regions" , routingKey : " regions.na.cities.*" ) // * matches exactly one city
191+ .WithConsumer <NorthAmericaCitiesConsumer >());
192+
193+ // Consumer 2: Match all events in the regions exchange
194+ mbb .Consume <RegionEvent >(x => x
195+ .Queue (" all-regions-queue" )
196+ .ExchangeBinding (" regions" , routingKey : " regions.#" ) // # matches zero or more segments
197+ .WithConsumer <AllRegionsConsumer >());
198+
199+ // Consumer 3: Match all audit events with any number of segments
200+ mbb .Consume <AuditEvent >(x => x
201+ .Queue (" audit-queue" )
202+ .ExchangeBinding (" audit" , routingKey : " audit.events.#" )
203+ .WithConsumer <AuditConsumer >());
204+
205+ // Consumer 4: Complex pattern - match region events ending with specific pattern
206+ mbb .Consume <RegionEvent >(x => x
207+ .Queue (" region-reports-queue" )
208+ .ExchangeBinding (" regions" , routingKey : " regions.*.reports.*" ) // matches regions.{country}.reports.{type}
209+ .WithConsumer <RegionReportsConsumer >());
210+ });
211+ ```
212+
213+ ** Routing Key Pattern Examples:**
214+
215+ | Pattern | Matches | Doesn't Match |
216+ | ---------| ---------| ---------------|
217+ | ` regions.na.cities.* ` | ` regions.na.cities.toronto ` <br />` regions.na.cities.newyork ` | ` regions.na.cities ` (missing segment)<br />` regions.na.cities.toronto.downtown ` (extra segment) |
218+ | ` audit.events.# ` | ` audit.events.users.signup ` <br />` audit.events.orders.placed ` <br />` audit.events ` | ` audit.users ` (wrong prefix) |
219+ | ` orders.#.region.* ` | ` orders.processed.region.na ` <br />` orders.created.cancelled.region.eu ` <br />` orders.region.na ` | ` orders.processed.state.california ` (wrong pattern)<br />` orders.processed.region ` (missing final segment) |
220+ | ` # ` | Any routing key | None (matches everything) |
221+
222+ ** Performance Note:** SlimMessageBus optimizes routing key matching by:
223+ - Using exact matches first for better performance
224+ - Only applying wildcard pattern matching when no exact match is found
225+ - Caching routing key patterns for efficient lookup
226+
151227#### Acknowledgment Mode
152228
153229When a consumer processes a message from a RabbitMQ queue, it needs to acknowledge that the message was processed. RabbitMQ supports three types of acknowledgments out which two are available in SMB:
@@ -370,7 +446,7 @@ In RabbitMQ, the default exchange (sometimes referred to as the default direct e
370446
371447- Its name is an empty string (`" " `).
372448- It is of type direct .
373- - Every queue that you declare is automatically bound to this default exchange with a routing key equal to the queue ’ s name .
449+ - Every queue that you declare is automatically bound to this default exchange with a routing key equal to the queue ' s name .
374450
375451This means :
376452
@@ -380,14 +456,14 @@ This will deliver the message straight to the `my_queue` queue.
380456
381457### Why it exists
382458
383- The default exchange makes it easy to send messages directly to a queue without having to explicitly set up an exchange and binding . It ’ s often used for simple "Hello World " style examples and direct queue messaging .
459+ The default exchange makes it easy to send messages directly to a queue without having to explicitly set up an exchange and binding . It ' s often used for simple "Hello World " style examples and direct queue messaging .
384460
385461✅ **Key points to remember **
386462
387463- The default exchange has no name (`" " `).
388464- Type : direct .
389465- Auto - binds every queue by its own name .
390- - Messages published to it must use the queue ’ s name as the routing key .
466+ - Messages published to it must use the queue ' s name as the routing key.
391467
392468## Connection Resiliency
393469
0 commit comments