public void ShouldFindSingleChild() { var continuation = new Continuation {Id = _job.Id}; var match = continuation.Find(_job); Assert.Equal(continuation, match); }
public void ReturnsTrueForContinuableContinuationsWithoutAnyFailureHandlers() { var continuation = new Continuation {Status = JobStatus.Poisoned, ContinueAfterHandlingFailure = true}; var result = continuation.CanContinue(); Assert.True(result); }
public void ReturnsFalseIfAnyChildContinuationIsNotContinuable() { var continuation = new Continuation { Status = JobStatus.Created, Children = new[] {new Continuation {Status = JobStatus.Poisoned}} }; var result = continuation.CanContinue(); Assert.False(result); }
public void ShouldFindNextContinuation() { var continuation = new Continuation { Id = Guid.NewGuid(), Next = new Continuation {Id = _job.Id} }; var match = continuation.Find(_job); Assert.Equal(continuation.Next, match); }
public void ShouldFindContinuationsInOnAnyFailure() { var continuation = new Continuation { Id = Guid.NewGuid(), OnAnyFailed = new Continuation {Id = _job.Id} }; var match = continuation.Find(_job); Assert.Equal(continuation.OnAnyFailed, match); }
public void ReturnsFalseIfAnyFailureHandlerIsFailed() { var continuation = new Continuation { Status = JobStatus.Poisoned, ContinueAfterHandlingFailure = true, OnAllFailed = new Continuation {Status = JobStatus.Poisoned} }; var result = continuation.CanContinue(); Assert.False(result); }
public void ReturnsNextIfAllContinuationsInGroupedIsComplete() { var continuation = new Continuation { Type = ContinuationType.Parallel, Children = new[] {new Continuation {Status = JobStatus.Completed}}, Next = new Continuation() }; var pending = continuation.PendingContinuations(); Assert.Equal(continuation.Next, pending.Single()); }
public void ReturnsFalseForGroupWithFailedChildrenAndFailedAnyFailureHandler() { var continuation = new Continuation { Status = JobStatus.Created, Children = new[] {new Continuation {Status = JobStatus.Poisoned}}, ContinueAfterHandlingFailure = true, OnAnyFailed = new Continuation {Status = JobStatus.Poisoned}, OnAllFailed = new Continuation {Status = JobStatus.Completed} }; var result = continuation.CanContinue(); Assert.False(result); }
public void ShouldFindContinuationsInGroup() { var matchingChild = new Continuation {Id = _job.Id}; var continuation = new Continuation { Children = new [] { new Continuation { Id = Guid.NewGuid() }, matchingChild } }; var match = continuation.Find(_job); Assert.Equal(matchingChild, match); }
ConvertedActivity ConvertActivityGroupToContinuation( ActivityGroup activityGroup, Job parent, IEnumerable<ExceptionFilter> inheritedExceptionFilters) { var jobs = Enumerable.Empty<Job>(); /* * Activities in a group inherit exception filters defined * in the group as well as the ones inherited by the group. */ var effectiveExceptionFilters = inheritedExceptionFilters.Concat(activityGroup.ExceptionFilters).ToArray(); var convertedItems = activityGroup.Items.Select(item => ConvertCore(item, parent, effectiveExceptionFilters)).ToArray(); jobs = convertedItems.Aggregate(jobs, (current, converted) => current.Concat(converted.Jobs)); var continuation = new Continuation { Type = activityGroup.IsParallel ? ContinuationType.Parallel : ContinuationType.Sequence, ContinueAfterHandlingFailure = activityGroup.CanContinueAfterHandlingFailure, Children = convertedItems.Select(c => c.Continuation) }; var onNext = ConvertCore(activityGroup.Next, parent, effectiveExceptionFilters); continuation.Next = onNext.Continuation; jobs = jobs.Concat(onNext.Jobs); var onAnyFailed = ConvertCore(activityGroup.OnAnyFailed, parent, effectiveExceptionFilters); continuation.OnAnyFailed = onAnyFailed.Continuation; jobs = jobs.Concat(onAnyFailed.Jobs); var onAllFailed = ConvertCore(activityGroup.OnAllFailed, parent, effectiveExceptionFilters); continuation.OnAllFailed = onAllFailed.Continuation; jobs = jobs.Concat(onAllFailed.Jobs); var onCancelled = ConvertCore(activityGroup.OnCancel, parent, effectiveExceptionFilters); if (onCancelled.Continuation != null) onCancelled.Continuation.CompensateForCancellation = true; continuation.OnCancelled = onCancelled.Continuation; jobs = jobs.Concat(onCancelled.Jobs); return new ConvertedActivity(continuation, jobs); }
public void ReturnsNextIfAnyFailedContinuationHasCompletedRecoverableContinuation() { var continuation = new Continuation { Type = ContinuationType.Parallel, Children = new[] { new Continuation {Status = JobStatus.Poisoned} }, ContinueAfterHandlingFailure = true, OnAnyFailed = new Continuation {Status = JobStatus.Completed}, Next = new Continuation() }; var pending = continuation.PendingContinuations(); Assert.Equal(continuation.Next, pending.Single()); }
public static bool CanContinue(this Continuation item, bool isFailureHandler = false) { if (item.Children.Any()) // Is this a group? { var noOfSuccessfulChildren = item.Children.Count(c => c.CanContinue()); if (noOfSuccessfulChildren == item.Children.Count()) { return(true); } // We come here if we've got at least one failing child. // First make sure we can continue if we run our failure handlers. if (!item.ContinueAfterHandlingFailure) { return(false); } // Have they all failed? if (noOfSuccessfulChildren == 0) { return((item.OnAllFailed == null || item.OnAllFailed.CanContinue(true)) && (item.OnAnyFailed == null || item.OnAnyFailed.CanContinue(true))); } return(item.OnAnyFailed == null || item.OnAnyFailed.CanContinue(true)); } // If this item is already completed we can continue if there's no next item or // next item can also continue. if (item.Status == JobStatus.Completed) { return(!isFailureHandler || item.Next == null || item.Next.CanContinue()); } if (item.Status == JobStatus.Poisoned) { // We cannot continue if await does not handle failures return(item.ContinueAfterHandlingFailure && (item.OnAllFailed == null || item.OnAllFailed.CanContinue(true))); } return(false); }
ConvertedActivity ConvertActivityGroupToContinuation( ActivityGroup activityGroup, Job parent, IEnumerable <ExceptionFilter> inheritedExceptionFilters) { var jobs = Enumerable.Empty <Job>(); /* * Activities in a group inherit exception filters defined * in the group as well as the ones inherited by the group. */ var effectiveExceptionFilters = inheritedExceptionFilters.Concat(activityGroup.ExceptionFilters).ToArray(); var convertedItems = activityGroup.Items.Select(item => ConvertCore(item, parent, effectiveExceptionFilters)).ToArray(); jobs = convertedItems.Aggregate(jobs, (current, converted) => current.Concat(converted.Jobs)); var continuation = new Continuation { Type = activityGroup.IsParallel ? ContinuationType.Parallel : ContinuationType.Sequence, ContinueAfterHandlingFailure = activityGroup.CanContinueAfterHandlingFailure, Children = convertedItems.Select(c => c.Continuation) }; var onNext = ConvertCore(activityGroup.Next, parent, effectiveExceptionFilters); continuation.Next = onNext.Continuation; jobs = jobs.Concat(onNext.Jobs); var onAnyFailed = ConvertCore(activityGroup.OnAnyFailed, parent, effectiveExceptionFilters); continuation.OnAnyFailed = onAnyFailed.Continuation; jobs = jobs.Concat(onAnyFailed.Jobs); var onAllFailed = ConvertCore(activityGroup.OnAllFailed, parent, effectiveExceptionFilters); continuation.OnAllFailed = onAllFailed.Continuation; jobs = jobs.Concat(onAllFailed.Jobs); return(new ConvertedActivity(continuation, jobs)); }
public void ReturnsAllIncompleteContinuationsInGrouped() { var created = new Continuation { Status = JobStatus.Created }; var ready = new Continuation { Status = JobStatus.Ready }; var completed = new Continuation {Status = JobStatus.Completed}; var poisoned = new Continuation {Status = JobStatus.Poisoned}; var continuation = new Continuation { Type = ContinuationType.Parallel, Children = new[] {created, completed, poisoned, ready} }; var pending = continuation.PendingContinuations().ToArray(); Assert.Contains(created, pending); Assert.Contains(ready, pending); Assert.DoesNotContain(completed, pending); Assert.DoesNotContain(poisoned, pending); }
public Job( Guid id, Type type, string method, object[] arguments, DateTime createdOn, Guid? rootId = null, Guid? parentId = null, Guid? correlationId = null, JobStatus status = JobStatus.Ready, int dispatchCount = 0, DateTime? retryOn = null, ExceptionFilter[] exceptionFilters = null, Continuation continuation = null, bool? suspended = null) { if(type == null) throw new ArgumentNullException("type"); if (arguments == null) throw new ArgumentNullException("arguments"); if (string.IsNullOrWhiteSpace(method)) throw new ArgumentException("A valid method is required."); Method = method; Id = id; Type = type; Arguments = arguments; CreatedOn = createdOn; RootId = rootId ?? id; ParentId = parentId; CorrelationId = correlationId ?? id; Status = status; DispatchCount = dispatchCount; RetryOn = retryOn; Properties = new Dictionary<string, object>(); ExceptionFilters = exceptionFilters ?? new ExceptionFilter[0]; Continuation = continuation; Suspended = suspended ?? false; }
ConvertedActivity ConvertSingleActivityToContinuation( SingleActivity singleActivity, Job parent, ExceptionFilter[] inheritedExceptionFilters) { var job = new Job(Guid.NewGuid(), singleActivity.Type, singleActivity.Name, singleActivity.Arguments, _now(), rootId: parent.RootId, parentId: parent.Id, status: JobStatus.Created, exceptionFilters: inheritedExceptionFilters.Concat(singleActivity.ExceptionFilters).ToArray()); var jobs = new List <Job>(new[] { job }); var continuation = new Continuation { Id = job.Id, Type = ContinuationType.Single, ContinueAfterHandlingFailure = singleActivity.CanContinueAfterHandlingFailure }; var onNext = ConvertCore(singleActivity.Next, parent, inheritedExceptionFilters); continuation.Next = onNext.Continuation; jobs.AddRange(onNext.Jobs); var onFailed = ConvertCore(singleActivity.OnFailed, parent, inheritedExceptionFilters); continuation.OnAllFailed = onFailed.Continuation; jobs.AddRange(onFailed.Jobs); return(new ConvertedActivity(continuation, jobs.AsEnumerable())); }
public void ReturnsTrueIfAllContinuationsInGroupAreCompleted() { var continuation = new Continuation { Status = JobStatus.Created, Children = new[] {new Continuation {Status = JobStatus.Completed}} }; var result = continuation.CanContinue(); Assert.True(result); }
public void ShouldReturnNextInSequence() { var continuation = new Continuation { Type = ContinuationType.Sequence, Children = new[] { new Continuation {Status = JobStatus.Completed}, new Continuation {Status = JobStatus.Created}, new Continuation {Status = JobStatus.Created} } }; var pending = continuation.PendingContinuations(); Assert.Equal(continuation.Children.ElementAt(1), pending.Single()); }
public void ReturnsTrueIfAllFailureHandlersAreCompleted() { var continuation = new Continuation { Status = JobStatus.Poisoned, ContinueAfterHandlingFailure = true, OnAnyFailed = new Continuation {Status = JobStatus.Completed}, OnAllFailed = new Continuation {Status = JobStatus.Completed} }; var result = continuation.CanContinue(); Assert.True(result); }
public void ShouldReturnAnyFailedContinuationIfAnyContinuationInGroupIsFailed() { var continuation = new Continuation { Type = ContinuationType.Parallel, Children = new[] { new Continuation {Status = JobStatus.Poisoned} }, OnAnyFailed = new Continuation() }; var pending = continuation.PendingContinuations(); Assert.Equal(continuation.OnAnyFailed, pending.Single()); }
public void ShouldReturnAnyFailedHandlerWhenAnyItemFailsInSequence() { var continuation = new Continuation { Type = ContinuationType.Sequence, Children = new[] { new Continuation {Status = JobStatus.Completed}, new Continuation {Status = JobStatus.Poisoned}, new Continuation {Status = JobStatus.Created} }, OnAnyFailed = new Continuation() }; var pending = continuation.PendingContinuations(); Assert.Equal(continuation.OnAnyFailed, pending.Single()); }
public ConvertedActivity(Continuation continuation, IEnumerable<Job> jobs) { if (jobs == null) throw new ArgumentNullException("jobs"); Continuation = continuation; Jobs = jobs; }
public void ShouldReturnAnyFailedContinuationIfAllContinuationsInGroupIsFailed() { var continuation = new Continuation { Type = ContinuationType.Parallel, Children = new[] { new Continuation {Status = JobStatus.Poisoned}, new Continuation {Status = JobStatus.Poisoned} }, OnAnyFailed = new Continuation(), OnAllFailed = new Continuation() }; var pending = continuation.PendingContinuations(); Assert.Contains(continuation.OnAnyFailed, pending); }
public void ShouldNotReturnNextIfSingleContinuationIsCreated() { var continuation = new Continuation {Next = new Continuation()}; var pending = continuation.PendingContinuations(); Assert.Equal(continuation, pending.Single()); }
public void ShouldNotReturnNextIfSingleContinuationIsFailed() { var continuation = new Continuation {Status = JobStatus.Poisoned, Next = new Continuation()}; var pending = continuation.PendingContinuations(); Assert.Empty(pending); }
public void ShouldNotReturnNextIfAllChilrenAreNotComplete() { var continuation = new Continuation { Children = new[] { new Continuation() }, Next = new Continuation() }; var pending = continuation.PendingContinuations(); Assert.DoesNotContain(continuation.Next, pending); }
public void ShouldNotReturnNextIfAnyContinuationInGroupIsFailed() { var continuation = new Continuation { Type = ContinuationType.Parallel, Children = new[] { new Continuation {Status = JobStatus.Completed}, new Continuation {Status = JobStatus.Poisoned} }, Next = new Continuation() }; var pending = continuation.PendingContinuations(); Assert.Empty(pending); }
public void ShouldNotReturnAllFailedContinuationIfAllContinuationsInGroupIsNotFailed() { var continuation = new Continuation { Children = new[] { new Continuation {Status = JobStatus.Completed}, new Continuation {Status = JobStatus.Poisoned} }, OnAllFailed = new Continuation() }; var pending = continuation.PendingContinuations(); Assert.DoesNotContain(continuation.OnAllFailed, pending); }
ConvertedActivity ConvertSingleActivityToContinuation( SingleActivity singleActivity, Job parent, ExceptionFilter[] inheritedExceptionFilters) { var job = new Job(Guid.NewGuid(), singleActivity.Type, singleActivity.Name, singleActivity.Arguments, _now(), rootId: parent.RootId, parentId: parent.Id, status: JobStatus.Created, exceptionFilters: inheritedExceptionFilters.Concat(singleActivity.ExceptionFilters).ToArray()); var jobs = new List<Job>(new[] {job}); var continuation = new Continuation { Id = job.Id, Type = ContinuationType.Single, ContinueAfterHandlingFailure = singleActivity.CanContinueAfterHandlingFailure }; var onNext = ConvertCore(singleActivity.Next, parent, inheritedExceptionFilters); continuation.Next = onNext.Continuation; jobs.AddRange(onNext.Jobs); var onFailed = ConvertCore(singleActivity.OnFailed, parent, inheritedExceptionFilters); continuation.OnAllFailed = onFailed.Continuation; jobs.AddRange(onFailed.Jobs); var onCancel = ConvertCore(singleActivity.OnCancel, parent, inheritedExceptionFilters); if (onCancel.Continuation != null) onCancel.Continuation.CompensateForCancellation = true; continuation.OnCancelled = onCancel.Continuation; jobs.AddRange(onCancel.Jobs); return new ConvertedActivity(continuation, jobs.AsEnumerable()); }
public void ReturnsSingleIncompleteContinuation(JobStatus incompleteStatus) { var continuation = new Continuation {Status = incompleteStatus}; var pending = continuation.PendingContinuations(); Assert.Equal(continuation, pending.Single()); }
public static IEnumerable <Continuation> PendingContinuations(this Continuation item) { if (item == null) { return(Enumerable.Empty <Continuation>()); } if (item.Type == ContinuationType.Single) { if (item.Status == JobStatus.Created || item.Status == JobStatus.Ready) { return new[] { item } } ; if (item.Status == JobStatus.Poisoned) { var failedHandler = item.OnAllFailed.PendingContinuations().ToArray(); if (!failedHandler.Any() && item.CanContinue()) { return(item.Next.PendingContinuations()); } return(failedHandler); } if (item.Status == JobStatus.Completed) { return(item.Next.PendingContinuations()); } } if (item.Type == ContinuationType.Parallel) { var children = item.Children.SelectMany(a => a.PendingContinuations()).ToArray(); if (children.Any()) { return(children); } } if (item.Type == ContinuationType.Sequence) { foreach (var child in item.Children) { var children = child.PendingContinuations().ToArray(); if (children.Any()) { return(children); } if (!child.CanContinue()) { break; } } } var anyFailureHandlers = Enumerable.Empty <Continuation>(); var allFailureHandlers = Enumerable.Empty <Continuation>(); var failedChildren = item.Children.Where(c => !c.CanContinue()).ToArray(); if (failedChildren.Any()) { anyFailureHandlers = item.OnAnyFailed.PendingContinuations(); } if (failedChildren.Length == item.Children.Count()) { allFailureHandlers = item.OnAllFailed.PendingContinuations(); } var resultArray = anyFailureHandlers.Concat(allFailureHandlers).ToArray(); return(resultArray.Any() ? resultArray : item.CanContinue() ? item.Next.PendingContinuations() : Enumerable.Empty <Continuation>()); }
public void ShouldNotReturnNextInSequenceIfCurrentIsFailed() { var continuation = new Continuation { Type = ContinuationType.Sequence, Children = new[] { new Continuation {Status = JobStatus.Completed}, new Continuation {Status = JobStatus.Poisoned}, new Continuation {Status = JobStatus.Created} } }; var pending = continuation.PendingContinuations(); Assert.Empty(pending); }
public void ReturnsOnFailedContinuationIfSingleContinuationIsFailed() { var continuation = new Continuation {Status = JobStatus.Poisoned, OnAllFailed = new Continuation()}; var pending = continuation.PendingContinuations(); Assert.Equal(continuation.OnAllFailed, pending.Single()); }
public void ReturnsNextIfSingleContinuationIsCompleted() { var continuation = new Continuation {Status = JobStatus.Completed, Next = new Continuation()}; var pending = continuation.PendingContinuations(); Assert.Equal(continuation.Next, pending.Single()); }