Added request/response validation for non-yieldpoint methods
Added ExceptionStrategy Removed PublishExchange, fixed default ExchangeStrategy
This commit is contained in:
parent
a7b1ea85e5
commit
4dd8f73f99
@ -7,7 +7,6 @@ namespace Tapeti.Config
|
|||||||
{
|
{
|
||||||
public interface IConfig
|
public interface IConfig
|
||||||
{
|
{
|
||||||
string SubscribeExchange { get; }
|
|
||||||
IDependencyResolver DependencyResolver { get; }
|
IDependencyResolver DependencyResolver { get; }
|
||||||
IReadOnlyList<IMessageMiddleware> MessageMiddleware { get; }
|
IReadOnlyList<IMessageMiddleware> MessageMiddleware { get; }
|
||||||
IEnumerable<IQueue> Queues { get; }
|
IEnumerable<IQueue> Queues { get; }
|
||||||
|
@ -14,6 +14,7 @@ namespace Tapeti.Connection
|
|||||||
private readonly IDependencyResolver dependencyResolver;
|
private readonly IDependencyResolver dependencyResolver;
|
||||||
private readonly IReadOnlyList<IMessageMiddleware> messageMiddleware;
|
private readonly IReadOnlyList<IMessageMiddleware> messageMiddleware;
|
||||||
private readonly List<IBinding> bindings;
|
private readonly List<IBinding> bindings;
|
||||||
|
private readonly IExceptionStrategy exceptionStrategy;
|
||||||
|
|
||||||
|
|
||||||
public TapetiConsumer(TapetiWorker worker, string queueName, IDependencyResolver dependencyResolver, IEnumerable<IBinding> bindings, IReadOnlyList<IMessageMiddleware> messageMiddleware)
|
public TapetiConsumer(TapetiWorker worker, string queueName, IDependencyResolver dependencyResolver, IEnumerable<IBinding> bindings, IReadOnlyList<IMessageMiddleware> messageMiddleware)
|
||||||
@ -23,6 +24,8 @@ namespace Tapeti.Connection
|
|||||||
this.dependencyResolver = dependencyResolver;
|
this.dependencyResolver = dependencyResolver;
|
||||||
this.messageMiddleware = messageMiddleware;
|
this.messageMiddleware = messageMiddleware;
|
||||||
this.bindings = bindings.ToList();
|
this.bindings = bindings.ToList();
|
||||||
|
|
||||||
|
exceptionStrategy = dependencyResolver.Resolve<IExceptionStrategy>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -46,47 +49,61 @@ namespace Tapeti.Connection
|
|||||||
Properties = properties
|
Properties = properties
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
foreach (var binding in bindings)
|
try
|
||||||
{
|
{
|
||||||
if (!binding.Accept(context, message).Result)
|
foreach (var binding in bindings)
|
||||||
continue;
|
{
|
||||||
|
if (!binding.Accept(context, message).Result)
|
||||||
|
continue;
|
||||||
|
|
||||||
context.Controller = dependencyResolver.Resolve(binding.Controller);
|
context.Controller = dependencyResolver.Resolve(binding.Controller);
|
||||||
context.Binding = binding;
|
context.Binding = binding;
|
||||||
|
|
||||||
// ReSharper disable AccessToDisposedClosure - MiddlewareHelper will not keep a reference to the lambdas
|
// ReSharper disable AccessToDisposedClosure - MiddlewareHelper will not keep a reference to the lambdas
|
||||||
MiddlewareHelper.GoAsync(
|
MiddlewareHelper.GoAsync(
|
||||||
binding.MessageMiddleware != null
|
binding.MessageMiddleware != null
|
||||||
? messageMiddleware.Concat(binding.MessageMiddleware).ToList()
|
? messageMiddleware.Concat(binding.MessageMiddleware).ToList()
|
||||||
: messageMiddleware,
|
: messageMiddleware,
|
||||||
async (handler, next) => await handler.Handle(context, next),
|
async (handler, next) => await handler.Handle(context, next),
|
||||||
() => binding.Invoke(context, message)
|
() => binding.Invoke(context, message)
|
||||||
).Wait();
|
).Wait();
|
||||||
// ReSharper restore AccessToDisposedClosure
|
// ReSharper restore AccessToDisposedClosure
|
||||||
|
|
||||||
validMessageType = true;
|
validMessageType = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validMessageType)
|
||||||
|
throw new ArgumentException($"Unsupported message type: {message.GetType().FullName}");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
worker.Respond(deliveryTag, exceptionStrategy.HandleException(context, UnwrapException(e)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validMessageType)
|
|
||||||
throw new ArgumentException($"Unsupported message type: {message.GetType().FullName}");
|
|
||||||
|
|
||||||
worker.Respond(deliveryTag, ConsumeResponse.Ack);
|
worker.Respond(deliveryTag, ConsumeResponse.Ack);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// TODO allow different exception handling depending on exception type
|
worker.Respond(deliveryTag, exceptionStrategy.HandleException(null, UnwrapException(e)));
|
||||||
worker.Respond(deliveryTag, ConsumeResponse.Requeue);
|
|
||||||
|
|
||||||
var aggregateException = e as AggregateException;
|
|
||||||
if (aggregateException != null && aggregateException.InnerExceptions.Count == 1)
|
|
||||||
throw aggregateException.InnerExceptions[0];
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Exception UnwrapException(Exception exception)
|
||||||
|
{
|
||||||
|
// In async/await style code this is handled similarly. For synchronous
|
||||||
|
// code using Tasks we have to unwrap these ourselves to get the proper
|
||||||
|
// exception directly instead of "Errors occured". We might lose
|
||||||
|
// some stack traces in the process though.
|
||||||
|
var aggregateException = exception as AggregateException;
|
||||||
|
if (aggregateException != null && aggregateException.InnerExceptions.Count == 1)
|
||||||
|
throw aggregateException.InnerExceptions[0];
|
||||||
|
|
||||||
|
return UnwrapException(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected class MessageContext : IMessageContext
|
protected class MessageContext : IMessageContext
|
||||||
{
|
{
|
||||||
public IDependencyResolver DependencyResolver { get; set; }
|
public IDependencyResolver DependencyResolver { get; set; }
|
||||||
|
@ -12,12 +12,12 @@ namespace Tapeti.Connection
|
|||||||
public class TapetiWorker
|
public class TapetiWorker
|
||||||
{
|
{
|
||||||
public TapetiConnectionParams ConnectionParams { get; set; }
|
public TapetiConnectionParams ConnectionParams { get; set; }
|
||||||
public string SubscribeExchange { get; set; }
|
|
||||||
|
|
||||||
private readonly IDependencyResolver dependencyResolver;
|
private readonly IDependencyResolver dependencyResolver;
|
||||||
private readonly IReadOnlyList<IMessageMiddleware> messageMiddleware;
|
private readonly IReadOnlyList<IMessageMiddleware> messageMiddleware;
|
||||||
private readonly IMessageSerializer messageSerializer;
|
private readonly IMessageSerializer messageSerializer;
|
||||||
private readonly IRoutingKeyStrategy routingKeyStrategy;
|
private readonly IRoutingKeyStrategy routingKeyStrategy;
|
||||||
|
private readonly IExchangeStrategy exchangeStrategy;
|
||||||
private readonly Lazy<SingleThreadTaskQueue> taskQueue = new Lazy<SingleThreadTaskQueue>();
|
private readonly Lazy<SingleThreadTaskQueue> taskQueue = new Lazy<SingleThreadTaskQueue>();
|
||||||
private RabbitMQ.Client.IConnection connection;
|
private RabbitMQ.Client.IConnection connection;
|
||||||
private IModel channelInstance;
|
private IModel channelInstance;
|
||||||
@ -27,15 +27,16 @@ namespace Tapeti.Connection
|
|||||||
{
|
{
|
||||||
this.dependencyResolver = dependencyResolver;
|
this.dependencyResolver = dependencyResolver;
|
||||||
this.messageMiddleware = messageMiddleware;
|
this.messageMiddleware = messageMiddleware;
|
||||||
|
|
||||||
messageSerializer = dependencyResolver.Resolve<IMessageSerializer>();
|
messageSerializer = dependencyResolver.Resolve<IMessageSerializer>();
|
||||||
routingKeyStrategy = dependencyResolver.Resolve<IRoutingKeyStrategy>();
|
routingKeyStrategy = dependencyResolver.Resolve<IRoutingKeyStrategy>();
|
||||||
|
exchangeStrategy = dependencyResolver.Resolve<IExchangeStrategy>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Task Publish(object message, IBasicProperties properties)
|
public Task Publish(object message, IBasicProperties properties)
|
||||||
{
|
{
|
||||||
// TODO use exchange strategy!
|
return Publish(message, properties, exchangeStrategy.GetExchange(message.GetType()), routingKeyStrategy.GetRoutingKey(message.GetType()));
|
||||||
return Publish(message, properties, SubscribeExchange, routingKeyStrategy.GetRoutingKey(message.GetType()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ namespace Tapeti.Connection
|
|||||||
foreach (var binding in queue.Bindings)
|
foreach (var binding in queue.Bindings)
|
||||||
{
|
{
|
||||||
var routingKey = routingKeyStrategy.GetRoutingKey(binding.MessageClass);
|
var routingKey = routingKeyStrategy.GetRoutingKey(binding.MessageClass);
|
||||||
channel.QueueBind(dynamicQueue.QueueName, SubscribeExchange, routingKey);
|
channel.QueueBind(dynamicQueue.QueueName, exchangeStrategy.GetExchange(binding.MessageClass), routingKey);
|
||||||
|
|
||||||
(binding as IDynamicQueueBinding)?.SetQueueName(dynamicQueue.QueueName);
|
(binding as IDynamicQueueBinding)?.SetQueueName(dynamicQueue.QueueName);
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,9 @@ namespace Tapeti.Default
|
|||||||
{
|
{
|
||||||
public class NamespaceMatchExchangeStrategy : IExchangeStrategy
|
public class NamespaceMatchExchangeStrategy : IExchangeStrategy
|
||||||
{
|
{
|
||||||
public const string DefaultFormat = "^Messaging\\.(.[^\\.]+)";
|
// If the namespace starts with "Messaging.Service[.Optional.Further.Parts]", the exchange will be "Service".
|
||||||
|
// If no Messaging prefix is present, the first part of the namespace will be used instead.
|
||||||
private readonly Regex namespaceRegEx;
|
private static readonly Regex NamespaceRegex = new Regex("^(Messaging\\.)?(?<exchange>[^\\.]+)", RegexOptions.Compiled | RegexOptions.Singleline);
|
||||||
|
|
||||||
|
|
||||||
public NamespaceMatchExchangeStrategy()
|
|
||||||
{
|
|
||||||
namespaceRegEx = new Regex(DefaultFormat, RegexOptions.Compiled | RegexOptions.Singleline);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string GetExchange(Type messageType)
|
public string GetExchange(Type messageType)
|
||||||
@ -21,11 +15,11 @@ namespace Tapeti.Default
|
|||||||
if (messageType.Namespace == null)
|
if (messageType.Namespace == null)
|
||||||
throw new ArgumentException($"{messageType.FullName} does not have a namespace");
|
throw new ArgumentException($"{messageType.FullName} does not have a namespace");
|
||||||
|
|
||||||
var match = namespaceRegEx.Match(messageType.Namespace);
|
var match = NamespaceRegex.Match(messageType.Namespace);
|
||||||
if (!match.Success)
|
if (!match.Success)
|
||||||
throw new ArgumentException($"Namespace for {messageType.FullName} does not match the specified format");
|
throw new ArgumentException($"Namespace for {messageType.FullName} does not match the specified format");
|
||||||
|
|
||||||
return match.Groups[1].Value.ToLower();
|
return match.Groups["exchange"].Value.ToLower();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
Default/RequeueExceptionStrategy.cs
Normal file
14
Default/RequeueExceptionStrategy.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using Tapeti.Config;
|
||||||
|
|
||||||
|
namespace Tapeti.Default
|
||||||
|
{
|
||||||
|
public class RequeueExceptionStrategy : IExceptionStrategy
|
||||||
|
{
|
||||||
|
public ConsumeResponse HandleException(IMessageContext context, Exception exception)
|
||||||
|
{
|
||||||
|
// TODO log exception
|
||||||
|
return ConsumeResponse.Requeue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
IExceptionStrategy.cs
Normal file
16
IExceptionStrategy.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using Tapeti.Config;
|
||||||
|
|
||||||
|
namespace Tapeti
|
||||||
|
{
|
||||||
|
public interface IExceptionStrategy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Called when an exception occurs while handling a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">The message context if available. May be null!</param>
|
||||||
|
/// <param name="exception">The exception instance</param>
|
||||||
|
/// <returns>The ConsumeResponse to determine whether to requeue, dead-letter (nack) or simply ack the message.</returns>
|
||||||
|
ConsumeResponse HandleException(IMessageContext context, Exception exception);
|
||||||
|
}
|
||||||
|
}
|
73
Tapeti.Flow/Default/FlowBindingMiddleware.cs
Normal file
73
Tapeti.Flow/Default/FlowBindingMiddleware.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Tapeti.Config;
|
||||||
|
using Tapeti.Flow.Annotations;
|
||||||
|
using Tapeti.Helpers;
|
||||||
|
|
||||||
|
namespace Tapeti.Flow.Default
|
||||||
|
{
|
||||||
|
// TODO figure out a way to prevent binding on Continuation methods (which are always the target of a direct response)
|
||||||
|
internal class FlowBindingMiddleware : IBindingMiddleware
|
||||||
|
{
|
||||||
|
public void Handle(IBindingContext context, Action next)
|
||||||
|
{
|
||||||
|
RegisterContinuationFilter(context);
|
||||||
|
RegisterYieldPointResult(context);
|
||||||
|
|
||||||
|
next();
|
||||||
|
|
||||||
|
ValidateRequestResponse(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void RegisterContinuationFilter(IBindingContext context)
|
||||||
|
{
|
||||||
|
var continuationAttribute = context.Method.GetCustomAttribute<ContinuationAttribute>();
|
||||||
|
if (continuationAttribute == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
context.Use(new FlowBindingFilter());
|
||||||
|
context.Use(new FlowMessageMiddleware());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void RegisterYieldPointResult(IBindingContext context)
|
||||||
|
{
|
||||||
|
bool isTask;
|
||||||
|
if (!context.Result.Info.ParameterType.IsTypeOrTaskOf(typeof(IYieldPoint), out isTask))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isTask)
|
||||||
|
{
|
||||||
|
context.Result.SetHandler(async (messageContext, value) =>
|
||||||
|
{
|
||||||
|
var yieldPoint = await (Task<IYieldPoint>)value;
|
||||||
|
if (yieldPoint != null)
|
||||||
|
await HandleYieldPoint(messageContext, yieldPoint);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
context.Result.SetHandler((messageContext, value) => HandleYieldPoint(messageContext, (IYieldPoint)value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Task HandleYieldPoint(IMessageContext context, IYieldPoint yieldPoint)
|
||||||
|
{
|
||||||
|
var flowHandler = context.DependencyResolver.Resolve<IFlowHandler>();
|
||||||
|
return flowHandler.Execute(context, yieldPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void ValidateRequestResponse(IBindingContext context)
|
||||||
|
{
|
||||||
|
var request = context.MessageClass?.GetCustomAttribute<RequestAttribute>();
|
||||||
|
if (request?.Response == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool isTask;
|
||||||
|
if (!context.Result.Info.ParameterType.IsTypeOrTaskOf(t => t == request.Response || t == typeof(IYieldPoint), out isTask))
|
||||||
|
throw new ResponseExpectedException($"Response of class {request.Response.FullName} expected in controller {context.Method.DeclaringType?.FullName}, method {context.Method.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,6 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Tapeti.Config;
|
using Tapeti.Config;
|
||||||
using Tapeti.Flow.Annotations;
|
|
||||||
using Tapeti.Flow.Default;
|
using Tapeti.Flow.Default;
|
||||||
using Tapeti.Helpers;
|
|
||||||
|
|
||||||
namespace Tapeti.Flow
|
namespace Tapeti.Flow
|
||||||
{
|
{
|
||||||
@ -26,55 +21,5 @@ namespace Tapeti.Flow
|
|||||||
|
|
||||||
return new[] { new FlowBindingMiddleware() };
|
return new[] { new FlowBindingMiddleware() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class FlowBindingMiddleware : IBindingMiddleware
|
|
||||||
{
|
|
||||||
public void Handle(IBindingContext context, Action next)
|
|
||||||
{
|
|
||||||
RegisterContinuationFilter(context);
|
|
||||||
RegisterYieldPointResult(context);
|
|
||||||
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static void RegisterContinuationFilter(IBindingContext context)
|
|
||||||
{
|
|
||||||
var continuationAttribute = context.Method.GetCustomAttribute<ContinuationAttribute>();
|
|
||||||
if (continuationAttribute == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
context.Use(new FlowBindingFilter());
|
|
||||||
context.Use(new FlowMessageMiddleware());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static void RegisterYieldPointResult(IBindingContext context)
|
|
||||||
{
|
|
||||||
bool isTask;
|
|
||||||
if (!context.Result.Info.ParameterType.IsTypeOrTaskOf(typeof(IYieldPoint), out isTask))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (isTask)
|
|
||||||
{
|
|
||||||
context.Result.SetHandler(async (messageContext, value) =>
|
|
||||||
{
|
|
||||||
var yieldPoint = await (Task<IYieldPoint>)value;
|
|
||||||
if (yieldPoint != null)
|
|
||||||
await HandleYieldPoint(messageContext, yieldPoint);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
context.Result.SetHandler((messageContext, value) => HandleYieldPoint(messageContext, (IYieldPoint)value));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static Task HandleYieldPoint(IMessageContext context, IYieldPoint yieldPoint)
|
|
||||||
{
|
|
||||||
var flowHandler = context.DependencyResolver.Resolve<IFlowHandler>();
|
|
||||||
return flowHandler.Execute(context, yieldPoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
Tapeti.Flow/ResponseExpectedException.cs
Normal file
9
Tapeti.Flow/ResponseExpectedException.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Tapeti.Flow
|
||||||
|
{
|
||||||
|
public class ResponseExpectedException : Exception
|
||||||
|
{
|
||||||
|
public ResponseExpectedException(string message) : base(message) { }
|
||||||
|
}
|
||||||
|
}
|
@ -53,6 +53,7 @@
|
|||||||
<Compile Include="Annotations\RequestAttribute.cs" />
|
<Compile Include="Annotations\RequestAttribute.cs" />
|
||||||
<Compile Include="ContextItems.cs" />
|
<Compile Include="ContextItems.cs" />
|
||||||
<Compile Include="Default\FlowBindingFilter.cs" />
|
<Compile Include="Default\FlowBindingFilter.cs" />
|
||||||
|
<Compile Include="Default\FlowBindingMiddleware.cs" />
|
||||||
<Compile Include="Default\FlowContext.cs" />
|
<Compile Include="Default\FlowContext.cs" />
|
||||||
<Compile Include="Default\FlowMessageMiddleware.cs" />
|
<Compile Include="Default\FlowMessageMiddleware.cs" />
|
||||||
<Compile Include="Default\FlowState.cs" />
|
<Compile Include="Default\FlowState.cs" />
|
||||||
@ -67,6 +68,7 @@
|
|||||||
<Compile Include="IFlowStore.cs" />
|
<Compile Include="IFlowStore.cs" />
|
||||||
<Compile Include="IFlowProvider.cs" />
|
<Compile Include="IFlowProvider.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="ResponseExpectedException.cs" />
|
||||||
<Compile Include="YieldPointException.cs" />
|
<Compile Include="YieldPointException.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -63,11 +63,13 @@
|
|||||||
<Compile Include="Default\JsonMessageSerializer.cs" />
|
<Compile Include="Default\JsonMessageSerializer.cs" />
|
||||||
<Compile Include="Default\PublishResultBinding.cs" />
|
<Compile Include="Default\PublishResultBinding.cs" />
|
||||||
<Compile Include="Default\NamespaceMatchExchangeStrategy.cs" />
|
<Compile Include="Default\NamespaceMatchExchangeStrategy.cs" />
|
||||||
|
<Compile Include="Default\RequeueExceptionStrategy.cs" />
|
||||||
<Compile Include="Default\TypeNameRoutingKeyStrategy.cs" />
|
<Compile Include="Default\TypeNameRoutingKeyStrategy.cs" />
|
||||||
<Compile Include="Helpers\ConsoleHelper.cs" />
|
<Compile Include="Helpers\ConsoleHelper.cs" />
|
||||||
<Compile Include="Helpers\MiddlewareHelper.cs" />
|
<Compile Include="Helpers\MiddlewareHelper.cs" />
|
||||||
<Compile Include="Helpers\TaskTypeHelper.cs" />
|
<Compile Include="Helpers\TaskTypeHelper.cs" />
|
||||||
<Compile Include="IConnection.cs" />
|
<Compile Include="IConnection.cs" />
|
||||||
|
<Compile Include="IExceptionStrategy.cs" />
|
||||||
<Compile Include="IExchangeStrategy.cs" />
|
<Compile Include="IExchangeStrategy.cs" />
|
||||||
<Compile Include="ILogger.cs" />
|
<Compile Include="ILogger.cs" />
|
||||||
<Compile Include="Config\IMessageContext.cs" />
|
<Compile Include="Config\IMessageContext.cs" />
|
||||||
@ -78,7 +80,7 @@
|
|||||||
<Compile Include="Config\IBindingMiddleware.cs" />
|
<Compile Include="Config\IBindingMiddleware.cs" />
|
||||||
<Compile Include="TapetiConnectionParams.cs" />
|
<Compile Include="TapetiConnectionParams.cs" />
|
||||||
<Compile Include="TapetiConfig.cs" />
|
<Compile Include="TapetiConfig.cs" />
|
||||||
<Compile Include="TapetiTypes.cs" />
|
<Compile Include="ConsumeResponse.cs" />
|
||||||
<Compile Include="Tasks\SingleThreadTaskQueue.cs" />
|
<Compile Include="Tasks\SingleThreadTaskQueue.cs" />
|
||||||
<Compile Include="IDependencyResolver.cs" />
|
<Compile Include="IDependencyResolver.cs" />
|
||||||
<Compile Include="IMessageSerializer.cs" />
|
<Compile Include="IMessageSerializer.cs" />
|
||||||
|
@ -27,13 +27,11 @@ namespace Tapeti
|
|||||||
private readonly List<IBindingMiddleware> bindingMiddleware = new List<IBindingMiddleware>();
|
private readonly List<IBindingMiddleware> bindingMiddleware = new List<IBindingMiddleware>();
|
||||||
private readonly List<IMessageMiddleware> messageMiddleware = new List<IMessageMiddleware>();
|
private readonly List<IMessageMiddleware> messageMiddleware = new List<IMessageMiddleware>();
|
||||||
|
|
||||||
private readonly string subscribeExchange;
|
|
||||||
private readonly IDependencyResolver dependencyResolver;
|
private readonly IDependencyResolver dependencyResolver;
|
||||||
|
|
||||||
|
|
||||||
public TapetiConfig(string subscribeExchange, IDependencyResolver dependencyResolver)
|
public TapetiConfig(IDependencyResolver dependencyResolver)
|
||||||
{
|
{
|
||||||
this.subscribeExchange = subscribeExchange;
|
|
||||||
this.dependencyResolver = dependencyResolver;
|
this.dependencyResolver = dependencyResolver;
|
||||||
|
|
||||||
Use(new DependencyResolverBinding());
|
Use(new DependencyResolverBinding());
|
||||||
@ -63,7 +61,7 @@ namespace Tapeti
|
|||||||
|
|
||||||
queues.AddRange(dynamicBindings.Select(bl => new Queue(new QueueInfo { Dynamic = true }, bl)));
|
queues.AddRange(dynamicBindings.Select(bl => new Queue(new QueueInfo { Dynamic = true }, bl)));
|
||||||
|
|
||||||
var config = new Config(subscribeExchange, dependencyResolver, messageMiddleware, queues);
|
var config = new Config(dependencyResolver, messageMiddleware, queues);
|
||||||
(dependencyResolver as IDependencyContainer)?.RegisterDefaultSingleton<IConfig>(config);
|
(dependencyResolver as IDependencyContainer)?.RegisterDefaultSingleton<IConfig>(config);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
@ -104,17 +102,18 @@ namespace Tapeti
|
|||||||
public void RegisterDefaults()
|
public void RegisterDefaults()
|
||||||
{
|
{
|
||||||
var container = dependencyResolver as IDependencyContainer;
|
var container = dependencyResolver as IDependencyContainer;
|
||||||
if (container != null)
|
if (container == null)
|
||||||
{
|
return;
|
||||||
if (ConsoleHelper.IsAvailable())
|
|
||||||
container.RegisterDefault<ILogger, ConsoleLogger>();
|
|
||||||
else
|
|
||||||
container.RegisterDefault<ILogger, DevNullLogger>();
|
|
||||||
|
|
||||||
container.RegisterDefault<IMessageSerializer, JsonMessageSerializer>();
|
if (ConsoleHelper.IsAvailable())
|
||||||
container.RegisterDefault<IExchangeStrategy, NamespaceMatchExchangeStrategy>();
|
container.RegisterDefault<ILogger, ConsoleLogger>();
|
||||||
container.RegisterDefault<IRoutingKeyStrategy, TypeNameRoutingKeyStrategy>();
|
else
|
||||||
}
|
container.RegisterDefault<ILogger, DevNullLogger>();
|
||||||
|
|
||||||
|
container.RegisterDefault<IMessageSerializer, JsonMessageSerializer>();
|
||||||
|
container.RegisterDefault<IExchangeStrategy, NamespaceMatchExchangeStrategy>();
|
||||||
|
container.RegisterDefault<IRoutingKeyStrategy, TypeNameRoutingKeyStrategy>();
|
||||||
|
container.RegisterDefault<IExceptionStrategy, RequeueExceptionStrategy>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -310,7 +309,6 @@ namespace Tapeti
|
|||||||
|
|
||||||
protected class Config : IConfig
|
protected class Config : IConfig
|
||||||
{
|
{
|
||||||
public string SubscribeExchange { get; }
|
|
||||||
public IDependencyResolver DependencyResolver { get; }
|
public IDependencyResolver DependencyResolver { get; }
|
||||||
public IReadOnlyList<IMessageMiddleware> MessageMiddleware { get; }
|
public IReadOnlyList<IMessageMiddleware> MessageMiddleware { get; }
|
||||||
public IEnumerable<IQueue> Queues { get; }
|
public IEnumerable<IQueue> Queues { get; }
|
||||||
@ -318,9 +316,8 @@ namespace Tapeti
|
|||||||
private readonly Dictionary<MethodInfo, IBinding> bindingMethodLookup;
|
private readonly Dictionary<MethodInfo, IBinding> bindingMethodLookup;
|
||||||
|
|
||||||
|
|
||||||
public Config(string subscribeExchange, IDependencyResolver dependencyResolver, IReadOnlyList<IMessageMiddleware> messageMiddleware, IEnumerable<IQueue> queues)
|
public Config(IDependencyResolver dependencyResolver, IReadOnlyList<IMessageMiddleware> messageMiddleware, IEnumerable<IQueue> queues)
|
||||||
{
|
{
|
||||||
SubscribeExchange = subscribeExchange;
|
|
||||||
DependencyResolver = dependencyResolver;
|
DependencyResolver = dependencyResolver;
|
||||||
MessageMiddleware = messageMiddleware;
|
MessageMiddleware = messageMiddleware;
|
||||||
Queues = queues.ToList();
|
Queues = queues.ToList();
|
||||||
|
@ -20,8 +20,7 @@ namespace Tapeti
|
|||||||
|
|
||||||
worker = new Lazy<TapetiWorker>(() => new TapetiWorker(config.DependencyResolver, config.MessageMiddleware)
|
worker = new Lazy<TapetiWorker>(() => new TapetiWorker(config.DependencyResolver, config.MessageMiddleware)
|
||||||
{
|
{
|
||||||
ConnectionParams = Params ?? new TapetiConnectionParams(),
|
ConnectionParams = Params ?? new TapetiConnectionParams()
|
||||||
SubscribeExchange = config.SubscribeExchange
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +62,6 @@ namespace Test
|
|||||||
* This will automatically include the correlationId in the response and
|
* This will automatically include the correlationId in the response and
|
||||||
* use the replyTo header of the request if provided.
|
* use the replyTo header of the request if provided.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO validation middleware to ensure a request message returns the specified response (already done for IYieldPoint methods)
|
|
||||||
public PoloConfirmationResponseMessage PoloConfirmation(PoloConfirmationRequestMessage message)
|
public PoloConfirmationResponseMessage PoloConfirmation(PoloConfirmationRequestMessage message)
|
||||||
{
|
{
|
||||||
Console.WriteLine(">> PoloConfirmation (returning confirmation)");
|
Console.WriteLine(">> PoloConfirmation (returning confirmation)");
|
||||||
|
@ -10,11 +10,14 @@ namespace Test
|
|||||||
{
|
{
|
||||||
private static void Main()
|
private static void Main()
|
||||||
{
|
{
|
||||||
|
// TODO SQL based flow store
|
||||||
|
// TODO logging
|
||||||
|
|
||||||
var container = new Container();
|
var container = new Container();
|
||||||
container.Register<MarcoEmitter>();
|
container.Register<MarcoEmitter>();
|
||||||
container.Register<Visualizer>();
|
container.Register<Visualizer>();
|
||||||
|
|
||||||
var config = new TapetiConfig("test", new SimpleInjectorDependencyResolver(container))
|
var config = new TapetiConfig(new SimpleInjectorDependencyResolver(container))
|
||||||
.WithFlow()
|
.WithFlow()
|
||||||
.RegisterAllControllers()
|
.RegisterAllControllers()
|
||||||
.Build();
|
.Build();
|
||||||
|
Loading…
Reference in New Issue
Block a user