public async Task <TFlowResponse> Handle(TFlowRequest flowRequest, CancellationToken cancellationToken) { // TODO: Respect the cancellation token var flowContext = new FlowContext(typeof(TFlowRequest), flowRequest.FlowContext); try { var stopWatch = new Stopwatch(); stopWatch.Start(); using (flowContext.IsRootFlow ? _logger?.BeginFlowScope(flowContext) : null) { _logger?.LogFlowRequest(flowContext, flowRequest); var flowDefinition = ResolveFlowDefinition(flowRequest, flowContext); var flowValues = GetInitialFlowValues(flowDefinition, flowRequest); var flowTrace = new FlowTrace(); var flowStepIndex = 0; while (flowStepIndex < flowDefinition.Steps.Count) { var flowStep = flowDefinition.Steps[flowStepIndex]; var stepFlowContext = flowContext.GetStepContext(flowStep.Name); OnDebugEvent(flowStep.Name, FlowDebugEvent.PreStep, flowValues); flowStepIndex = await PerformFlowStep( stepFlowContext, flowDefinition, flowStep, flowStepIndex, flowValues, flowTrace, cancellationToken); OnDebugEvent(flowStep.Name, FlowDebugEvent.PostStep, flowValues); } var flowResponse = BuildFlowResponse(flowContext, flowDefinition, flowTrace, flowValues); stopWatch.Stop(); _logger?.LogFlowResponse(flowContext, flowResponse, stopWatch.ElapsedMilliseconds); return(flowResponse); } } catch (Exception ex) when(LogFlowError(flowContext, flowRequest, ex)) { throw; } }