1
0
mirror of synced 2024-11-21 17:03:50 +00:00

Fixed timing issue when a parallel flow response arrives before the flow is stored

This commit is contained in:
Mark van Renswoude 2023-04-17 16:40:26 +02:00
parent b66c448c17
commit 0573ffc93c
2 changed files with 49 additions and 22 deletions

View File

@ -94,6 +94,8 @@ namespace Tapeti.Flow.Default
var flowHandler = context.Config.DependencyResolver.Resolve<IFlowHandler>(); var flowHandler = context.Config.DependencyResolver.Resolve<IFlowHandler>();
return flowHandler.Execute(new FlowHandlerContext(context), new DelegateYieldPoint(async flowContext => return flowHandler.Execute(new FlowHandlerContext(context), new DelegateYieldPoint(async flowContext =>
{ {
// IFlowParallelRequest.AddRequest will store the flow immediately
if (!flowPayload.FlowContext.IsStoredOrDeleted())
await flowContext.Store(context.Binding.QueueType == QueueType.Durable); await flowContext.Store(context.Binding.QueueType == QueueType.Durable);
})); }));
} }

View File

@ -48,7 +48,7 @@ namespace Tapeti.Flow.Default
/// <inheritdoc /> /// <inheritdoc />
public IFlowParallelRequestBuilder YieldWithParallelRequest() public IFlowParallelRequestBuilder YieldWithParallelRequest()
{ {
return new ParallelRequestBuilder(config, this); return new ParallelRequestBuilder(config, this, publisher);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -64,8 +64,8 @@ namespace Tapeti.Flow.Default
} }
internal async Task SendRequest(FlowContext context, object message, ResponseHandlerInfo responseHandlerInfo, internal async Task<MessageProperties> PrepareRequest(FlowContext context, ResponseHandlerInfo responseHandlerInfo,
string convergeMethodName = null, bool convergeMethodTaskSync = false, bool store = true) string convergeMethodName = null, bool convergeMethodTaskSync = false)
{ {
if (context.FlowState == null) if (context.FlowState == null)
{ {
@ -89,7 +89,14 @@ namespace Tapeti.Flow.Default
ReplyTo = responseHandlerInfo.ReplyToQueue ReplyTo = responseHandlerInfo.ReplyToQueue
}; };
if (store) return properties;
}
internal async Task SendRequest(FlowContext context, object message, ResponseHandlerInfo responseHandlerInfo,
string convergeMethodName = null, bool convergeMethodTaskSync = false)
{
var properties = await PrepareRequest(context, responseHandlerInfo, convergeMethodName, convergeMethodTaskSync);
await context.Store(responseHandlerInfo.IsDurableQueue); await context.Store(responseHandlerInfo.IsDurableQueue);
await publisher.Publish(message, properties, true); await publisher.Publish(message, properties, true);
@ -297,13 +304,15 @@ namespace Tapeti.Flow.Default
private readonly ITapetiConfig config; private readonly ITapetiConfig config;
private readonly FlowProvider flowProvider; private readonly FlowProvider flowProvider;
private readonly IInternalPublisher publisher;
private readonly List<RequestInfo> requests = new List<RequestInfo>(); private readonly List<RequestInfo> requests = new List<RequestInfo>();
public ParallelRequestBuilder(ITapetiConfig config, FlowProvider flowProvider) public ParallelRequestBuilder(ITapetiConfig config, FlowProvider flowProvider, IInternalPublisher publisher)
{ {
this.config = config; this.config = config;
this.flowProvider = flowProvider; this.flowProvider = flowProvider;
this.publisher = publisher;
} }
@ -325,7 +334,7 @@ namespace Tapeti.Flow.Default
} }
public IFlowParallelRequestBuilder InternalAddRequest(object message, Delegate responseHandler) private IFlowParallelRequestBuilder InternalAddRequest(object message, Delegate responseHandler)
{ {
requests.Add(new RequestInfo requests.Add(new RequestInfo
{ {
@ -378,18 +387,21 @@ namespace Tapeti.Flow.Default
if (convergeMethod.Method.DeclaringType != context.HandlerContext.Controller.GetType()) if (convergeMethod.Method.DeclaringType != context.HandlerContext.Controller.GetType())
throw new YieldPointException("Converge method must be in the same controller class"); throw new YieldPointException("Converge method must be in the same controller class");
var preparedRequests = new List<PreparedRequest>();
foreach (var requestInfo in requests) foreach (var requestInfo in requests)
{ {
await flowProvider.SendRequest( var properties = await flowProvider.PrepareRequest(
context, context,
requestInfo.Message,
requestInfo.ResponseHandlerInfo, requestInfo.ResponseHandlerInfo,
convergeMethod.Method.Name, convergeMethod.Method.Name,
convergeMethodSync, convergeMethodSync);
false);
preparedRequests.Add(new PreparedRequest(requestInfo.Message, properties));
} }
await context.Store(requests.Any(i => i.ResponseHandlerInfo.IsDurableQueue)); await context.Store(requests.Any(i => i.ResponseHandlerInfo.IsDurableQueue));
await Task.WhenAll(preparedRequests.Select(r => publisher.Publish(r.Message, r.Properties, true)));
}); });
} }
} }
@ -437,8 +449,7 @@ namespace Tapeti.Flow.Default
message, message,
responseHandlerInfo, responseHandlerInfo,
flowContext.ContinuationMetadata.ConvergeMethodName, flowContext.ContinuationMetadata.ConvergeMethodName,
flowContext.ContinuationMetadata.ConvergeMethodSync, flowContext.ContinuationMetadata.ConvergeMethodSync);
false);
} }
} }
@ -449,5 +460,19 @@ namespace Tapeti.Flow.Default
public string ReplyToQueue { get; set; } public string ReplyToQueue { get; set; }
public bool IsDurableQueue { get; set; } public bool IsDurableQueue { get; set; }
} }
internal class PreparedRequest
{
public object Message { get; }
public MessageProperties Properties { get; }
public PreparedRequest(object message, MessageProperties properties)
{
Message = message;
Properties = properties;
}
}
} }
} }