void FinishStep(AsyncStep step, IAsyncResult result) { Exception error = null; try { step.End(this.iterState, result); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } error = e; } if (error != null) { this.HandleException(error, step); } this.OnStepCompletion(); }
// Returns true if a handler matched the Exception, false otherwise. bool HandleException(Exception e) { bool handled; this.LastAsyncStepException = e; AsyncStep step = this.steps.Current; switch (step.Policy) { case ExceptionPolicy.Continue: handled = true; break; case ExceptionPolicy.Transfer: handled = false; if (!this.IsCompleted) { this.Complete(e); handled = true; } break; default: handled = false; break; } return(handled); }
IAsyncResult StartStep(AsyncStep step) { IAsyncResult result = null; Exception error = null; try { this.OnStepStart(); result = step.Begin( this.iterState, this.timeoutHelper.RemainingTime(), this.onStepCompletedCallback, step); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } error = e; } if (error != null) { this.HandleException(error, step); } return(result); }
public async void ProcessForkWithException() { // Arrange var settings = new StepSettings { TrackStateChanges = true, AutoProgress = true }; const string firstStepName = "first"; const string forkStepName = "fork"; const string secondStepName = "second"; const string exceptionalStepName = "exceptionalStep"; const string fourthStepName = "fourth"; var firstBaseStep = new BaseStep(firstStepName, settings); var secondStepAsync = new AsyncStep(500, secondStepName); var exceptionalStep = new ExceptionalStep(exceptionalStepName); var fourthStepAsync = new AsyncStep(200, fourthStepName); firstBaseStep.Fork( name: forkStepName, stepSettings: settings, secondStepAsync, exceptionalStep, fourthStepAsync); var expectedExecutionStarted = new[] { firstStepName, forkStepName, secondStepName, exceptionalStepName, fourthStepName }; var expectedExecutionCompletionOrder = new[] { firstStepName, fourthStepName, secondStepName }; var expectedFailedOrder = new[] { forkStepName, exceptionalStepName }; // Actssert try { await firstBaseStep.Execute(_workflowState); } catch (WorkflowActionException <SimpleWorkflowState> ex) { var result = ex.WorkflowState; var orderedByStarted = result.WorkflowChain.ToList().Select(x => x.StepName).ToArray(); var orderedByCompletion = result.WorkflowChain.ToList() .Where(x => x.StepActivities.Any(y => y.Activity == StepActivityStages.ExecutionCompleted)) .OrderBy(x => x.StepActivities.FirstOrDefault(y => y.Activity == StepActivityStages.ExecutionCompleted).DateTimeOffset) .Select(x => x.StepName) .ToArray(); var failedStepNames = result.WorkflowChain.ToList() .Where(x => x.StepActivities.Any(y => y.Activity == StepActivityStages.ExecutionFailed)) .Select(x => x.StepName) .ToArray(); // Assert Assert.True(expectedExecutionStarted.SequenceEqual(orderedByStarted)); Assert.True(expectedExecutionCompletionOrder.SequenceEqual(orderedByCompletion)); Assert.True(expectedFailedOrder.SequenceEqual(failedStepNames)); } }
static AsyncStep GetDequeueStep() { if (dequeueStep == null) { dequeueStep = RandomDelayQueuedSendsAsyncResult <TItem> .CallAsync( (thisPtr, t, c, s) => thisPtr.itemQueue.BeginDequeue(TimeSpan.MaxValue, c, s), (thisPtr, r) => thisPtr.currentItem = thisPtr.itemQueue.EndDequeue(r)); } return(dequeueStep); }
static AsyncStep GetSendItemStep() { if (sendItemStep == null) { sendItemStep = RandomDelayQueuedSendsAsyncResult <TItem> .CallParallel( (thisPtr, t, c, s) => thisPtr.OnBeginSendItem(thisPtr.currentItem, t, c, s), (thisPtr, r) => thisPtr.OnEndSendItem(r)); } return(sendItemStep); }
static AsyncStep GetDelayStep() { if (delayStep == null) { delayStep = RandomDelayQueuedSendsAsyncResult <TItem> .CallAsync( (thisPtr, t, c, s) => thisPtr.BeginDelay(c, s), (thisPtr, r) => thisPtr.EndDelay(r)); } return(delayStep); }
static AsyncStep GetDequeueStep() { if (dequeueStep == null) { dequeueStep = DiscoveryChannelBuilderAsyncResult.CallAsync( (thisPtr, t, c, s) => thisPtr.discoveryClientChannelBase.discoveredEndpoints.BeginDequeue(thisPtr.RemainingTime(), c, s), (thisPtr, r) => thisPtr.currentEndpointDiscoveryMetadata = thisPtr.discoveryClientChannelBase.discoveredEndpoints.EndDequeue(r), new IAsyncCatch[] { new DiscoveryChannelBuilderAsyncResult.AsyncCatch <TimeoutException>(HandleTimeoutException) }); } return(dequeueStep); }
void OnStepCompleted(IAsyncResult result) { if (result.CompletedSynchronously) { return; } this.completedSynchronously = false; AsyncStep step = (AsyncStep)result.AsyncState; this.FinishStep(step, result); if (!step.IsParallel) { this.ExecuteSteps(); } }
static AsyncStep GetOpenStep() { if (openStep == null) { openStep = DiscoveryChannelBuilderAsyncResult.CallAsync( (thisPtr, t, c, s) => thisPtr.innerChannel.BeginOpen(thisPtr.RemainingTime(), c, s), (thisPtr, r) => thisPtr.innerChannel.EndOpen(r), new IAsyncCatch[] { new DiscoveryChannelBuilderAsyncResult.AsyncCatch <TimeoutException>(HandleTimeoutException), new DiscoveryChannelBuilderAsyncResult.AsyncCatch <CommunicationException>(HandleCommunicationException), new DiscoveryChannelBuilderAsyncResult.AsyncCatch <Exception>(HandleException) }); } return(openStep); }
public async void ProcessFork() { // Arrange var settings = new StepSettings { TrackStateChanges = true, AutoProgress = true }; const string firstStepName = "first"; const string forkStepName = "fork"; const string secondStepName = "second"; const string thirdStepName = "third"; const string fourthStepName = "fourth"; var firstBaseStep = new BaseStep(firstStepName, settings); var secondStepAsync = new AsyncStep(500, secondStepName); var thirdStepAsync = new AsyncStep(0, thirdStepName); var fourthStepAsync = new AsyncStep(200, fourthStepName); firstBaseStep.Fork( name: forkStepName, stepSettings: settings, secondStepAsync, thirdStepAsync, fourthStepAsync); var expectedExecutionStarted = new[] { firstStepName, forkStepName, secondStepName, thirdStepName, fourthStepName }; var expectedExecutionCompletionOrder = new[] { firstStepName, thirdStepName, fourthStepName, secondStepName, forkStepName }; // Act var result = await firstBaseStep.Execute(_workflowState); var orderedByStarted = result.WorkflowChain.ToList().Select(x => x.StepName).ToArray(); var orderedByCompletion = result.WorkflowChain.ToList() .OrderBy(x => x.StepActivities.FirstOrDefault(y => y.Activity == StepActivityStages.ExecutionCompleted).DateTimeOffset) .Select(x => x.StepName) .ToArray(); // Assert Assert.True(expectedExecutionStarted.SequenceEqual(orderedByStarted)); Assert.True(expectedExecutionCompletionOrder.SequenceEqual(orderedByCompletion)); }
void HandleException(Exception e, AsyncStep step) { if (step.Catches != null) { Exception outException; for (int i = 0; i < step.Catches.Length; i++) { if (step.Catches[i].HandleException(iterState, e, out outException)) { if (outException != null) { this.CompleteOnce(outException); } else { return; } } } } // The exception wasn't handled this.CompleteOnce(e); }
// This runs async steps until one of them completes asynchronously, or until // Begin throws on the Start thread with a policy of PassThrough. void EnumerateSteps(CurrentThreadType state) { while (!this.IsCompleted && this.MoveNextStep()) { this.LastAsyncStepException = null; AsyncStep step = this.steps.Current; if (step.BeginCall != null) { IAsyncResult result = null; if (state == CurrentThreadType.Synchronous && step.HasSynchronous) { if (step.Policy == ExceptionPolicy.Transfer) { step.Call((TIteratorAsyncResult)this, this.timeoutHelper.RemainingTime()); } else { try { step.Call((TIteratorAsyncResult)this, this.timeoutHelper.RemainingTime()); } catch (Exception e) { if (!this.HandleException(e)) { throw; } } } } else { if (step.Policy == ExceptionPolicy.Transfer) { result = step.BeginCall( (TIteratorAsyncResult)this, this.timeoutHelper.RemainingTime(), this.PrepareAsyncCompletion(IteratorAsyncResult <TIteratorAsyncResult> .StepCallbackDelegate), this); } else { try { result = step.BeginCall( (TIteratorAsyncResult)this, this.timeoutHelper.RemainingTime(), this.PrepareAsyncCompletion(IteratorAsyncResult <TIteratorAsyncResult> .StepCallbackDelegate), this); } catch (Exception e) { if (!this.HandleException(e)) { throw; } } } } if (result != null) { if (!this.CheckSyncContinue(result)) { return; } try { // Don't refactor this into a seperate method. It adds one extra call stack reducing readibility of call stack in trace. this.steps.Current.EndCall((TIteratorAsyncResult)this, result); } catch (Exception e) { if (!this.HandleException(e)) { throw; } } } } } if (!this.IsCompleted) { this.Complete(!this.everCompletedAsynchronously); } }