Skip to content
This repository was archived by the owner on Apr 29, 2022. It is now read-only.

Commit 7601e13

Browse files
author
Anton Vorontsov
committed
Finished advanced configuration section.
1 parent 3a58f81 commit 7601e13

File tree

3 files changed

+149
-3
lines changed

3 files changed

+149
-3
lines changed

docs/advanced-usage.md

Lines changed: 147 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,152 @@
11
# Advanced usage
22

3-
todo
3+
`IQueueService` is an interface that implements two other interfaces - `IConsumingService` and `IProducingService`. By default a RabbitMQ Client is registered as `IQueueService` without a logical separation at producing and consuming code. Thus, you can inject only a `IQueueService` instance, and `IConsumingService` or `IProducingService` won't be available. This is not a real deal until you want to control the way a RabbitMQ Client connects to the server.
44

5+
An instance of `IQueueService` opens two connections to the RabbitMQ server, one is for message production and the other one is for message consumption. Normally a RabbitMQ Client is added in a singleton mode, so both connections stay opened while application is running. It is also noticeable that a RabbitMQ Client uses the same credentials for both connections. If you add `IQueueService` in a transient mode (via the `AddRabbitMqClientTransient` extension method) both connections will be opened each time `IQueueService` is being injected somewhere else. This behavior does not fit everybody, so you can change it a little.
6+
7+
You are allowed to register a RabbitMQ Client as an implementation of two interfaces that have been mentioned before - `IConsumingService` and `IProducingService`. Each interface defines its own connection and its own collection of methods, obviously, for message production and message consumption. You can also use different credentials for different connections, and there is an option `ClientProvidedName` which allows you to create a "named" connection (which will be easier to find in the RabbitMQ management UI). There is also a possibility of registering `IConsumingService` and `IProducingService` in different lifetime modes, in case you want your consumption connection to be persist (singleton `IConsumingService`) and open a connection each time you want to send a message (a transient `IProducingService`). This situation will be covered in code examples below.
8+
9+
Let' say your application is a web API and you want to use both `IConsumingService` and `IProducingService`. Your `Startup` will look like this.
10+
11+
```c#
12+
public class Startup
13+
{
14+
private IConfiguration Configuration { get; }
15+
16+
public Startup(IConfiguration configuration)
17+
{
18+
Configuration = configuration;
19+
}
20+
21+
public void ConfigureServices(IServiceCollection services)
22+
{
23+
services.AddControllers();
24+
25+
// We will use different credentials for connections.
26+
var rabbitMqConsumerSection = Configuration.GetSection("RabbitMqConsumer");
27+
var rabbitMqProducerSection = Configuration.GetSection("RabbitMqProducer");
28+
29+
// And we also configure different exchanges just for a better example.
30+
var producingExchangeSection = Configuration.GetSection("ProducingExchange");
31+
var consumingExchangeSection = Configuration.GetSection("ConsumingExchange");
32+
33+
services.AddRabbitMqConsumingClientSingleton(rabbitMqConsumerSection)
34+
.AddRabbitMqProducingClientSingleton(rabbitMqProducerSection)
35+
.AddProductionExchange("exchange.to.send.messages.only", producingExchangeSection)
36+
.AddConsumptionExchange("consumption.exchange", consumingExchangeSection)
37+
.AddMessageHandlerTransient<CustomMessageHandler>("routing.key");
38+
39+
services.AddHostedService<ConsumingHostedService>();
40+
}
41+
42+
public void Configure(IApplicationBuilder app)
43+
{
44+
app.UseRouting();
45+
app.UseEndpoints(endpoints => endpoints.MapControllers());
46+
}
47+
}
48+
```
49+
50+
We have added `IConsumingService` and `IProducingService` via `AddRabbitMqConsumingClientSingleton` and `AddRabbitMqProducingClientSingleton` extension methods. We have also added two exchanges (for different purposes) via `AddProductionExchange` and `AddConsumptionExchange` methods which are covered in previous documentation sections. To start a message consumption we add a custom `IHostedService`, which injects `IConsumingService` and uses its `StartConsuming` method.
51+
52+
```c#
53+
public class ConsumingHostedService : IHostedService
54+
{
55+
readonly IConsumingService _consumingService;
56+
57+
public ConsumingHostedService(IConsumingService consumingService)
58+
{
59+
_consumingService = consumingService;
60+
}
61+
62+
public Task StartAsync(CancellationToken cancellationToken)
63+
{
64+
_consumingService.StartConsuming();
65+
return Task.CompletedTask;
66+
}
67+
68+
public Task StopAsync(CancellationToken cancellationToken)
69+
{
70+
return Task.CompletedTask;
71+
}
72+
}
73+
```
74+
75+
To send messages we can only use `IProducingService`. Let's inject it inside a controller.
76+
77+
```c#
78+
[ApiController]
79+
[Route("api/example")]
80+
public class ExampleController : ControllerBase
81+
{
82+
readonly ILogger<ExampleController> _logger;
83+
readonly IProducingService _producingService;
84+
85+
public ExampleController(
86+
IProducingService producingService,
87+
ILogger<ExampleController> logger)
88+
{
89+
_producingService = producingService;
90+
_logger = logger;
91+
}
92+
93+
[HttpGet]
94+
public async Task<IActionResult> Get()
95+
{
96+
_logger.LogInformation($"Sending messages with {typeof(IProducingService)}.");
97+
var message = new { message = "text" };
98+
await _producingService.SendAsync(message, "exchange.to.send.messages.only", "some.routing.key");
99+
return Ok(message);
100+
}
101+
}
102+
```
103+
104+
And the last thing we have to look at is a configuration file.
105+
```
106+
{
107+
"RabbitMqConsumer": {
108+
"ClientProvidedName": "Consumer",
109+
"TcpEndpoints": [
110+
{
111+
"HostName": "127.0.0.1",
112+
"Port": 5672
113+
}
114+
],
115+
"Port": "5672",
116+
"UserName": "user-consumer",
117+
"Password": "passwordForConsumer"
118+
},
119+
"RabbitMqProducer": {
120+
"ClientProvidedName": "Producer",
121+
"TcpEndpoints": [
122+
{
123+
"HostName": "127.0.0.1",
124+
"Port": 5672
125+
}
126+
],
127+
"Port": "5672",
128+
"UserName": "user-producer",
129+
"Password": "passwordForProducer"
130+
},
131+
"ConsumingExchange": {
132+
"Queues": [
133+
{
134+
"Name": "consuming.queue",
135+
"RoutingKeys": [ "routing.key" ]
136+
}
137+
]
138+
},
139+
"ProducingExchange": {
140+
"Queues": [
141+
{
142+
"Name": "queue.of.producing.exchange",
143+
"RoutingKeys": [ "produce.messages", "produce.events" ]
144+
}
145+
]
146+
}
147+
}
148+
```
149+
150+
As you can see, we set up a RabbitMQ client, which will create a connection for message production each time we call a `IProducingService`. We have also configured connections with different names and credentials. And the most important part is that we separated `IQueueService` for a logical parts. Be aware that `IQueueService` won't be available for injecting when you configure a RabbitMQ client in a `IConsumingService` plus `IProducingService` way.
5151

6152
For basic message consumption features see the [Previous page](message-consumption.md)

docs/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ These files cover all functionality of the library and if the new feature comes
44
Documentation consists of four sections. **RabbitMQ configuration section** covers ways of configuring the connection to the RabbitMQ host or multiple hosts (HA cluster).
55
**Exchange configuration section** explains the difference between consumption and production exchanges in terms of this library as well as specific nuances of configuring them.
66
**Message production section** says about features of sending messages and **message consuming section** covers ways of receiving and handling messages.
7-
Last section **Advanced usage** covers specific usage of the RabbitMQ client that can be useful for users who want to control behavior of RabbitMQ client tighter.
7+
Last section **Advanced usage** covers specific usage of the RabbitMQ client that can be useful for users who want to set up a tighter behavior control of the RabbitMQ client.
88

99
## Table of contents
1010

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,6 @@ All notable changes are being tracked in the [changelog](./docs/changelog.md) fi
250250

251251
## License
252252

253-
This library licenced under the MIT license.
253+
This library licensed under the MIT license.
254254

255255
Feel free to contribute!

0 commit comments

Comments
 (0)