You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Apr 29, 2022. It is now read-only.
@@ -104,82 +104,11 @@ public class Worker : BackgroundService
104
104
}
105
105
```
106
106
107
-
### Synchronous message handlers
108
-
109
-
The second step without which receiving messages does not make sense - configuration of message handling services. If there are no message handlers then received messages will not be processed.
110
-
111
-
Message handlers are classes that implement the `IMessageHandler` interface (or a few others) and contain functionality (including error handling) for processing messages.
112
-
You can register `IMessageHandler` in your `Startup` like this.
RabbitMQ client and exchange configuration sections are not specified in this example, but covered [here](rabbit-configuration.md) and [here](exchange-configuration.md).
136
-
137
-
`IMessageHandler` implementation will "listen" for messages by the specified routing key, or a collection of routing keys. If it is necessary, you can also register multiple message handler at once.
You can also use **pattern matching** in routes where `*` (star) can substitute for exactly one word and `#` (hash) can substitute for zero or more words.
You can register it in two modes, **singleton** or **transient**, using `AddMessageHandlerSingleton` or `AddMessageHandlerTransient` methods respectively.
You can also set multiple message handlers for managing messages received by one routing key. This case can happen when you want to divide responsibilities between services (e.g. one contains business logic, and the other writes messages in the database).
107
+
The second step is to define classes that will take responsibility of handling received messages. There are synchronous and asynchronous message handlers.
`IMessageHandler` consists of one method `Handle` that gets a message in a string format. You can deserialize it (if it is a json message) or handle a raw value.
111
+
`IMessageHandler` consists of one method `Handle` that gets a message in a string format. You can deserialize that message (if it is a json message) or handle its raw value.
183
112
Thus, a message handler will look like this.
184
113
185
114
```c#
@@ -193,7 +122,7 @@ public class CustomMessageHandler : IMessageHandler
193
122
}
194
123
```
195
124
196
-
You can also inject services inside the `IMessageHandler` constructor.
125
+
You can also inject almost any services inside the `IMessageHandler` constructor.
197
126
198
127
```c#
199
128
publicclassCustomMessageHandler : IMessageHandler
@@ -212,16 +141,7 @@ public class CustomMessageHandler : IMessageHandler
212
141
```
213
142
214
143
The only exception is the `IQueueService`. You can't inject it inside a message handler because of the appearance of cyclic dependencies. If you want to use an instance of `IQueueService` (e.g. handle one message and send another) use `INonCyclicMessageHandler`.
215
-
`INonCyclicMessageHandler` can be registered the same way as `IMessageHandler`. There are similar semantic methods for adding it in **singleton** or **transient** modes.
@@ -244,27 +164,12 @@ public class CustomNonCyclicMessageHandler : INonCyclicMessageHandler
244
164
### Asynchronous message handlers
245
165
246
166
`IMessageHandler` and `INonCyclicMessageHandler` work synchronously, but if you want to use an async technology then use `IAsyncMessageHandler` and `IAsyncNonCyclicMessageHandler`.
247
-
There are extension methods that allow you to register it the same way as synchronous ones in **singleton** or **transient** modes.
@@ -295,13 +201,112 @@ public class CustomAsyncNonCyclicMessageHandler : IAsyncNonCyclicMessageHandler
295
201
296
202
So you can use async/await power inside your message handler.
297
203
204
+
### Message handlers registering
205
+
206
+
The third and final step is to register defined message handlers and let them "listen" for messages relying on specified rules. If there are no message handlers registered then received messages will not be processed.
207
+
You can register `IMessageHandler` in your `Startup` calling one of `AddMessageHandler`-ish methods. You are allowed to add message handlers in two modes, **singleton** or **transient**, and there are extension methods for each mode and each message handler type:
208
+
209
+
-`AddMessageHandlerTransient`
210
+
-`AddMessageHandlerSingleton`
211
+
-`AddNonCyclicMessageHandlerTransient`
212
+
-`AddNonCyclicMessageHandlerSingleton`
213
+
-`AddAsyncMessageHandlerTransient`
214
+
-`AddAsyncMessageHandlerSingleton`
215
+
-`AddAsyncNonCyclicMessageHandlerTransient`
216
+
-`AddAsyncNonCyclicMessageHandlerSingleton`
217
+
218
+
And this will look like this in your `Startup` code.
RabbitMQ client and exchange configuration sections are not specified in this example, but covered [here](rabbit-configuration.md) and [here](exchange-configuration.md).
242
+
243
+
Message handlers can "listen" for messages by the **specified routing key**, or a **collection of routing keys**. If it is necessary, you can also register multiple message handler at once.
You can also use **pattern matching** in routes where `*` (star) can substitute for exactly one word and `#` (hash) can substitute for zero or more words.
You can also set multiple message handlers for managing messages received by one routing key. This case can happen when you want to divide responsibilities between services (e.g. one contains business logic, and the other writes messages in the database).
Since you are allowed to register multiple message handlers for one routing key (or one route pattern) you might want to make it run in a special order. You are allowed to do that too.
The higher order value - the more important message handler is. So it the previous code snippet the `OneMoreCustomMessageHandler` will process the received message first, `AnotherCustomMessageHandler` will be the second and `CustomMessageHandler` will be the third one.
291
+
292
+
You can also combine exchange and order configurations together!
The message handling process is organized as follows:
301
306
302
307
-`IQueueMessage` receives a message and delegates it to `IMessageHandlingService`.
303
-
-`IMessageHandlingService` gets a message (as a byte array) and decodes it to the UTF8 string. It also checks if there are any message handlers in collections of `IMessageHandler`, `IAsyncMessageHandler`, `INonCyclicMessageHandler` and `IAsyncNonCyclicMessageHandler` instances and forwards a message to them.
304
-
- All subscribed message handlers (`IMessageHandler`, `IAsyncMessageHandler`, `INonCyclicMessageHandler`, `IAsyncNonCyclicMessageHandler`) process the given message.
308
+
-`IMessageHandlingService` gets a message (as a byte array) and decodes it to the UTF8 string. It also checks if there are any message handlers in a combined collection of `IMessageHandler`, `IAsyncMessageHandler`, `INonCyclicMessageHandler` and `IAsyncNonCyclicMessageHandler` instances and forwards a message to them.
309
+
- All subscribed message handlers (`IMessageHandler`, `IAsyncMessageHandler`, `INonCyclicMessageHandler`, `IAsyncNonCyclicMessageHandler`) process the given message in a given or a default order.
305
310
-`IMessageHandlingService` acknowledges the message by its `DeliveryTag`.
306
311
- If any exception occurs `IMessageHandlingService` acknowledges the message anyway and checks if the message has to be re-send. If exchange option `RequeueFailedMessages` is set `true` then `IMessageHandlingService` adds a header `"requeued"` to the message and sends it again with delay in 60 seconds. Mechanism of sending delayed messages covered in the message production [documentation](message-production.md).
307
312
- If any exception occurs within handling the message that has been already re-sent that message will not be re-send again (re-send happens only once).
0 commit comments