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();
        }
Exemple #2
0
        // 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);
        }
Exemple #13
0
        // 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);
            }
        }