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

Commit 617fb48

Browse files
author
Anton Vorontsov
committed
Added MessageHandlerContainerBuilder, changed tests to fit a new service constructor parameters.
1 parent 4ebdd35 commit 617fb48

File tree

5 files changed

+146
-121
lines changed

5 files changed

+146
-121
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Collections.Generic;
2+
using RabbitMQ.Client.Core.DependencyInjection.Models;
3+
4+
namespace RabbitMQ.Client.Core.DependencyInjection
5+
{
6+
/// <summary>
7+
/// Interface of the service that build message handler containers collection.
8+
/// </summary>
9+
public interface IMessageHandlerContainerBuilder
10+
{
11+
/// <summary>
12+
/// Build message handler containers collection.
13+
/// </summary>
14+
/// <returns>Collection of message handler containers <see cref="MessageHandlerContainer"/>.</returns>
15+
IEnumerable<MessageHandlerContainer> BuildCollection();
16+
}
17+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using RabbitMQ.Client.Core.DependencyInjection.Extensions;
5+
using RabbitMQ.Client.Core.DependencyInjection.Models;
6+
7+
namespace RabbitMQ.Client.Core.DependencyInjection
8+
{
9+
/// <summary>
10+
/// Implementation of the service that build message handler containers collection.
11+
/// Those containers contain information about message handlers (all types) bound to the exchange.
12+
/// Container could be "general" if message handler has not been bound to the exchange (so it will "listen" regardless of the exchange).
13+
/// </summary>
14+
public class MessageHandlerContainerBuilder : IMessageHandlerContainerBuilder
15+
{
16+
readonly IEnumerable<MessageHandlerRouter> _routers;
17+
readonly IEnumerable<IMessageHandler> _messageHandlers;
18+
readonly IEnumerable<IAsyncMessageHandler> _asyncMessageHandlers;
19+
readonly IEnumerable<INonCyclicMessageHandler> _nonCyclicHandlers;
20+
readonly IEnumerable<IAsyncNonCyclicMessageHandler> _asyncNonCyclicHandlers;
21+
22+
public MessageHandlerContainerBuilder(
23+
IEnumerable<MessageHandlerRouter> routers,
24+
IEnumerable<IMessageHandler> messageHandlers,
25+
IEnumerable<IAsyncMessageHandler> asyncMessageHandlers,
26+
IEnumerable<INonCyclicMessageHandler> nonCyclicHandlers,
27+
IEnumerable<IAsyncNonCyclicMessageHandler> asyncNonCyclicHandlers)
28+
{
29+
_routers = routers;
30+
_messageHandlers = messageHandlers;
31+
_asyncMessageHandlers = asyncMessageHandlers;
32+
_nonCyclicHandlers = nonCyclicHandlers;
33+
_asyncNonCyclicHandlers = asyncNonCyclicHandlers;
34+
}
35+
36+
/// <summary>
37+
/// Build message handler containers collection.
38+
/// </summary>
39+
/// <returns>Collection of message handler containers <see cref="MessageHandlerContainer"/>.</returns>
40+
public IEnumerable<MessageHandlerContainer> BuildCollection()
41+
{
42+
var containers = new List<MessageHandlerContainer>();
43+
var generalRouters = _routers.Where(x => x.IsGeneral).ToList();
44+
if (generalRouters.Any())
45+
{
46+
var container = CreateContainer(null, generalRouters);
47+
containers.Add(container);
48+
}
49+
50+
var exchanges = _routers.Where(x => !x.IsGeneral).Select(x => x.Exchange).Distinct().ToList();
51+
foreach (var exchange in exchanges)
52+
{
53+
var exchangeRouters = _routers.Where(x => x.Exchange == exchange).ToList();
54+
var container = CreateContainer(exchange, exchangeRouters);
55+
containers.Add(container);
56+
}
57+
return containers;
58+
}
59+
60+
MessageHandlerContainer CreateContainer(string exchange, IEnumerable<MessageHandlerRouter> selectedRouters)
61+
{
62+
var routersDictionary = TransformMessageHandlerRoutersToDictionary(selectedRouters);
63+
var boundMessageHandlers = _messageHandlers.Where(x => routersDictionary.Keys.Contains(x.GetType()));
64+
var boundAsyncMessageHandlers = _asyncMessageHandlers.Where(x => routersDictionary.Keys.Contains(x.GetType()));
65+
var boundNonCyclicMessageHandlers = _nonCyclicHandlers.Where(x => routersDictionary.Keys.Contains(x.GetType()));
66+
var boundAsyncNonCyclicMessageHandlers = _asyncNonCyclicHandlers.Where(x => routersDictionary.Keys.Contains(x.GetType()));
67+
var routePatterns = selectedRouters.SelectMany(x => x.RoutePatterns).Distinct().ToList();
68+
return new MessageHandlerContainer
69+
{
70+
Exchange = exchange,
71+
Tree = WildcardExtensions.ConstructRoutesTree(routePatterns),
72+
MessageHandlers = TransformMessageHandlersCollectionToDictionary(boundMessageHandlers, routersDictionary),
73+
AsyncMessageHandlers = TransformMessageHandlersCollectionToDictionary(boundAsyncMessageHandlers, routersDictionary),
74+
NonCyclicHandlers = TransformMessageHandlersCollectionToDictionary(boundNonCyclicMessageHandlers, routersDictionary),
75+
AsyncNonCyclicHandlers = TransformMessageHandlersCollectionToDictionary(boundAsyncNonCyclicMessageHandlers, routersDictionary)
76+
};
77+
}
78+
79+
static IDictionary<Type, List<string>> TransformMessageHandlerRoutersToDictionary(IEnumerable<MessageHandlerRouter> routers)
80+
{
81+
var dictionary = new Dictionary<Type, List<string>>();
82+
foreach (var router in routers)
83+
{
84+
if (dictionary.ContainsKey(router.Type))
85+
{
86+
dictionary[router.Type] = dictionary[router.Type].Union(router.RoutePatterns).ToList();
87+
}
88+
else
89+
{
90+
dictionary.Add(router.Type, router.RoutePatterns);
91+
}
92+
}
93+
return dictionary;
94+
}
95+
96+
static IDictionary<string, IList<T>> TransformMessageHandlersCollectionToDictionary<T>(
97+
IEnumerable<T> messageHandlers,
98+
IDictionary<Type, List<string>> routersDictionary)
99+
{
100+
var dictionary = new Dictionary<string, IList<T>>();
101+
foreach (var handler in messageHandlers)
102+
{
103+
var type = handler.GetType();
104+
foreach (var routingKey in routersDictionary[type])
105+
{
106+
if (dictionary.ContainsKey(routingKey))
107+
{
108+
if (!dictionary[routingKey].Any(x => x.GetType() == handler.GetType()))
109+
{
110+
dictionary[routingKey].Add(handler);
111+
}
112+
}
113+
else
114+
{
115+
dictionary.Add(routingKey, new List<T> { handler });
116+
}
117+
}
118+
}
119+
return dictionary;
120+
}
121+
}
122+
}

src/RabbitMQ.Client.Core.DependencyInjection/MessageHandlingService.cs

Lines changed: 2 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,12 @@ public class MessageHandlingService : IMessageHandlingService
2222
readonly ILogger<MessageHandlingService> _logger;
2323

2424
public MessageHandlingService(
25+
IMessageHandlerContainerBuilder messageHandlerContainerBuilder,
2526
IEnumerable<RabbitMqExchange> exchanges,
26-
IEnumerable<MessageHandlerRouter> routers,
27-
IEnumerable<IMessageHandler> messageHandlers,
28-
IEnumerable<IAsyncMessageHandler> asyncMessageHandlers,
29-
IEnumerable<INonCyclicMessageHandler> nonCyclicHandlers,
30-
IEnumerable<IAsyncNonCyclicMessageHandler> asyncNonCyclicHandlers,
3127
ILogger<MessageHandlingService> logger)
3228
{
3329
_exchanges = exchanges;
34-
_messageHandlerContainers = ConstructMessageHandlerContainers(
35-
routers,
36-
messageHandlers,
37-
asyncMessageHandlers,
38-
nonCyclicHandlers,
39-
asyncNonCyclicHandlers);
30+
_messageHandlerContainers = messageHandlerContainerBuilder.BuildCollection();
4031
_logger = logger;
4132
}
4233

@@ -218,110 +209,5 @@ static void ValidateHandler<T>(T messageHandler)
218209
throw new ArgumentNullException(nameof(messageHandler), "Message handler is null.");
219210
}
220211
}
221-
222-
static IEnumerable<MessageHandlerContainer> ConstructMessageHandlerContainers(
223-
IEnumerable<MessageHandlerRouter> routers,
224-
IEnumerable<IMessageHandler> messageHandlers,
225-
IEnumerable<IAsyncMessageHandler> asyncMessageHandlers,
226-
IEnumerable<INonCyclicMessageHandler> nonCyclicHandlers,
227-
IEnumerable<IAsyncNonCyclicMessageHandler> asyncNonCyclicHandlers)
228-
{
229-
var containers = new List<MessageHandlerContainer>();
230-
var generalRouters = routers.Where(x => x.IsGeneral).ToList();
231-
if (generalRouters.Any())
232-
{
233-
var container = CreateContailer(
234-
null,
235-
generalRouters,
236-
messageHandlers,
237-
asyncMessageHandlers,
238-
nonCyclicHandlers,
239-
asyncNonCyclicHandlers);
240-
containers.Add(container);
241-
}
242-
243-
var exchanges = routers.Where(x => !x.IsGeneral).Select(x => x.Exchange).Distinct().ToList();
244-
foreach (var exchange in exchanges)
245-
{
246-
var exchangeRouters = routers.Where(x => x.Exchange == exchange).ToList();
247-
var container = CreateContailer(
248-
exchange,
249-
exchangeRouters,
250-
messageHandlers,
251-
asyncMessageHandlers,
252-
nonCyclicHandlers,
253-
asyncNonCyclicHandlers);
254-
containers.Add(container);
255-
}
256-
return containers;
257-
}
258-
259-
static MessageHandlerContainer CreateContailer(
260-
string exchange,
261-
IEnumerable<MessageHandlerRouter> selectedRouters,
262-
IEnumerable<IMessageHandler> messageHandlers,
263-
IEnumerable<IAsyncMessageHandler> asyncMessageHandlers,
264-
IEnumerable<INonCyclicMessageHandler> nonCyclicHandlers,
265-
IEnumerable<IAsyncNonCyclicMessageHandler> asyncNonCyclicHandlers)
266-
{
267-
var routersDictionary = TransformMessageHandlerRoutersToDictionary(selectedRouters);
268-
var boundMessageHandlers = messageHandlers.Where(x => routersDictionary.Keys.Contains(x.GetType()));
269-
var boundAsyncMessageHandlers = asyncMessageHandlers.Where(x => routersDictionary.Keys.Contains(x.GetType()));
270-
var boundNonCyclicMessageHandlers = nonCyclicHandlers.Where(x => routersDictionary.Keys.Contains(x.GetType()));
271-
var boundAsyncNonCyclicMessageHandlers = asyncNonCyclicHandlers.Where(x => routersDictionary.Keys.Contains(x.GetType()));
272-
var routePatterns = selectedRouters.SelectMany(x => x.RoutePatterns).Distinct().ToList();
273-
return new MessageHandlerContainer
274-
{
275-
Exchange = exchange,
276-
Tree = WildcardExtensions.ConstructRoutesTree(routePatterns),
277-
MessageHandlers = TransformMessageHandlersCollectionToDictionary(boundMessageHandlers, routersDictionary),
278-
AsyncMessageHandlers = TransformMessageHandlersCollectionToDictionary(boundAsyncMessageHandlers, routersDictionary),
279-
NonCyclicHandlers = TransformMessageHandlersCollectionToDictionary(boundNonCyclicMessageHandlers, routersDictionary),
280-
AsyncNonCyclicHandlers = TransformMessageHandlersCollectionToDictionary(boundAsyncNonCyclicMessageHandlers, routersDictionary)
281-
};
282-
}
283-
284-
static IDictionary<Type, List<string>> TransformMessageHandlerRoutersToDictionary(IEnumerable<MessageHandlerRouter> routers)
285-
{
286-
var dictionary = new Dictionary<Type, List<string>>();
287-
foreach (var router in routers)
288-
{
289-
if (dictionary.ContainsKey(router.Type))
290-
{
291-
dictionary[router.Type] = dictionary[router.Type].Union(router.RoutePatterns).ToList();
292-
}
293-
else
294-
{
295-
dictionary.Add(router.Type, router.RoutePatterns);
296-
}
297-
}
298-
return dictionary;
299-
}
300-
301-
static IDictionary<string, IList<T>> TransformMessageHandlersCollectionToDictionary<T>(
302-
IEnumerable<T> messageHandlers,
303-
IDictionary<Type, List<string>> routersDictionary)
304-
{
305-
var dictionary = new Dictionary<string, IList<T>>();
306-
foreach (var handler in messageHandlers)
307-
{
308-
var type = handler.GetType();
309-
foreach (var routingKey in routersDictionary[type])
310-
{
311-
if (dictionary.ContainsKey(routingKey))
312-
{
313-
if (!dictionary[routingKey].Any(x => x.GetType() == handler.GetType()))
314-
{
315-
dictionary[routingKey].Add(handler);
316-
}
317-
}
318-
else
319-
{
320-
dictionary.Add(routingKey, new List<T> { handler });
321-
}
322-
}
323-
}
324-
return dictionary;
325-
}
326212
}
327213
}

src/RabbitMQ.Client.Core.DependencyInjection/RabbitMqClientDependencyInjectionExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public static IServiceCollection AddRabbitMqClient(this IServiceCollection servi
2121
services.AddOptions();
2222
services.AddLogging(options => options.AddConsole());
2323
services.Configure<RabbitMqClientOptions>(configuration);
24+
services.AddSingleton<IMessageHandlerContainerBuilder, MessageHandlerContainerBuilder>();
2425
services.AddSingleton<IMessageHandlingService, MessageHandlingService>();
2526
services.AddSingleton<IQueueService, QueueService>();
2627
return services;

tests/RabbitMQ.Client.Core.DependencyInjection.Tests/UnitTests/MessageHandlingServiceTests.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,14 @@ static IMessageHandlingService CreateService(
106106
IEnumerable<INonCyclicMessageHandler> nonCyclicMessageHandler,
107107
IEnumerable<IAsyncNonCyclicMessageHandler> asyncNonCyclicMessageHandlers)
108108
{
109-
var loggerMock = new Mock<ILogger<MessageHandlingService>>();
110-
return new MessageHandlingService(
111-
exchanges,
109+
var messageHandlerContainerBuilder = new MessageHandlerContainerBuilder(
112110
routers,
113111
messageHandlers,
114112
asyncMessageHandlers,
115113
nonCyclicMessageHandler,
116-
asyncNonCyclicMessageHandlers,
117-
loggerMock.Object);
114+
asyncNonCyclicMessageHandlers);
115+
var loggerMock = new Mock<ILogger<MessageHandlingService>>();
116+
return new MessageHandlingService(messageHandlerContainerBuilder, exchanges, loggerMock.Object);
118117
}
119118
}
120119
}

0 commit comments

Comments
 (0)