Tapeti/Tapeti/Connection/TapetiPublisher.cs

109 lines
3.5 KiB
C#

using System;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using RabbitMQ.Client;
using Tapeti.Annotations;
using Tapeti.Config;
using Tapeti.Default;
using Tapeti.Exceptions;
using Tapeti.Helpers;
namespace Tapeti.Connection
{
/// <inheritdoc />
public class TapetiPublisher : IInternalPublisher
{
private readonly ITapetiConfig config;
private readonly Func<ITapetiClient> clientFactory;
private readonly IExchangeStrategy exchangeStrategy;
private readonly IRoutingKeyStrategy routingKeyStrategy;
private readonly IMessageSerializer messageSerializer;
/// <inheritdoc />
public TapetiPublisher(ITapetiConfig config, Func<ITapetiClient> clientFactory)
{
this.config = config;
this.clientFactory = clientFactory;
exchangeStrategy = config.DependencyResolver.Resolve<IExchangeStrategy>();
routingKeyStrategy = config.DependencyResolver.Resolve<IRoutingKeyStrategy>();
messageSerializer = config.DependencyResolver.Resolve<IMessageSerializer>();
}
/// <inheritdoc />
public async Task Publish(object message)
{
await Publish(message, null, IsMandatory(message));
}
/// <inheritdoc />
public async Task Publish(object message, IMessageProperties properties, bool mandatory)
{
var messageClass = message.GetType();
var exchange = exchangeStrategy.GetExchange(messageClass);
var routingKey = routingKeyStrategy.GetRoutingKey(messageClass);
await Publish(message, properties, exchange, routingKey, mandatory);
}
/// <inheritdoc />
public async Task PublishDirect(object message, string queueName, IMessageProperties properties, bool mandatory)
{
await Publish(message, properties, null, queueName, mandatory);
}
private async Task Publish(object message, IMessageProperties properties, string exchange, string routingKey, bool mandatory)
{
var writableProperties = new MessageProperties(properties);
if (!writableProperties.Timestamp.HasValue)
writableProperties.Timestamp = DateTime.UtcNow;
writableProperties.Persistent = true;
var context = new PublishContext
{
Config = config,
Exchange = exchange,
RoutingKey = routingKey,
Message = message,
Properties = writableProperties
};
await MiddlewareHelper.GoAsync(
config.Middleware.Publish,
async (handler, next) => await handler.Handle(context, next),
async () =>
{
var body = messageSerializer.Serialize(message, writableProperties);
await clientFactory().Publish(body, writableProperties, exchange, routingKey, mandatory);
});
}
private static bool IsMandatory(object message)
{
return message.GetType().GetCustomAttribute<MandatoryAttribute>() != null;
}
private class PublishContext : IPublishContext
{
public ITapetiConfig Config { get; set; }
public string Exchange { get; set; }
public string RoutingKey { get; set; }
public object Message { get; set; }
public IMessageProperties Properties { get; set; }
}
}
}