コード例 #1
0
        /// <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);
        }
コード例 #2
0
        /// <summary>
        /// Handles the next <see cref="IWorkflowActivityProcessor"/>'s <see cref="V1WorkflowActivityCompletedIntegrationEvent"/>
        /// </summary>
        /// <param name="processor">The <see cref="IWorkflowActivityProcessor"/> that returned the <see cref="V1WorkflowActivityCompletedIntegrationEvent"/></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 OnTriggerResultAsync(IWorkflowActivityProcessor processor, V1WorkflowActivityCompletedIntegrationEvent e, CancellationToken cancellationToken)
        {
            using (await this.Lock.LockAsync(cancellationToken))
            {
                if (this.Activity.Status == V1WorkflowActivityStatus.Completed)
                {
                    return;
                }
                var completedActivities = (await this.Context.Workflow.GetActivitiesAsync(this.Activity, cancellationToken))
                                          .Where(p => p.Type == V1WorkflowActivityType.EventTrigger && p.Status == V1WorkflowActivityStatus.Completed)
                                          .ToList();
                if (this.State.Exclusive ||
                    completedActivities.Count == this.State.Triggers.Count)
                {
                    var output = new object();
                    foreach (var activity in completedActivities
                             .Where(p => p.Output != null))
                    {
                        output = output.Merge(activity.Output.ToObject());
                    }
                    await this.OnNextAsync(new V1WorkflowActivityCompletedIntegrationEvent(this.Activity.Id, output), cancellationToken);

                    await this.OnCompletedAsync(cancellationToken);
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Handles the next <see cref="V1WorkflowActivityCompletedIntegrationEvent"/>
        /// </summary>
        /// <param name="processor">The <see cref="IWorkflowActivityProcessor"/> that has produced an <see cref="V1WorkflowActivityCompletedIntegrationEvent"/></param>
        /// <param name="e">The <see cref="V1WorkflowActivityCompletedIntegrationEvent"/> to process</param>
        /// <returns>A new awaitable <see cref="Task"/></returns>
        protected virtual async Task OnTransitionCompletedAsync(ITransitionProcessor processor, V1WorkflowActivityCompletedIntegrationEvent e)
        {
            if (!this.Context.Workflow.Definition.TryGetState(processor.Transition.NextState, out StateDefinition nextState))
            {
                throw new NullReferenceException($"Failed to find a state with name '{processor.Transition.NextState}' in workflow '{this.Context.Workflow.Definition.Id} {this.Context.Workflow.Definition.Version}'");
            }
            await this.Context.Workflow.TransitionToAsync(nextState, this.CancellationToken);

            var metadata = new Dictionary <string, string>()
            {
                { V1WorkflowActivityMetadata.State, nextState.Name }
            };
            var activity = await this.Context.Workflow.CreateActivityAsync(V1WorkflowActivityType.State, e.Output, metadata, null, this.CancellationToken);

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            this.CreateActivityProcessor(activity);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
        }
コード例 #4
0
 /// <summary>
 /// Handles the completion of the specified <see cref="IEndProcessor"/>
 /// </summary>
 /// <param name="processor">The <see cref="IEndProcessor"/> that has produced the <see cref="V1WorkflowActivityCompletedIntegrationEvent"/></param>
 /// <param name="e">The <see cref="V1WorkflowActivityCompletedIntegrationEvent"/> to handle</param>
 /// <returns>A new awaitable <see cref="Task"/></returns>
 protected virtual async Task OnEndCompletedAsync(IEndProcessor processor, V1WorkflowActivityCompletedIntegrationEvent e)
 {
     await this.Context.Workflow.SetOutputAsync(e.Output, this.CancellationToken);
 }
コード例 #5
0
        /// <summary>
        /// Handles the completion of a state
        /// </summary>
        /// <param name="processor">The <see cref="IStateProcessor"/> that has finished processing the state</param>
        /// <param name="e">The <see cref="V1WorkflowActivityCompletedIntegrationEvent"/> that describes the processed state's output</param>
        /// <returns>A new awaitable <see cref="Task"/></returns>
        protected virtual async Task OnStateCompletedAsync(IStateProcessor processor, V1WorkflowActivityCompletedIntegrationEvent e)
        {
            var metadata = new Dictionary <string, string>()
            {
                { V1WorkflowActivityMetadata.State, processor.State.Name }
            };

            if (processor.State is SwitchStateDefinition switchState)
            {
                if (!processor.Activity.Metadata.TryGetValue(V1WorkflowActivityMetadata.Case, out var caseName))
                {
                    throw new InvalidOperationException($"Failed to retrieve the required switch state metadata with key '{V1WorkflowActivityMetadata.Case}'");
                }
                if (!switchState.TryGetCase(caseName, out SwitchCaseDefinition switchCase))
                {
                    throw new InvalidOperationException($"Failed to find a case with name '{caseName}' in the state '{processor.State.Name}' of workflow '{this.Context.Workflow.Definition.Id}'");
                }
                metadata.Add(V1WorkflowActivityMetadata.Case, caseName);
                var activity = null as V1WorkflowActivity;
                switch (switchCase.Type)
                {
                case ConditionType.End:
                    activity = await this.Context.Workflow.CreateActivityAsync(V1WorkflowActivityType.End, e.Output, metadata, null, this.CancellationToken);

                    break;

                case ConditionType.Transition:
                    activity = await this.Context.Workflow.CreateActivityAsync(V1WorkflowActivityType.Transition, e.Output, metadata, null, this.CancellationToken);

                    break;

                default:
                    throw new NotSupportedException($"The specified condition type '{switchCase.Type}' is not supported in this context");
                }
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
                this.CreateActivityProcessor(activity);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            }
            else
            {
                if (processor.State.Transition != null ||
                    !string.IsNullOrWhiteSpace(processor.State.TransitionToStateName))
                {
                    await this.Context.Workflow.CreateActivityAsync(V1WorkflowActivityType.Transition, e.Output !.ToObject() !, metadata, null, this.CancellationToken);
                }
                else if (processor.State.End != null ||
                         processor.State.IsEnd)
                {
                    await this.Context.Workflow.CreateActivityAsync(V1WorkflowActivityType.End, e.Output !.ToObject() !, metadata, null, this.CancellationToken);
                }
                else
                {
                    throw new InvalidOperationException($"The state '{processor.State.Name}' must declare a transition definition or an end definition for it is part of the main execution logic of the workflow '{this.Context.Workflow.Definition.Id}'");
                }
                foreach (var activity in await this.Context.Workflow.GetOperativeActivitiesAsync(this.CancellationToken))
                {
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
                    this.CreateActivityProcessor(activity);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
                }
            }
        }