示例#1
0
        /// <inheritdoc />
        public Task <object> Execute(WorkflowInstance workflow, WorkableLogger tasklogger, IDictionary <string, object> arguments, bool profiling, CancellationToken token)
        {
            StateVariableProvider variables = new StateVariableProvider(ProcessImports(tasklogger, workflow.StartNode.Parameters?.Imports));

            variables.Add(arguments);
            return(Execute(new WorkflowInstanceState(new WorkflowIdentifier(workflow.Id, workflow.Revision, workflow.Name), tasklogger, variables, GetWorkflowInstance, this, workflow.Language, profiling), token, workflow.StartNode));
        }
        async Task <WorkableTask> Execute(IScript scriptinstance, WorkableTask scripttask, IDictionary <string, object> variables, TimeSpan?wait)
        {
            WorkableLogger scriptlogger = new WorkableLogger(logger, scripttask);

            scripttask.Task = Execute(scriptinstance, scriptlogger, variables, scripttask.Token.Token).ContinueWith(t => {
                if (t.IsCanceled)
                {
                    scriptlogger.Warning("Script execution was aborted");
                    scripttask.Status = TaskStatus.Canceled;
                }
                else if (t.IsFaulted)
                {
                    scriptlogger.Error("Script failed to execute", t.Exception?.InnerException ?? t.Exception);
                    scripttask.Status = TaskStatus.Failure;
                }
                else
                {
                    scripttask.Result = t.Result;
                    scriptlogger.Info($"Script executed successfully with result '{scripttask.Result}'");
                    scripttask.Status = TaskStatus.Success;
                }

                scripttask.Finished = DateTime.Now;
                scriptinstances.FinishTask(scripttask.Id).GetAwaiter().GetResult();
            });

            if (wait.HasValue && !scripttask.Task.IsCompleted)
            {
                await Task.WhenAny(scripttask.Task, Task.Delay(wait.Value));
            }

            return(scripttask);
        }
示例#3
0
        /// <inheritdoc />
        public async Task <WorkableTask> Execute(WorkflowInstance workflow, IDictionary <string, object> arguments, bool profiling, TimeSpan?wait = null)
        {
            WorkableTask   task       = taskservice.CreateTask(WorkableType.Workflow, workflow.Id, workflow.Revision, workflow.Name, arguments);
            WorkableLogger tasklogger = new WorkableLogger(logger, task);

            try {
                task.Task = Task.Run(() => {
                    StateVariableProvider variables = new StateVariableProvider(ProcessImports(tasklogger, workflow.StartNode.Parameters?.Imports));
                    variables.Add(arguments);

                    WorkflowInstanceState workflowstate = new WorkflowInstanceState(new WorkflowIdentifier(workflow.Id, workflow.Revision, workflow.Name), tasklogger, variables, GetWorkflowInstance, this, workflow.Language, profiling);
                    return(Execute(workflowstate, task.Token.Token, workflow.StartNode));
                }).ContinueWith(t => HandleTaskResult(t, task, tasklogger));
            }
            catch (Exception e) {
                tasklogger.Error("Failed to execute workflow", e);
                task.Finished = DateTime.Now;
                task.Status   = TaskStatus.Failure;
                await taskservice.FinishTask(task.Id);
            }

            if (wait.HasValue && !task.Task.IsCompleted)
            {
                await Task.WhenAny(task.Task, Task.Delay(wait.Value));
            }

            return(task);
        }
示例#4
0
        void HandleTaskResult(Task <object> t, WorkableTask task, WorkableLogger tasklogger)
        {
            tasklogger.LogPerformance();
            if (t.IsCanceled)
            {
                tasklogger.Warning("Workflow execution was aborted");
                task.Status = TaskStatus.Canceled;
            }
            else if (t.IsFaulted)
            {
                tasklogger.Error("Workflow failed to execute", t.Exception?.InnerException ?? t.Exception);
                task.Status = TaskStatus.Failure;
            }
            else
            {
                if (t.Result is SuspendState state)
                {
                    tasklogger.Info($"Workflow was suspended at '{state}'");
                    task.SuspensionState = state;
                    task.Status          = TaskStatus.Suspended;

                    // don't finish task when it gets suspended
                    // else it would get serialized and suspension state is lost
                    // TODO: this could get refactored to allow for state serialization
                    return;
                }

                task.Result = t.Result;
                tasklogger.Info($"Workflow executed successfully with result '{task.Result}'");
                task.Status = TaskStatus.Success;
            }

            task.Finished = DateTime.Now;
            taskservice.FinishTask(task.Id).GetAwaiter().GetResult();
        }
示例#5
0
        Dictionary <string, object> ProcessImports(WorkableLogger tasklogger, ImportDeclaration[] imports)
        {
            Dictionary <string, object> variables = new Dictionary <string, object> {
                ["log"] = tasklogger
            };

            if (imports != null)
            {
                foreach (ImportDeclaration import in imports)
                {
                    variables[import.Variable] = importprovider.Import(new object[] { import.Type, import.Name });
                }
            }

            return(variables);
        }
示例#6
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);
        }
示例#7
0
        /// <inheritdoc />
        public async Task <WorkableTask> Continue(Guid taskid, IDictionary <string, object> variables = null, TimeSpan?wait = null)
        {
            WorkableTask task = await taskservice.GetTask(taskid);

            if (task.Status != TaskStatus.Suspended)
            {
                throw new ArgumentException($"Task '{taskid}' is not suspended.");
            }
            if (task.SuspensionState == null)
            {
                throw new InvalidOperationException($"Task '{taskid}' has no suspension state linked to it.");
            }

            WorkableLogger tasklogger = new WorkableLogger(logger, task);

            tasklogger.Info("Resuming execution of workflow", string.Join("\n", variables?.Select(p => $"{p.Key}={p.Value}") ?? new string[0]));

            try {
                task.Status = TaskStatus.Running;
                task.Task   = Task.Run(async() => {
                    WorkflowInstanceState workflowstate = new WorkflowInstanceState(task.SuspensionState.Workflow, tasklogger, task.SuspensionState.Variables, GetWorkflowInstance, this, task.SuspensionState.Language, task.SuspensionState.Profiling);
                    return(await ContinueState(task.SuspensionState, workflowstate, tasklogger, variables, task.Token.Token));
                }).ContinueWith(t => HandleTaskResult(t, task, tasklogger));
            }
            catch (Exception e) {
                tasklogger.Error("Failed to execute workflow", e);
                task.Finished = DateTime.Now;
                task.Status   = TaskStatus.Failure;
                await taskservice.FinishTask(task.Id);
            }

            if (wait.HasValue && !task.Task.IsCompleted)
            {
                await Task.WhenAny(task.Task, Task.Delay(wait.Value));
            }

            return(task);
        }
        /// <inheritdoc />
        public Task <object> Execute(IScript script, WorkableLogger scriptlogger, IDictionary <string, object> variables, CancellationToken token)
        {
            IVariableProvider scopevariables = new StateVariableProvider(variables, new Variable("log", scriptlogger));

            return(script.ExecuteAsync(scopevariables, token));
        }
示例#9
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));
        }