2017-03-09 15:56:34 +01:00
|
|
|
|
|
|
|
|
|
using Microsoft.eShopOnContainers.Services.Common.Infrastructure.Catalog;
|
2017-03-10 13:17:16 +01:00
|
|
|
|
using Newtonsoft.Json;
|
2017-03-09 15:56:34 +01:00
|
|
|
|
using RabbitMQ.Client;
|
|
|
|
|
using RabbitMQ.Client.Events;
|
|
|
|
|
using System;
|
2017-03-10 13:17:16 +01:00
|
|
|
|
using System.Collections;
|
2017-03-09 15:56:34 +01:00
|
|
|
|
using System.Collections.Generic;
|
2017-03-10 13:17:16 +01:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
2017-03-09 15:56:34 +01:00
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.eShopOnContainers.Services.Common.Infrastructure
|
|
|
|
|
{
|
|
|
|
|
public class EventBus : IEventBus
|
|
|
|
|
{
|
2017-03-10 13:17:16 +01:00
|
|
|
|
private readonly string _brokerName = "event_bus";
|
|
|
|
|
private readonly Dictionary<string, List<IIntegrationEventHandler>> _handlers;
|
|
|
|
|
private readonly List<Type> _eventTypes;
|
|
|
|
|
|
|
|
|
|
private Tuple<IModel, IConnection> _connection;
|
|
|
|
|
private string _queueName;
|
|
|
|
|
|
2017-03-09 15:56:34 +01:00
|
|
|
|
|
|
|
|
|
public EventBus()
|
|
|
|
|
{
|
|
|
|
|
_handlers = new Dictionary<string, List<IIntegrationEventHandler>>();
|
2017-03-10 13:17:16 +01:00
|
|
|
|
_eventTypes = new List<Type>();
|
2017-03-09 15:56:34 +01:00
|
|
|
|
}
|
|
|
|
|
public void Publish(IIntegrationEvent @event)
|
|
|
|
|
{
|
2017-03-10 13:17:16 +01:00
|
|
|
|
var eventName = @event.GetType().Name;
|
2017-03-09 15:56:34 +01:00
|
|
|
|
var factory = new ConnectionFactory() { HostName = "172.20.0.1" };
|
|
|
|
|
using (var connection = factory.CreateConnection())
|
|
|
|
|
using (var channel = connection.CreateModel())
|
2017-03-10 13:17:16 +01:00
|
|
|
|
{
|
|
|
|
|
channel.ExchangeDeclare(exchange: _brokerName,
|
|
|
|
|
type: "direct");
|
2017-03-09 15:56:34 +01:00
|
|
|
|
|
2017-03-10 13:17:16 +01:00
|
|
|
|
string message = JsonConvert.SerializeObject(@event);
|
2017-03-09 15:56:34 +01:00
|
|
|
|
var body = Encoding.UTF8.GetBytes(message);
|
|
|
|
|
|
2017-03-10 13:17:16 +01:00
|
|
|
|
channel.BasicPublish(exchange: _brokerName,
|
|
|
|
|
routingKey: eventName,
|
2017-03-09 15:56:34 +01:00
|
|
|
|
basicProperties: null,
|
|
|
|
|
body: body);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Subscribe<T>(IIntegrationEventHandler<T> handler) where T : IIntegrationEvent
|
|
|
|
|
{
|
|
|
|
|
var eventName = typeof(T).Name;
|
|
|
|
|
if (_handlers.ContainsKey(eventName))
|
|
|
|
|
{
|
|
|
|
|
_handlers[eventName].Add(handler);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-03-10 13:17:16 +01:00
|
|
|
|
var channel = GetChannel();
|
|
|
|
|
channel.QueueBind(queue: _queueName,
|
|
|
|
|
exchange: _brokerName,
|
|
|
|
|
routingKey: eventName);
|
|
|
|
|
|
2017-03-09 15:56:34 +01:00
|
|
|
|
_handlers.Add(eventName, new List<IIntegrationEventHandler>());
|
|
|
|
|
_handlers[eventName].Add(handler);
|
2017-03-10 13:17:16 +01:00
|
|
|
|
_eventTypes.Add(typeof(T));
|
2017-03-09 15:56:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Unsubscribe<T>(IIntegrationEventHandler<T> handler) where T : IIntegrationEvent
|
|
|
|
|
{
|
|
|
|
|
var eventName = typeof(T).Name;
|
|
|
|
|
if (_handlers.ContainsKey(eventName) && _handlers[eventName].Contains(handler))
|
|
|
|
|
{
|
|
|
|
|
_handlers[eventName].Remove(handler);
|
|
|
|
|
|
|
|
|
|
if (_handlers[eventName].Count == 0)
|
|
|
|
|
{
|
|
|
|
|
_handlers.Remove(eventName);
|
2017-03-10 13:17:16 +01:00
|
|
|
|
var eventType = _eventTypes.Single(e => e.Name == eventName);
|
|
|
|
|
_eventTypes.Remove(eventType);
|
|
|
|
|
_connection.Item1.QueueUnbind(queue: _queueName,
|
|
|
|
|
exchange: _brokerName,
|
|
|
|
|
routingKey: eventName);
|
|
|
|
|
|
|
|
|
|
if (_handlers.Keys.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
_queueName = string.Empty;
|
|
|
|
|
_connection.Item1.Close();
|
|
|
|
|
_connection.Item2.Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-03-09 15:56:34 +01:00
|
|
|
|
|
2017-03-10 13:17:16 +01:00
|
|
|
|
private IModel GetChannel()
|
|
|
|
|
{
|
|
|
|
|
if (_connection != null)
|
|
|
|
|
{
|
|
|
|
|
return _connection.Item1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var factory = new ConnectionFactory() { HostName = "172.20.0.1" };
|
|
|
|
|
var connection = factory.CreateConnection();
|
|
|
|
|
var channel = connection.CreateModel();
|
2017-03-09 15:56:34 +01:00
|
|
|
|
|
2017-03-10 13:17:16 +01:00
|
|
|
|
channel.ExchangeDeclare(exchange: _brokerName,
|
|
|
|
|
type: "direct");
|
|
|
|
|
if (string.IsNullOrEmpty(_queueName))
|
|
|
|
|
{
|
|
|
|
|
_queueName = channel.QueueDeclare().QueueName;
|
2017-03-09 15:56:34 +01:00
|
|
|
|
}
|
2017-03-10 13:17:16 +01:00
|
|
|
|
|
|
|
|
|
var consumer = new EventingBasicConsumer(channel);
|
|
|
|
|
consumer.Received += (model, ea) =>
|
|
|
|
|
{
|
|
|
|
|
var eventName = ea.RoutingKey;
|
|
|
|
|
if (_handlers.ContainsKey(eventName))
|
|
|
|
|
{
|
|
|
|
|
var message = Encoding.UTF8.GetString(ea.Body);
|
|
|
|
|
Type eventType = _eventTypes.Single(t => t.Name == eventName);
|
|
|
|
|
|
|
|
|
|
var integrationEvent = JsonConvert.DeserializeObject(message, eventType);
|
|
|
|
|
var handlers = _handlers[eventName];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType);
|
|
|
|
|
|
|
|
|
|
foreach (var handler in handlers)
|
|
|
|
|
{
|
|
|
|
|
concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
channel.BasicConsume(queue: _queueName,
|
|
|
|
|
noAck: true,
|
|
|
|
|
consumer: consumer);
|
|
|
|
|
_connection = new Tuple<IModel, IConnection>(channel, connection);
|
|
|
|
|
|
|
|
|
|
return _connection.Item1;
|
2017-03-09 15:56:34 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|