diff --git a/Tapeti.Annotations/Tapeti.Annotations.csproj b/Tapeti.Annotations/Tapeti.Annotations.csproj
index be5c9ef..f584c07 100644
--- a/Tapeti.Annotations/Tapeti.Annotations.csproj
+++ b/Tapeti.Annotations/Tapeti.Annotations.csproj
@@ -5,4 +5,8 @@
true
+
+ 1701;1702;1591
+
+
diff --git a/Tapeti.DataAnnotations.Extensions/Tapeti.DataAnnotations.Extensions.csproj b/Tapeti.DataAnnotations.Extensions/Tapeti.DataAnnotations.Extensions.csproj
index 56cdff2..6ad9eab 100644
--- a/Tapeti.DataAnnotations.Extensions/Tapeti.DataAnnotations.Extensions.csproj
+++ b/Tapeti.DataAnnotations.Extensions/Tapeti.DataAnnotations.Extensions.csproj
@@ -4,6 +4,10 @@
netstandard2.0
+
+ 1701;1702;1591
+
+
diff --git a/Tapeti.DataAnnotations/Tapeti.DataAnnotations.csproj b/Tapeti.DataAnnotations/Tapeti.DataAnnotations.csproj
index 52e0d73..2237cd1 100644
--- a/Tapeti.DataAnnotations/Tapeti.DataAnnotations.csproj
+++ b/Tapeti.DataAnnotations/Tapeti.DataAnnotations.csproj
@@ -5,6 +5,10 @@
true
+
+ 1701;1702;1591
+
+
diff --git a/Tapeti.Flow.SQL/Tapeti.Flow.SQL.csproj b/Tapeti.Flow.SQL/Tapeti.Flow.SQL.csproj
index eaa2e91..51ce58a 100644
--- a/Tapeti.Flow.SQL/Tapeti.Flow.SQL.csproj
+++ b/Tapeti.Flow.SQL/Tapeti.Flow.SQL.csproj
@@ -5,6 +5,10 @@
true
+
+ 1701;1702;1591
+
+
diff --git a/Tapeti.Flow/Default/FlowBindingMiddleware.cs b/Tapeti.Flow/Default/FlowBindingMiddleware.cs
index fd796c4..7a65642 100644
--- a/Tapeti.Flow/Default/FlowBindingMiddleware.cs
+++ b/Tapeti.Flow/Default/FlowBindingMiddleware.cs
@@ -8,15 +8,15 @@ using Tapeti.Helpers;
namespace Tapeti.Flow.Default
{
- internal class FlowBindingMiddleware : IBindingMiddleware
+ internal class FlowBindingMiddleware : IControllerBindingMiddleware
{
- public void Handle(IBindingContext context, Action next)
+ public void Handle(IControllerBindingContext context, Action next)
{
if (context.Method.GetCustomAttribute() != null)
return;
if (context.Method.GetCustomAttribute() != null)
- context.QueueBindingMode = QueueBindingMode.DirectToQueue;
+ context.SetBindingTargetMode(BindingTargetMode.Direct);
RegisterYieldPointResult(context);
RegisterContinuationFilter(context);
@@ -27,14 +27,13 @@ namespace Tapeti.Flow.Default
}
- private static void RegisterContinuationFilter(IBindingContext context)
+ private static void RegisterContinuationFilter(IControllerBindingContext context)
{
var continuationAttribute = context.Method.GetCustomAttribute();
if (continuationAttribute == null)
return;
- context.Use(new FlowMessageFilterMiddleware());
- context.Use(new FlowMessageMiddleware());
+ context.Use(new FlowMiddleware());
if (context.Result.HasHandler)
return;
@@ -58,7 +57,7 @@ namespace Tapeti.Flow.Default
}
- private static void RegisterYieldPointResult(IBindingContext context)
+ private static void RegisterYieldPointResult(IControllerBindingContext context)
{
if (!context.Result.Info.ParameterType.IsTypeOrTaskOf(typeof(IYieldPoint), out var isTaskOf))
return;
@@ -77,16 +76,16 @@ namespace Tapeti.Flow.Default
}
- private static Task HandleYieldPoint(IMessageContext context, IYieldPoint yieldPoint)
+ private static Task HandleYieldPoint(IControllerMessageContext context, IYieldPoint yieldPoint)
{
- var flowHandler = context.DependencyResolver.Resolve();
+ var flowHandler = context.Config.DependencyResolver.Resolve();
return flowHandler.Execute(context, yieldPoint);
}
- private static Task HandleParallelResponse(IMessageContext context)
+ private static Task HandleParallelResponse(IControllerMessageContext context)
{
- var flowHandler = context.DependencyResolver.Resolve();
+ var flowHandler = context.Config.DependencyResolver.Resolve();
return flowHandler.Execute(context, new DelegateYieldPoint(async flowContext =>
{
await flowContext.Store();
@@ -94,7 +93,7 @@ namespace Tapeti.Flow.Default
}
- private static void ValidateRequestResponse(IBindingContext context)
+ private static void ValidateRequestResponse(IControllerBindingContext context)
{
var request = context.MessageClass?.GetCustomAttribute();
if (request?.Response == null)
diff --git a/Tapeti.Flow/Default/FlowCleanupMiddleware.cs b/Tapeti.Flow/Default/FlowCleanupMiddleware.cs
deleted file mode 100644
index 12673ad..0000000
--- a/Tapeti.Flow/Default/FlowCleanupMiddleware.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.Threading.Tasks;
-using Tapeti.Config;
-
-namespace Tapeti.Flow.Default
-{
- public class FlowCleanupMiddleware : ICleanupMiddleware
- {
- public async Task Handle(IMessageContext context, HandlingResult handlingResult)
- {
- if (!context.Items.TryGetValue(ContextItems.FlowContext, out var flowContextObj))
- return;
- var flowContext = (FlowContext)flowContextObj;
-
- if (flowContext?.FlowStateLock != null)
- {
- if (handlingResult.ConsumeResponse == ConsumeResponse.Nack
- || handlingResult.MessageAction == MessageAction.ErrorLog)
- {
- await flowContext.FlowStateLock.DeleteFlowState();
- }
- flowContext.FlowStateLock.Dispose();
- }
- }
- }
-}
diff --git a/Tapeti.Flow/Default/FlowContext.cs b/Tapeti.Flow/Default/FlowContext.cs
index dbadf08..0746a31 100644
--- a/Tapeti.Flow/Default/FlowContext.cs
+++ b/Tapeti.Flow/Default/FlowContext.cs
@@ -6,7 +6,7 @@ namespace Tapeti.Flow.Default
{
internal class FlowContext : IDisposable
{
- public IMessageContext MessageContext { get; set; }
+ public IControllerMessageContext MessageContext { get; set; }
public IFlowStateLock FlowStateLock { get; set; }
public FlowState FlowState { get; set; }
diff --git a/Tapeti.Flow/Default/FlowMessageFilterMiddleware.cs b/Tapeti.Flow/Default/FlowMessageFilterMiddleware.cs
deleted file mode 100644
index 8df46e8..0000000
--- a/Tapeti.Flow/Default/FlowMessageFilterMiddleware.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-using System;
-using System.Threading.Tasks;
-using Tapeti.Config;
-using Tapeti.Flow.FlowHelpers;
-
-namespace Tapeti.Flow.Default
-{
- public class FlowMessageFilterMiddleware : IMessageFilterMiddleware
- {
- public async Task Handle(IMessageContext context, Func next)
- {
- var flowContext = await GetFlowContext(context);
- if (flowContext?.ContinuationMetadata == null)
- return;
-
- if (flowContext.ContinuationMetadata.MethodName != MethodSerializer.Serialize(context.Binding.Method))
- return;
-
- await next();
- }
-
-
- private static async Task GetFlowContext(IMessageContext context)
- {
- if (context.Items.ContainsKey(ContextItems.FlowContext))
- return (FlowContext)context.Items[ContextItems.FlowContext];
-
- if (context.Properties.CorrelationId == null)
- return null;
-
- if (!Guid.TryParse(context.Properties.CorrelationId, out var continuationID))
- return null;
-
- var flowStore = context.DependencyResolver.Resolve();
-
- var flowID = await flowStore.FindFlowID(continuationID);
- if (!flowID.HasValue)
- return null;
-
- var flowStateLock = await flowStore.LockFlowState(flowID.Value);
-
- var flowState = await flowStateLock.GetFlowState();
- if (flowState == null)
- return null;
-
- var flowContext = new FlowContext
- {
- MessageContext = context,
-
- FlowStateLock = flowStateLock,
- FlowState = flowState,
-
- ContinuationID = continuationID,
- ContinuationMetadata = flowState.Continuations.TryGetValue(continuationID, out var continuation) ? continuation : null
- };
-
- // IDisposable items in the IMessageContext are automatically disposed
- context.Items.Add(ContextItems.FlowContext, flowContext);
- return flowContext;
- }
- }
-}
diff --git a/Tapeti.Flow/Default/FlowMessageMiddleware.cs b/Tapeti.Flow/Default/FlowMessageMiddleware.cs
deleted file mode 100644
index 394ae0b..0000000
--- a/Tapeti.Flow/Default/FlowMessageMiddleware.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System;
-using System.Reflection;
-using System.Threading.Tasks;
-using Tapeti.Config;
-
-namespace Tapeti.Flow.Default
-{
- public class FlowMessageMiddleware : IMessageMiddleware
- {
- public async Task Handle(IMessageContext context, Func next)
- {
- var flowContext = (FlowContext)context.Items[ContextItems.FlowContext];
- if (flowContext != null)
- {
- Newtonsoft.Json.JsonConvert.PopulateObject(flowContext.FlowState.Data, context.Controller);
-
- // Remove Continuation now because the IYieldPoint result handler will store the new state
- flowContext.FlowState.Continuations.Remove(flowContext.ContinuationID);
- var converge = flowContext.FlowState.Continuations.Count == 0 &&
- flowContext.ContinuationMetadata.ConvergeMethodName != null;
-
- await next();
-
- if (converge)
- await CallConvergeMethod(context,
- flowContext.ContinuationMetadata.ConvergeMethodName,
- flowContext.ContinuationMetadata.ConvergeMethodSync);
- }
- else
- await next();
- }
-
-
- private static async Task CallConvergeMethod(IMessageContext context, string methodName, bool sync)
- {
- IYieldPoint yieldPoint;
-
- var method = context.Controller.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
- if (method == null)
- throw new ArgumentException($"Unknown converge method in controller {context.Controller.GetType().Name}: {methodName}");
-
- if (sync)
- yieldPoint = (IYieldPoint)method.Invoke(context.Controller, new object[] {});
- else
- yieldPoint = await (Task)method.Invoke(context.Controller, new object[] { });
-
- if (yieldPoint == null)
- throw new YieldPointException($"Yield point is required in controller {context.Controller.GetType().Name} for converge method {methodName}");
-
- var flowHandler = context.DependencyResolver.Resolve();
- await flowHandler.Execute(context, yieldPoint);
- }
- }
-}
diff --git a/Tapeti.Flow/Default/FlowMiddleware.cs b/Tapeti.Flow/Default/FlowMiddleware.cs
new file mode 100644
index 0000000..c90332a
--- /dev/null
+++ b/Tapeti.Flow/Default/FlowMiddleware.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Reflection;
+using System.Threading.Tasks;
+using Tapeti.Config;
+using Tapeti.Flow.FlowHelpers;
+
+namespace Tapeti.Flow.Default
+{
+ public class FlowMiddleware : IControllerFilterMiddleware, IControllerMessageMiddleware, IControllerCleanupMiddleware
+ {
+ public async Task Filter(IControllerMessageContext context, Func next)
+ {
+ var flowContext = await CreateFlowContext(context);
+ if (flowContext?.ContinuationMetadata == null)
+ return;
+
+ if (flowContext.ContinuationMetadata.MethodName != MethodSerializer.Serialize(context.Binding.Method))
+ return;
+
+ await next();
+ }
+
+
+ public async Task Handle(IControllerMessageContext context, Func next)
+ {
+ if (context.Get(ContextItems.FlowContext, out FlowContext flowContext))
+ {
+ Newtonsoft.Json.JsonConvert.PopulateObject(flowContext.FlowState.Data, context.Controller);
+
+ // Remove Continuation now because the IYieldPoint result handler will store the new state
+ flowContext.FlowState.Continuations.Remove(flowContext.ContinuationID);
+ var converge = flowContext.FlowState.Continuations.Count == 0 &&
+ flowContext.ContinuationMetadata.ConvergeMethodName != null;
+
+ await next();
+
+ if (converge)
+ await CallConvergeMethod(context,
+ flowContext.ContinuationMetadata.ConvergeMethodName,
+ flowContext.ContinuationMetadata.ConvergeMethodSync);
+ }
+ else
+ await next();
+ }
+
+
+ public async Task Cleanup(IControllerMessageContext context, HandlingResult handlingResult, Func next)
+ {
+ await next();
+
+ if (!context.Get(ContextItems.FlowContext, out FlowContext flowContext))
+ return;
+
+ if (flowContext?.FlowStateLock != null)
+ {
+ if (handlingResult.ConsumeResponse == ConsumeResponse.Nack
+ || handlingResult.MessageAction == MessageAction.ErrorLog)
+ {
+ await flowContext.FlowStateLock.DeleteFlowState();
+ }
+ flowContext.FlowStateLock.Dispose();
+ }
+ }
+
+
+
+ private static async Task CreateFlowContext(IControllerMessageContext context)
+ {
+ if (context.Get(ContextItems.FlowContext, out FlowContext flowContext))
+ return flowContext;
+
+
+ if (context.Properties.CorrelationId == null)
+ return null;
+
+ if (!Guid.TryParse(context.Properties.CorrelationId, out var continuationID))
+ return null;
+
+ var flowStore = context.Config.DependencyResolver.Resolve();
+
+ var flowID = await flowStore.FindFlowID(continuationID);
+ if (!flowID.HasValue)
+ return null;
+
+ var flowStateLock = await flowStore.LockFlowState(flowID.Value);
+
+ var flowState = await flowStateLock.GetFlowState();
+ if (flowState == null)
+ return null;
+
+ flowContext = new FlowContext
+ {
+ MessageContext = context,
+
+ FlowStateLock = flowStateLock,
+ FlowState = flowState,
+
+ ContinuationID = continuationID,
+ ContinuationMetadata = flowState.Continuations.TryGetValue(continuationID, out var continuation) ? continuation : null
+ };
+
+ // IDisposable items in the IMessageContext are automatically disposed
+ context.Store(ContextItems.FlowContext, flowContext);
+ return flowContext;
+ }
+
+
+ private static async Task CallConvergeMethod(IControllerMessageContext context, string methodName, bool sync)
+ {
+ IYieldPoint yieldPoint;
+
+ var method = context.Controller.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
+ if (method == null)
+ throw new ArgumentException($"Unknown converge method in controller {context.Controller.GetType().Name}: {methodName}");
+
+ if (sync)
+ yieldPoint = (IYieldPoint)method.Invoke(context.Controller, new object[] {});
+ else
+ yieldPoint = await (Task)method.Invoke(context.Controller, new object[] { });
+
+ if (yieldPoint == null)
+ throw new YieldPointException($"Yield point is required in controller {context.Controller.GetType().Name} for converge method {methodName}");
+
+ var flowHandler = context.Config.DependencyResolver.Resolve();
+ await flowHandler.Execute(context, yieldPoint);
+ }
+ }
+}
diff --git a/Tapeti.Flow/Default/FlowProvider.cs b/Tapeti.Flow/Default/FlowProvider.cs
index 5c6d9d9..9da8a7d 100644
--- a/Tapeti.Flow/Default/FlowProvider.cs
+++ b/Tapeti.Flow/Default/FlowProvider.cs
@@ -4,9 +4,9 @@ using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
-using RabbitMQ.Client.Framing;
using Tapeti.Annotations;
using Tapeti.Config;
+using Tapeti.Default;
using Tapeti.Flow.Annotations;
using Tapeti.Flow.FlowHelpers;
@@ -14,11 +14,11 @@ namespace Tapeti.Flow.Default
{
public class FlowProvider : IFlowProvider, IFlowHandler
{
- private readonly IConfig config;
+ private readonly ITapetiConfig config;
private readonly IInternalPublisher publisher;
- public FlowProvider(IConfig config, IPublisher publisher)
+ public FlowProvider(ITapetiConfig config, IPublisher publisher)
{
this.config = config;
this.publisher = (IInternalPublisher)publisher;
@@ -72,7 +72,7 @@ namespace Tapeti.Flow.Default
ConvergeMethodSync = convergeMethodTaskSync
});
- var properties = new BasicProperties
+ var properties = new MessageProperties
{
CorrelationId = continuationID.ToString(),
ReplyTo = responseHandlerInfo.ReplyToQueue
@@ -96,12 +96,10 @@ namespace Tapeti.Flow.Default
if (message.GetType().FullName != reply.ResponseTypeName)
throw new YieldPointException($"Flow must end with a response message of type {reply.ResponseTypeName}, {message.GetType().FullName} was returned instead");
- var properties = new BasicProperties();
-
- // Only set the property if it's not null, otherwise a string reference exception can occur:
- // http://rabbitmq.1065348.n5.nabble.com/SocketException-when-invoking-model-BasicPublish-td36330.html
- if (reply.CorrelationId != null)
- properties.CorrelationId = reply.CorrelationId;
+ var properties = new MessageProperties
+ {
+ CorrelationId = reply.CorrelationId
+ };
// TODO disallow if replyto is not specified?
if (reply.ReplyTo != null)
@@ -122,9 +120,9 @@ namespace Tapeti.Flow.Default
}
- private static ResponseHandlerInfo GetResponseHandlerInfo(IConfig config, object request, Delegate responseHandler)
+ private static ResponseHandlerInfo GetResponseHandlerInfo(ITapetiConfig config, object request, Delegate responseHandler)
{
- var binding = config.GetBinding(responseHandler);
+ var binding = config.Bindings.ForMethod(responseHandler);
if (binding == null)
throw new ArgumentException("responseHandler must be a registered message handler", nameof(responseHandler));
@@ -158,13 +156,13 @@ namespace Tapeti.Flow.Default
CorrelationId = context.Properties.CorrelationId,
ReplyTo = context.Properties.ReplyTo,
ResponseTypeName = requestAttribute.Response.FullName,
- Mandatory = context.Properties.Persistent
+ Mandatory = context.Properties.Persistent.GetValueOrDefault(true)
};
}
- private async Task CreateNewFlowState(FlowContext flowContext)
+ private static async Task CreateNewFlowState(FlowContext flowContext)
{
- var flowStore = flowContext.MessageContext.DependencyResolver.Resolve();
+ var flowStore = flowContext.MessageContext.Config.DependencyResolver.Resolve();
var flowID = Guid.NewGuid();
flowContext.FlowStateLock = await flowStore.LockFlowState(flowID);
@@ -181,25 +179,20 @@ namespace Tapeti.Flow.Default
};
}
- public async Task Execute(IMessageContext context, IYieldPoint yieldPoint)
+ public async Task Execute(IControllerMessageContext context, IYieldPoint yieldPoint)
{
if (!(yieldPoint is DelegateYieldPoint executableYieldPoint))
throw new YieldPointException($"Yield point is required in controller {context.Controller.GetType().Name} for method {context.Binding.Method.Name}");
- FlowContext flowContext;
-
- if (!context.Items.TryGetValue(ContextItems.FlowContext, out var flowContextItem))
+ if (!context.Get(ContextItems.FlowContext, out FlowContext flowContext))
{
flowContext = new FlowContext
{
MessageContext = context
};
- context.Items.Add(ContextItems.FlowContext, flowContext);
+ context.Store(ContextItems.FlowContext, flowContext);
}
- else
- flowContext = (FlowContext)flowContextItem;
-
try
{
@@ -234,12 +227,12 @@ namespace Tapeti.Flow.Default
}
- private readonly IConfig config;
+ private readonly ITapetiConfig config;
private readonly SendRequestFunc sendRequest;
private readonly List requests = new List();
- public ParallelRequestBuilder(IConfig config, SendRequestFunc sendRequest)
+ public ParallelRequestBuilder(ITapetiConfig config, SendRequestFunc sendRequest)
{
this.config = config;
this.sendRequest = sendRequest;
diff --git a/Tapeti.Flow/Default/FlowStarter.cs b/Tapeti.Flow/Default/FlowStarter.cs
index 306f034..ab8a152 100644
--- a/Tapeti.Flow/Default/FlowStarter.cs
+++ b/Tapeti.Flow/Default/FlowStarter.cs
@@ -9,11 +9,11 @@ namespace Tapeti.Flow.Default
{
public class FlowStarter : IFlowStarter
{
- private readonly IConfig config;
+ private readonly ITapetiConfig config;
private readonly ILogger logger;
- public FlowStarter(IConfig config, ILogger logger)
+ public FlowStarter(ITapetiConfig config, ILogger logger)
{
this.config = config;
this.logger = logger;
@@ -47,9 +47,9 @@ namespace Tapeti.Flow.Default
var controller = config.DependencyResolver.Resolve();
var yieldPoint = await getYieldPointResult(method.Invoke(controller, parameters));
- var context = new MessageContext
+ var context = new ControllerMessageContext
{
- DependencyResolver = config.DependencyResolver,
+ Config = config,
Controller = controller
};
@@ -72,6 +72,7 @@ namespace Tapeti.Flow.Default
private async Task RunCleanup(MessageContext context, HandlingResult handlingResult)
{
+ /*
foreach (var handler in config.CleanupMiddleware)
{
try
@@ -83,6 +84,7 @@ namespace Tapeti.Flow.Default
logger.HandlerException(eCleanup);
}
}
+ */
}
diff --git a/Tapeti.Flow/FlowMiddleware.cs b/Tapeti.Flow/FlowMiddleware.cs
index ddc1d61..a4b9cdb 100644
--- a/Tapeti.Flow/FlowMiddleware.cs
+++ b/Tapeti.Flow/FlowMiddleware.cs
@@ -25,7 +25,6 @@ namespace Tapeti.Flow
public IEnumerable