/// <summary> /// Handles the completion of the specified <see cref="BranchProcessor"/> /// </summary> /// <param name="processor">The <see cref="BranchProcessor"/> to handle the completion of</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/></param> /// <returns>A new awaitable <see cref="Task"/></returns> protected virtual async Task OnBranchCompletedAsync(BranchProcessor processor, CancellationToken cancellationToken) { this.Processors.TryRemove(processor); processor.Dispose(); if (this.BranchesCompleted) { return; } using (await this.Lock.LockAsync(cancellationToken)) { var childActivities = (await this.Context.Workflow.GetActivitiesAsync(this.Activity, cancellationToken)) .Where(a => a.Type == V1WorkflowActivityType.Branch) .ToList(); var completed = false; switch (this.State.CompletionType) { case ParallelCompletionType.AllOf: completed = childActivities.All(p => p.Status >= V1WorkflowActivityStatus.Faulted); break; case ParallelCompletionType.AtLeastN: if (childActivities.Where(p => p.Status >= V1WorkflowActivityStatus.Faulted).Count() >= this.State.N) { completed = true; } break; default: throw new NotSupportedException($"The specified {nameof(ParallelCompletionType)} '{this.State.CompletionType}' is not supported"); } if (!completed) { return; } if (completed && !this.BranchesCompleted) { this.BranchesCompleted = true; } else { return; } } await this.OnCompletedAsync(cancellationToken); }
/// <summary> /// Handles the <see cref="BranchProcessor"/>'s execution /// </summary> /// <param name="processor">The <see cref="BranchProcessor"/> that has produced the <see cref="V1WorkflowActivityCompletedIntegrationEvent"/> to process</param> /// <param name="e">The <see cref="V1WorkflowActivityCompletedIntegrationEvent"/> to handle</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/></param> /// <returns>A new awaitable <see cref="Task"/></returns> protected virtual async Task OnBranchExecutedAsync(BranchProcessor processor, V1WorkflowActivityCompletedIntegrationEvent e, CancellationToken cancellationToken) { if (this.BranchesExecuted) { return; } var output = null as object; var childActivities = (await this.Context.Workflow.GetActivitiesAsync(this.Activity, cancellationToken)) .Where(a => a.Type == V1WorkflowActivityType.Branch) .ToList(); var executed = false; switch (this.State.CompletionType) { case ParallelCompletionType.AtLeastN: var executedActivities = childActivities .Where(p => p.Status >= V1WorkflowActivityStatus.Faulted) .ToList(); if (executedActivities.Count() >= this.State.N) { executed = true; output = new(); foreach (var executedActivity in executedActivities) { output = output.Merge(executedActivity.Output !.ToObject() !); } } break; case ParallelCompletionType.AllOf: if (childActivities.All(p => p.Status >= V1WorkflowActivityStatus.Faulted)) { executed = true; output = new(); foreach (var executedActivity in childActivities) { output = output.Merge(executedActivity.Output !.ToObject() !); } } break; default: throw new NotSupportedException($"The specified {nameof(ParallelCompletionType)} '{this.State.CompletionType}' is not supported"); } if (!executed) { return; } using (await this.Lock.LockAsync(cancellationToken)) { if (this.BranchesExecuted) { return; } else { this.BranchesExecuted = true; } } await this.OnNextAsync(new V1WorkflowActivityCompletedIntegrationEvent(this.Activity.Id, output), cancellationToken); }