private async Task SendResponse(FlowContext context, object message) { var reply = context.FlowState == null ? GetReply(context.HandlerContext) : context.FlowState.Metadata.Reply; if (reply == null) { throw new YieldPointException("No response is required"); } 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 MessageProperties { CorrelationId = reply.CorrelationId }; // TODO disallow if replyto is not specified? if (reply.ReplyTo != null) { await publisher.PublishDirect(message, reply.ReplyTo, properties, reply.Mandatory); } else { await publisher.Publish(message, properties, reply.Mandatory); } await context.Delete(); }
private async Task SendRequest(FlowContext context, object message, ResponseHandlerInfo responseHandlerInfo, string convergeMethodName = null, bool convergeMethodTaskSync = false) { if (context.FlowState == null) { await CreateNewFlowState(context); Debug.Assert(context.FlowState != null, "context.FlowState != null"); } var continuationID = Guid.NewGuid(); context.FlowState.Continuations.Add(continuationID, new ContinuationMetadata { MethodName = responseHandlerInfo.MethodName, ConvergeMethodName = convergeMethodName, ConvergeMethodSync = convergeMethodTaskSync }); var properties = new MessageProperties { CorrelationId = continuationID.ToString(), ReplyTo = responseHandlerInfo.ReplyToQueue }; await context.Store(responseHandlerInfo.IsDurableQueue); await publisher.Publish(message, properties, true); }
private static async Task EndFlow(FlowContext context) { await context.Delete(); if (context.FlowState?.Metadata.Reply != null) { throw new YieldPointException($"Flow must end with a response message of type {context.FlowState.Metadata.Reply.ResponseTypeName}"); } }
private static async Task <FlowContext> GetFlowContext(IMessageContext context) { if (context.Items.ContainsKey(ContextItems.FlowContext)) { return((FlowContext)context.Items[ContextItems.FlowContext]); } if (context.Properties.CorrelationId == null) { return(null); } Guid continuationID; if (!Guid.TryParse(context.Properties.CorrelationId, out continuationID)) { return(null); } var flowStore = context.DependencyResolver.Resolve <IFlowStore>(); 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); } ContinuationMetadata continuation; var flowContext = new FlowContext { MessageContext = context, FlowStateLock = flowStateLock, FlowState = flowState, ContinuationID = continuationID, ContinuationMetadata = flowState.Continuations.TryGetValue(continuationID, out continuation) ? continuation : null }; // IDisposable items in the IMessageContext are automatically disposed context.Items.Add(ContextItems.FlowContext, flowContext); return(flowContext); }
/// <inheritdoc /> public async Task Execute(IFlowHandlerContext context, IYieldPoint yieldPoint) { if (!(yieldPoint is DelegateYieldPoint executableYieldPoint)) { throw new YieldPointException($"Yield point is required in controller {context.Controller.GetType().Name} for method {context.Method.Name}"); } FlowContext flowContext = null; var disposeFlowContext = false; try { var messageContext = context.ControllerMessageContext; if (messageContext == null || !messageContext.Get(ContextItems.FlowContext, out flowContext)) { flowContext = new FlowContext { HandlerContext = context }; // If we ended up here it is because of a Start. No point in storing the new FlowContext // in the messageContext as the yield point is the last to execute. disposeFlowContext = true; } try { await executableYieldPoint.Execute(flowContext); } catch (YieldPointException e) { // Useful for debugging e.Data["Tapeti.Controller.Name"] = context.Controller.GetType().FullName; e.Data["Tapeti.Controller.Method"] = context.Method.Name; throw; } flowContext.EnsureStoreOrDeleteIsCalled(); } finally { if (disposeFlowContext) { flowContext.Dispose(); } } }
public async Task Execute(IMessageContext context, IYieldPoint yieldPoint) { var executableYieldPoint = yieldPoint as DelegateYieldPoint; if (executableYieldPoint == null) { throw new YieldPointException($"Yield point is required in controller {context.Controller.GetType().Name} for method {context.Binding.Method.Name}"); } FlowContext flowContext; object flowContextItem; if (!context.Items.TryGetValue(ContextItems.FlowContext, out flowContextItem)) { flowContext = new FlowContext { MessageContext = context }; context.Items.Add(ContextItems.FlowContext, flowContext); } else { flowContext = (FlowContext)flowContextItem; } try { if (executableYieldPoint != null) { await executableYieldPoint.Execute(flowContext); } } catch (YieldPointException e) { // Useful for debugging e.Data["Tapeti.Controller.Name"] = context.Controller.GetType().FullName; e.Data["Tapeti.Controller.Method"] = context.Binding.Method.Name; throw; } flowContext.EnsureStoreOrDeleteIsCalled(); }
private static async Task CreateNewFlowState(FlowContext flowContext) { var flowStore = flowContext.HandlerContext.Config.DependencyResolver.Resolve <IFlowStore>(); var flowID = Guid.NewGuid(); flowContext.FlowStateLock = await flowStore.LockFlowState(flowID); if (flowContext.FlowStateLock == null) { throw new InvalidOperationException("Unable to lock a new flow"); } flowContext.FlowState = new FlowState { Metadata = new FlowMetadata { Reply = GetReply(flowContext.HandlerContext) } }; }
private async Task SendResponse(FlowContext context, object message) { var reply = context.FlowState == null ? GetReply(context.MessageContext) : context.FlowState.Metadata.Reply; if (reply == null) { throw new YieldPointException("No response is required"); } 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; } // TODO disallow if replyto is not specified? if (reply.ReplyTo != null) { await publisher.PublishDirect(message, reply.ReplyTo, properties); } else { await publisher.Publish(message, properties); } await context.Delete(); }
public Task Execute(FlowContext context) { return(onExecute(context)); }
public async Task Execute(FlowContext context) { await onExecute(context); }