Ejemplo n.º 1
0
        async Task <object> ContinueState(SuspendState state, WorkflowInstanceState workflowstate, WorkableLogger tasklogger, IDictionary <string, object> variables, CancellationToken token)
        {
            object lastresult = null;

            if (state.Subflow != null)
            {
                WorkflowIdentifier workflow = workflowstate.Workflow;
                workflowstate.Workflow = state.Subflow.Workflow;
                lastresult             = await ContinueState(state.Subflow, workflowstate, tasklogger, variables, token);

                workflowstate.Workflow = workflow;
            }
            else
            {
                if (variables != null)
                {
                    foreach (KeyValuePair <string, object> entry in variables)
                    {
                        state.Variables[entry.Key] = entry.Value.DetermineValue(state.Variables);
                    }
                }
            }

            InstanceTransition transition = await EvaluateTransitions(state.Node, tasklogger, state.Variables, state.Node.Transitions, token);

            if (transition == null)
            {
                tasklogger.Warning("Suspend node has no transition defined for current state. Workflow ends by default.");
                return(lastresult);
            }

            return(await Execute(workflowstate, token, transition.Target, lastresult));
        }
Ejemplo n.º 2
0
        async Task <InstanceTransition> EvaluateTransitions(IInstanceNode current, WorkableLogger tasklogger, IVariableProvider variableprovider, List <InstanceTransition> transitions, CancellationToken token)
        {
            if (transitions == null)
            {
                return(null);
            }

            InstanceTransition transition = null;

            foreach (InstanceTransition conditionaltransition in transitions.Where(c => c.Condition != null))
            {
                if (await conditionaltransition.Condition.ExecuteAsync <bool>(variableprovider, token))
                {
                    transition = conditionaltransition;
                    break;
                }
            }

            if (transition == null)
            {
                InstanceTransition[] defaulttransitions = transitions.Where(t => t.Condition == null).ToArray();
                if (defaulttransitions.Length > 1)
                {
                    throw new InvalidOperationException($"More than one default transition defined for '{current.NodeName}'.");
                }
                transition = defaulttransitions.FirstOrDefault();
            }

            if (transition?.Log != null)
            {
                try {
                    tasklogger.Info(await transition.Log.ExecuteAsync <string>(variableprovider, token));
                }
                catch (Exception e) {
                    tasklogger.Error($"Error executing transition log of '{current.NodeName}'->'{transition.Target?.NodeName}'", e);
                    throw;
                }
            }
            return(transition);
        }
Ejemplo n.º 3
0
        async Task <object> Execute(WorkflowInstanceState state, CancellationToken token, IInstanceNode current, object lastresult = null)
        {
            while (current != null)
            {
                try {
                    if (state.Profiling)
                    {
                        Stopwatch stopwatch = Stopwatch.StartNew();
                        lastresult = await current.Execute(state, token);

                        state.Logger.Performance(state.Workflow, current.NodeId, current.NodeName, stopwatch.Elapsed);
                    }
                    else
                    {
                        lastresult = await current.Execute(state, token);
                    }

                    if (token.IsCancellationRequested)
                    {
                        throw new TaskCanceledException();
                    }

                    // used for workflow suspension
                    if (lastresult is SuspendState)
                    {
                        return(lastresult);
                    }
                }
                catch (Exception e) {
                    state.Logger.Warning($"Error while executing node '{current.NodeName}'", e.Message);

                    InstanceTransition next = await EvaluateTransitions(current, state.Logger, new VariableProvider(state.Variables, new Variable("error", e)), current.ErrorTransitions, token);

                    if (next == null)
                    {
                        throw;
                    }

                    current = next.Target;
                    continue;
                }

                try {
                    InstanceTransition transition;
                    if (lastresult is LoopCommand)
                    {
                        if (current.LoopTransitions.Count == 0)
                        {
                            throw new InvalidOperationException("Iterator node without any loop transitions detected.");
                        }

                        transition = await EvaluateTransitions(current, state.Logger, state.Variables, current.LoopTransitions, token);

                        current = transition?.Target ?? current;
                    }
                    else
                    {
                        transition = await EvaluateTransitions(current, state.Logger, state.Variables, current.Transitions, token);

                        current = transition?.Target;
                    }
                }
                catch (Exception e) {
                    state.Logger.Warning($"Error while evaluating transitions of node '{current?.NodeName}'", e.Message);

                    InstanceTransition next = await EvaluateTransitions(current, state.Logger, new VariableProvider(state.Variables, new Variable("error", e)), current?.ErrorTransitions, token);

                    if (next == null)
                    {
                        throw;
                    }

                    current = next.Target;
                }
            }

            return(lastresult);
        }