Esempio n. 1
0
        private WorkflowStepCollection ConvertSteps(ICollection <StepSourceV1> source, Type dataType)
        {
            var result         = new WorkflowStepCollection();
            int i              = 0;
            var stack          = new Stack <StepSourceV1>(source.Reverse <StepSourceV1>());
            var parents        = new List <StepSourceV1>();
            var compensatables = new List <StepSourceV1>();

            while (stack.Count > 0)
            {
                var nextStep = stack.Pop();

                var stepType      = FindType(nextStep.StepType);
                var containerType = typeof(WorkflowStep <>).MakeGenericType(stepType);
                var targetStep    = (containerType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep);

                if (nextStep.Saga)
                {
                    containerType = typeof(SagaContainer <>).MakeGenericType(stepType);
                    targetStep    = (containerType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep);
                }

                if (!string.IsNullOrEmpty(nextStep.CancelCondition))
                {
                    var cancelExprType = typeof(Expression <>).MakeGenericType(typeof(Func <,>).MakeGenericType(dataType, typeof(bool)));
                    var dataParameter  = Expression.Parameter(dataType, "data");
                    var cancelExpr     = DynamicExpressionParser.ParseLambda(new[] { dataParameter }, typeof(bool), nextStep.CancelCondition);
                    targetStep.CancelCondition = cancelExpr;
                }

                targetStep.Id            = i;
                targetStep.Name          = nextStep.Name;
                targetStep.ErrorBehavior = nextStep.ErrorBehavior;
                targetStep.RetryInterval = nextStep.RetryInterval;
                targetStep.ExternalId    = $"{nextStep.Id}";

                AttachInputs(nextStep, dataType, stepType, targetStep);
                AttachOutputs(nextStep, dataType, stepType, targetStep);

                if (nextStep.Do != null)
                {
                    foreach (var branch in nextStep.Do)
                    {
                        foreach (var child in branch.Reverse <StepSourceV1>())
                        {
                            stack.Push(child);
                        }
                    }

                    if (nextStep.Do.Count > 0)
                    {
                        parents.Add(nextStep);
                    }
                }

                if (nextStep.CompensateWith != null)
                {
                    foreach (var compChild in nextStep.CompensateWith.Reverse <StepSourceV1>())
                    {
                        stack.Push(compChild);
                    }

                    if (nextStep.CompensateWith.Count > 0)
                    {
                        compensatables.Add(nextStep);
                    }
                }

                if (!string.IsNullOrEmpty(nextStep.NextStepId))
                {
                    targetStep.Outcomes.Add(new StepOutcome()
                    {
                        ExternalNextStepId = $"{nextStep.NextStepId}"
                    });
                }

                result.Add(targetStep);

                i++;
            }

            foreach (var step in result)
            {
                if (result.Any(x => x.ExternalId == step.ExternalId && x.Id != step.Id))
                {
                    throw new WorkflowDefinitionLoadException($"Duplicate step Id {step.ExternalId}");
                }

                foreach (var outcome in step.Outcomes)
                {
                    if (result.All(x => x.ExternalId != outcome.ExternalNextStepId))
                    {
                        throw new WorkflowDefinitionLoadException($"Cannot find step id {outcome.ExternalNextStepId}");
                    }

                    outcome.NextStep = result.Single(x => x.ExternalId == outcome.ExternalNextStepId).Id;
                }
            }

            foreach (var parent in parents)
            {
                var target = result.Single(x => x.ExternalId == parent.Id);
                foreach (var branch in parent.Do)
                {
                    var childTags = branch.Select(x => x.Id).ToList();
                    target.Children.AddRange(result
                                             .Where(x => childTags.Contains(x.ExternalId))
                                             .OrderBy(x => x.Id)
                                             .Select(x => x.Id)
                                             .Take(1)
                                             .ToList());
                }
            }

            foreach (var item in compensatables)
            {
                var target = result.Single(x => x.ExternalId == item.Id);
                var tag    = item.CompensateWith.Select(x => x.Id).FirstOrDefault();
                if (tag != null)
                {
                    var compStep = result.FirstOrDefault(x => x.ExternalId == tag);
                    if (compStep != null)
                    {
                        target.CompensationStepId = compStep.Id;
                    }
                }
            }

            return(result);
        }
Esempio n. 2
0
        private WorkflowStepCollection ConvertSteps(ICollection <Step> source, Type dataType)
        {
            var result         = new WorkflowStepCollection();
            int i              = 0;
            var stack          = new Stack <Step>(source.Reverse());
            var parents        = new List <Step>();
            var compensatables = new List <Step>();

            while (stack.Count > 0)
            {
                var nextStep = stack.Pop();

                var stepType      = FindType(nextStep.StepType);
                var containerType = typeof(WorkflowStep <>).MakeGenericType(stepType);
                var targetStep    = (containerType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep);
                if (stepType == typeof(CustomStep))
                {
                    targetStep.Inputs.Add(new ActionParameter <CustomStep, object>((pStep, pData) => pStep["__custom_step__"] = nextStep.StepType));
                }

                if (nextStep.Saga)
                {
                    containerType = typeof(SagaContainer <>).MakeGenericType(stepType);
                    targetStep    = (containerType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep);
                }

                if (!string.IsNullOrEmpty(nextStep.CancelCondition))
                {
                    Func <ExpandoObject, bool> cancelFunc = (data) => _scriptHost.EvaluateExpression <bool>(nextStep.CancelCondition, new Dictionary <string, object>()
                    {
                        ["data"]        = data,
                        ["environment"] = Environment.GetEnvironmentVariables()
                    });

                    Expression <Func <ExpandoObject, bool> > cancelExpr = (data) => cancelFunc(data);
                    targetStep.CancelCondition = cancelExpr;
                }

                targetStep.Id            = i;
                targetStep.Name          = nextStep.Name;
                targetStep.ErrorBehavior = nextStep.ErrorBehavior;
                targetStep.RetryInterval = nextStep.RetryInterval;
                targetStep.ExternalId    = $"{nextStep.Id}";

                AttachInputs(nextStep, dataType, stepType, targetStep);
                AttachOutputs(nextStep, dataType, stepType, targetStep);

                if (nextStep.Do != null)
                {
                    foreach (var branch in nextStep.Do)
                    {
                        foreach (var child in branch.Reverse <Step>())
                        {
                            stack.Push(child);
                        }
                    }

                    if (nextStep.Do.Count > 0)
                    {
                        parents.Add(nextStep);
                    }
                }

                if (nextStep.CompensateWith != null)
                {
                    foreach (var compChild in nextStep.CompensateWith.Reverse <Step>())
                    {
                        stack.Push(compChild);
                    }

                    if (nextStep.CompensateWith.Count > 0)
                    {
                        compensatables.Add(nextStep);
                    }
                }

                if (!string.IsNullOrEmpty(nextStep.NextStepId))
                {
                    targetStep.Outcomes.Add(new StepOutcome()
                    {
                        ExternalNextStepId = $"{nextStep.NextStepId}"
                    });
                }

                result.Add(targetStep);

                i++;
            }

            foreach (var step in result)
            {
                if (result.Any(x => x.ExternalId == step.ExternalId && x.Id != step.Id))
                {
                    throw new WorkflowDefinitionLoadException($"Duplicate step Id {step.ExternalId}");
                }

                foreach (var outcome in step.Outcomes)
                {
                    if (result.All(x => x.ExternalId != outcome.ExternalNextStepId))
                    {
                        throw new WorkflowDefinitionLoadException($"Cannot find step id {outcome.ExternalNextStepId}");
                    }

                    outcome.NextStep = result.Single(x => x.ExternalId == outcome.ExternalNextStepId).Id;
                }
            }

            foreach (var parent in parents)
            {
                var target = result.Single(x => x.ExternalId == parent.Id);
                foreach (var branch in parent.Do)
                {
                    var childTags = branch.Select(x => x.Id).ToList();
                    target.Children.AddRange(result
                                             .Where(x => childTags.Contains(x.ExternalId))
                                             .OrderBy(x => x.Id)
                                             .Select(x => x.Id)
                                             .Take(1)
                                             .ToList());
                }
            }

            foreach (var item in compensatables)
            {
                var target = result.Single(x => x.ExternalId == item.Id);
                var tag    = item.CompensateWith.Select(x => x.Id).FirstOrDefault();
                if (tag != null)
                {
                    var compStep = result.FirstOrDefault(x => x.ExternalId == tag);
                    if (compStep != null)
                    {
                        target.CompensationStepId = compStep.Id;
                    }
                }
            }

            return(result);
        }