Example #1
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();
        }
Example #2
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);
        }
        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);
        }
 WorkableTask GenerateListVersion(WorkableTask task)
 {
     return(new WorkableTask {
         Id = task.Id,
         WorkableId = task.WorkableId,
         WorkableRevision = task.WorkableRevision,
         WorkableName = task.WorkableName,
         Started = task.Started,
         Finished = task.Finished,
         Runtime = (task.Finished ?? DateTime.Now) - task.Started,
         Status = task.Status,
         Result = task.Result
     });
 }
        /// <inheritdoc />
        public Task StoreTask(WorkableTask task)
        {
            task.Finished ??= DateTime.Now;

            return(insert.ExecuteAsync(task.Id,
                                       task.Type,
                                       task.WorkableId,
                                       task.WorkableRevision,
                                       task.WorkableName,
                                       task.Parameters.Serialize(),
                                       task.Started,
                                       task.Finished,
                                       task.Status,
                                       task.Result.Serialize(),
                                       task.Log.Serialize()));
        }
        /// <inheritdoc />
        public async Task <WorkableTask> Execute(NamedCode code, IDictionary <string, object> variables = null, TimeSpan?wait = null)
        {
            IDictionary <string, object> runtimevariables = await variables.TranslateVariables(scriptcompiler, ScriptLanguage.NCScript);

            WorkableTask scripttask = scriptinstances.CreateTask(WorkableType.Script, 0, 0, code.Name, runtimevariables);

            try {
                return(await Execute(await scriptcompiler.CompileCodeAsync(code.Code, code.Language), scripttask, runtimevariables, wait));
            }
            catch (Exception e) {
                scripttask.Log.Add(e.ToString());
                scripttask.Status = TaskStatus.Failure;
                await scriptinstances.FinishTask(scripttask.Id);
            }

            return(scripttask);
        }
Example #7
0
        public async Task ListRunningTask()
        {
            Mock <IScriptImportService> importservice = new Mock <IScriptImportService>();

            importservice.Setup(s => s.Clone(It.IsAny <WorkableLogger>())).Returns(() => importservice.Object);

            IEntityManager           database         = TestSetup.CreateMemoryDatabase();
            CacheService             cache            = new CacheService(new NullLogger <CacheService>());
            IScriptCompiler          compiler         = new ScriptCompiler(new NullLogger <ScriptCompiler>(), new ScriptParser(), cache, null, new Mock <IScriptService>().Object, new Mock <IArchiveService>().Object, importservice.Object, null, null);
            WorkflowCompiler         workflowcompiler = new WorkflowCompiler(new NullLogger <WorkflowCompiler>(), cache, null, compiler);
            ITaskService             taskservice      = new DatabaseTaskService(database);
            WorkflowExecutionService executionservice = new WorkflowExecutionService(new NullLogger <WorkflowExecutionService>(), taskservice, null, null, workflowcompiler);

            WorkableTask task = await executionservice.Execute(await workflowcompiler.BuildWorkflow(new WorkflowStructure {
                Name  = "JS Test",
                Nodes = new[] {
                    new NodeData {
                        Type = NodeType.Start
                    },
                    new NodeData {
                        Type = NodeType.Node,
                    }
                },
                Transitions = new[] {
                    new IndexTransition {
                        OriginIndex = 0,
                        TargetIndex = 1
                    },
                    new IndexTransition {
                        OriginIndex = 1,
                        TargetIndex = 0,
                    }
                }
            }), new Dictionary <string, object>(), false);

            Assert.AreEqual(TaskStatus.Running, task.Status);
            Page <WorkableTask> tasks = await taskservice.ListTasks();

            Assert.AreEqual(1, tasks.Total);
            Assert.AreEqual(1, tasks.Result.Length);

            task.Token.Cancel();
            await Task.WhenAny(task.Task, Task.Delay(1000));

            Assert.AreEqual(TaskStatus.Canceled, task.Status);
        }
Example #8
0
        public async Task <WorkableTask> Execute([FromBody] ExecuteWorkflowParameters parameters)
        {
            logger.LogInformation("Executing {workflow} with parameters '{parameters}'",
                                  parameters.Id?.ToString() ?? parameters.Name,
                                  string.Join(";", parameters.Parameters?.Select(p => $"{p.Key}={p.Value}") ?? new string[0]));

            try {
                if (parameters.Id.HasValue)
                {
                    if (!string.IsNullOrEmpty(parameters.Name))
                    {
                        throw new ArgumentException("Either id or name has to be set, not both");
                    }
                    return(await executionservice.Execute(await compiler.BuildWorkflow(parameters.Id.Value, parameters.Revision), parameters.Parameters, parameters.Profile ?? false, parameters.Wait));
                }

                if (!string.IsNullOrEmpty(parameters.Name))
                {
                    return(await executionservice.Execute(await compiler.BuildWorkflow(parameters.Name, parameters.Revision), parameters.Parameters, parameters.Profile ?? false, parameters.Wait));
                }

                if (parameters.Workflow != null)
                {
                    return(await executionservice.Execute(await compiler.BuildWorkflow(parameters.Workflow), parameters.Parameters, parameters.Profile ?? false, parameters.Wait));
                }
            }
            catch (Exception e) {
                WorkableTask failtask = new WorkableTask {
                    Id       = Guid.NewGuid(),
                    Status   = TaskStatus.Failure,
                    Started  = DateTime.Now,
                    Finished = DateTime.Now,
                    Log      = new List <string>(new[] {
                        e.ToString()
                    }),
                    Parameters = parameters.Parameters,
                    Type       = WorkableType.Workflow,
                };
                await taskservice.StoreTask(failtask);

                return(failtask);
            }

            throw new ArgumentException("Workflow id or name is required");
        }
        /// <inheritdoc />
        public WorkableTask CreateTask(WorkableType type, long workableid, int workablerevision, string workablename, IDictionary <string, object> variables)
        {
            WorkableTask task = new WorkableTask {
                Id               = Guid.NewGuid(),
                Type             = type,
                WorkableId       = workableid,
                WorkableRevision = workablerevision,
                WorkableName     = workablename,
                Log              = new List <string>(),
                Started          = DateTime.Now,
                Parameters       = variables,
                Status           = TaskStatus.Running,
                Token            = new CancellationTokenSource()
            };

            runningtasks[task.Id] = task;
            return(task);
        }
        /// <inheritdoc />
        public async Task <WorkableTask> Execute(long id, int?revision = null, IDictionary <string, object> variables = null, TimeSpan?wait = null)
        {
            CompiledScript script = await scriptcompiler.CompileScriptAsync(id, revision);

            IDictionary <string, object> runtimevariables = await variables.TranslateVariables(scriptcompiler, ScriptLanguage.NCScript);

            WorkableTask scripttask = scriptinstances.CreateTask(WorkableType.Script, script.Id, script.Revision, script.Name, runtimevariables);

            try {
                return(await Execute(script.Instance, scripttask, runtimevariables, wait));
            }
            catch (Exception e) {
                scripttask.Log.Add(e.ToString());
                scripttask.Status = TaskStatus.Failure;
                await scriptinstances.FinishTask(scripttask.Id);
            }

            return(scripttask);
        }
Example #11
0
        public async Task ExecuteJavascriptExpression()
        {
            Mock <IScriptImportService> importservice = new Mock <IScriptImportService>();

            importservice.Setup(s => s.Clone(It.IsAny <WorkableLogger>())).Returns(() => importservice.Object);

            IEntityManager           database         = TestSetup.CreateMemoryDatabase();
            CacheService             cache            = new CacheService(new NullLogger <CacheService>());
            IScriptCompiler          compiler         = new ScriptCompiler(new NullLogger <ScriptCompiler>(), new ScriptParser(), cache, null, new Mock <IScriptService>().Object, new Mock <IArchiveService>().Object, importservice.Object, null, null);
            WorkflowCompiler         workflowcompiler = new WorkflowCompiler(new NullLogger <WorkflowCompiler>(), cache, null, compiler);
            WorkflowExecutionService executionservice = new WorkflowExecutionService(new NullLogger <WorkflowExecutionService>(), new DatabaseTaskService(database), null, null, workflowcompiler);

            WorkableTask task = await executionservice.Execute(await workflowcompiler.BuildWorkflow(new WorkflowStructure {
                Name  = "JS Test",
                Nodes = new[] {
                    new NodeData {
                        Type = NodeType.Start
                    },
                    new NodeData {
                        Type       = NodeType.Expression,
                        Parameters = new Dictionary <string, object> {
                            ["Code"]     = "return a+b",
                            ["Language"] = ScriptLanguage.JavaScript
                        }
                    }
                },
                Transitions = new[] {
                    new IndexTransition {
                        OriginIndex = 0,
                        TargetIndex = 1
                    },
                }
            }), new Dictionary <string, object> {
                ["a"] = 3,
                ["b"] = 4
            }, false);

            await task.Task;

            Assert.AreEqual(TaskStatus.Success, task.Status);
            Assert.AreEqual(7, task.Result);
        }
        public async Task ExecuteWithDictionary()
        {
            Mock <ITaskService> taskservice = new Mock <ITaskService>();

            taskservice.Setup(s => s.CreateTask(WorkableType.Script, 0, 0, "Test", It.IsAny <IDictionary <string, object> >())).Returns(new WorkableTask()
            {
                Token  = new CancellationTokenSource(),
                Log    = new List <string>(),
                Status = TaskStatus.Running
            });

            ScriptExecutionService service = new ScriptExecutionService(new NullLogger <ScriptExecutionService>(), taskservice.Object, new TestCompiler());
            WorkableTask           task    = await service.Execute(new NamedCode {
                Name = "Test",
                Code = "return(param.property)"
            }, new Dictionary <string, object> {
                ["param"] = "{\"property\":3}"
            }, TimeSpan.FromSeconds(10));

            Assert.AreEqual(TaskStatus.Success, task.Status);
            Assert.AreEqual(3, task.Result);
        }
Example #13
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);
        }
Example #14
0
        public async Task ProfileLoopPerformance()
        {
            Mock <IScriptImportService> importservice = new Mock <IScriptImportService>();

            importservice.Setup(s => s.Clone(It.IsAny <WorkableLogger>())).Returns(() => importservice.Object);

            IEntityManager           database         = TestSetup.CreateMemoryDatabase();
            CacheService             cache            = new CacheService(new NullLogger <CacheService>());
            IScriptCompiler          compiler         = new ScriptCompiler(new NullLogger <ScriptCompiler>(), new ScriptParser(), cache, null, new Mock <IScriptService>().Object, new Mock <IArchiveService>().Object, importservice.Object, null, null);
            WorkflowCompiler         workflowcompiler = new WorkflowCompiler(new NullLogger <WorkflowCompiler>(), cache, null, compiler);
            WorkflowExecutionService executionservice = new WorkflowExecutionService(new NullLogger <WorkflowExecutionService>(), new DatabaseTaskService(database), null, null, workflowcompiler);

            WorkableTask task = await executionservice.Execute(await workflowcompiler.BuildWorkflow(new WorkflowStructure {
                Name  = "JS Test",
                Nodes = new[] {
                    new NodeData {
                        Type = NodeType.Start
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = "0"
                        },
                        Variable = "result"
                    },
                    new NodeData {
                        Type       = NodeType.Iterator,
                        Parameters = new Dictionary <string, object> {
                            ["Collection"] = "[1,2,3,4,5]",
                            ["Item"]       = "number"
                        },
                    },
                    new NodeData {
                        Type       = NodeType.BinaryOperation,
                        Parameters = new Dictionary <string, object> {
                            ["Lhs"] = "$result",
                            ["Rhs"] = "$number",
                            ["Op"]  = BinaryOperation.Add
                        },
                        Variable = "result"
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = "$result"
                        }
                    }
                },
                Transitions = new[] {
                    new IndexTransition {
                        OriginIndex = 0,
                        TargetIndex = 1
                    },
                    new IndexTransition {
                        OriginIndex = 1,
                        TargetIndex = 2,
                    },
                    new IndexTransition {
                        OriginIndex = 2,
                        TargetIndex = 3,
                        Type        = TransitionType.Loop,
                        Log         = "$\"Adding number {$number}\""
                    },
                    new IndexTransition {
                        OriginIndex = 3,
                        TargetIndex = 2
                    },
                    new IndexTransition {
                        OriginIndex = 2,
                        TargetIndex = 4
                    },
                }
            }), new Dictionary <string, object>(), true);

            await task.Task;

            Assert.AreEqual(TaskStatus.Success, task.Status);
            Assert.That(task.Log.Any(l => l.Contains("calls")));
            Assert.AreEqual(15, task.Result);
        }
Example #15
0
        public async Task ExecuteSubWorkflowWithParametersInLoop()
        {
            Mock <IScriptImportService> importservice = new Mock <IScriptImportService>();

            importservice.Setup(s => s.Clone(It.IsAny <WorkableLogger>())).Returns(() => importservice.Object);
            Mock <IArchiveService> archiveservice = new Mock <IArchiveService>();

            IEntityManager           database         = TestSetup.CreateMemoryDatabase();
            CacheService             cache            = new CacheService(new NullLogger <CacheService>());
            IScriptCompiler          compiler         = new ScriptCompiler(new NullLogger <ScriptCompiler>(), new ScriptParser(), cache, null, new Mock <IScriptService>().Object, archiveservice.Object, importservice.Object, null, null);
            IWorkflowService         workflowservice  = new DatabaseWorkflowService(database, archiveservice.Object);
            WorkflowCompiler         workflowcompiler = new WorkflowCompiler(new NullLogger <WorkflowCompiler>(), cache, workflowservice, compiler);
            WorkflowExecutionService executionservice = new WorkflowExecutionService(new NullLogger <WorkflowExecutionService>(), new DatabaseTaskService(database), null, workflowservice, workflowcompiler);

            await workflowservice.CreateWorkflow(new WorkflowStructure {
                Name  = "Submarine",
                Nodes = new [] {
                    new NodeData {
                        Type = NodeType.Start
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = "$value"
                        }
                    }
                },
                Transitions = new[] {
                    new IndexTransition {
                        OriginIndex = 0,
                        TargetIndex = 1
                    },
                }
            });

            WorkableTask task = await executionservice.Execute(await workflowcompiler.BuildWorkflow(new WorkflowStructure {
                Name  = "Subcall Test",
                Nodes = new[] {
                    new NodeData {
                        Type = NodeType.Start
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = "0",
                        },
                        Variable = "result"
                    },
                    new NodeData {
                        Type       = NodeType.Iterator,
                        Parameters = new Dictionary <string, object> {
                            ["Item"]       = "value",
                            ["Collection"] = "[1,2,3,4,5]"
                        }
                    },
                    new NodeData {
                        Type       = NodeType.Workflow,
                        Parameters = new Dictionary <string, object> {
                            ["Name"]      = "Submarine",
                            ["Arguments"] = new Dictionary <string, object> {
                                ["value"] = "$value"
                            }
                        },
                        Variable = "subresult"
                    },
                    new NodeData {
                        Type       = NodeType.BinaryOperation,
                        Parameters = new Dictionary <string, object> {
                            ["Lhs"]       = "$result",
                            ["Operation"] = BinaryOperation.Add,
                            ["Rhs"]       = "$subresult"
                        },
                        Variable = "result"
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = "$result",
                        }
                    },
                },
                Transitions = new[] {
                    new IndexTransition {
                        OriginIndex = 0,
                        TargetIndex = 1
                    },
                    new IndexTransition {
                        OriginIndex = 1,
                        TargetIndex = 2
                    },
                    new IndexTransition {
                        OriginIndex = 2,
                        TargetIndex = 3,
                        Type        = TransitionType.Loop
                    },
                    new IndexTransition {
                        OriginIndex = 2,
                        TargetIndex = 5
                    },
                    new IndexTransition {
                        OriginIndex = 3,
                        TargetIndex = 4
                    },
                    new IndexTransition {
                        OriginIndex = 4,
                        TargetIndex = 2
                    },
                }
            }), new Dictionary <string, object>(), false);

            await task.Task;

            Assert.AreEqual(TaskStatus.Success, task.Status);
            Assert.AreEqual(15, task.Result);
        }
Example #16
0
        public async Task SuspendAndContinueWithParameters()
        {
            IEntityManager           database         = TestSetup.CreateMemoryDatabase();
            CacheService             cache            = new CacheService(new NullLogger <CacheService>());
            IScriptCompiler          compiler         = new ScriptCompiler(new NullLogger <ScriptCompiler>(), new ScriptParser(), cache, null, new Mock <IScriptService>().Object, new Mock <IArchiveService>().Object, null, null, null);
            WorkflowCompiler         workflowcompiler = new WorkflowCompiler(new NullLogger <WorkflowCompiler>(), cache, null, compiler);
            WorkflowExecutionService executionservice = new WorkflowExecutionService(new NullLogger <WorkflowExecutionService>(), new DatabaseTaskService(database), null, null, workflowcompiler);

            WorkableTask task = await executionservice.Execute(await workflowcompiler.BuildWorkflow(new WorkflowStructure {
                Name  = "Test",
                Nodes = new[] {
                    new NodeData {
                        Type = NodeType.Start
                    },
                    new NodeData {
                        Type       = NodeType.Suspend,
                        Parameters = new Dictionary <string, object> {
                            ["Variable"] = "x"
                        }
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = 10
                        }
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = 5
                        }
                    }
                },
                Transitions = new[] {
                    new IndexTransition {
                        OriginIndex = 0,
                        TargetIndex = 1,
                    },
                    new IndexTransition {
                        OriginIndex = 1,
                        TargetIndex = 2,
                        Condition   = "$x>=3"
                    },
                    new IndexTransition {
                        OriginIndex = 1,
                        TargetIndex = 3,
                    }
                }
            }), new Dictionary <string, object>(), false);

            await task.Task;

            Assert.AreEqual(TaskStatus.Suspended, task.Status);

            task = await executionservice.Continue(task.Id, new Dictionary <string, object> {
                ["x"] = 5
            });

            await task.Task;

            Assert.AreEqual(TaskStatus.Success, task.Status);
            Assert.AreEqual(10, task.Result);
        }
Example #17
0
        public async Task ProfileSubWorkflow()
        {
            Mock <IScriptImportService> importservice = new Mock <IScriptImportService>();

            importservice.Setup(s => s.Clone(It.IsAny <WorkableLogger>())).Returns(() => importservice.Object);
            Mock <IArchiveService> archiveservice = new Mock <IArchiveService>();

            IEntityManager           database         = TestSetup.CreateMemoryDatabase();
            CacheService             cache            = new CacheService(new NullLogger <CacheService>());
            IScriptCompiler          compiler         = new ScriptCompiler(new NullLogger <ScriptCompiler>(), new ScriptParser(), cache, null, new Mock <IScriptService>().Object, archiveservice.Object, importservice.Object, null, null);
            IWorkflowService         workflowservice  = new DatabaseWorkflowService(database, archiveservice.Object);
            WorkflowCompiler         workflowcompiler = new WorkflowCompiler(new NullLogger <WorkflowCompiler>(), cache, workflowservice, compiler);
            WorkflowExecutionService executionservice = new WorkflowExecutionService(new NullLogger <WorkflowExecutionService>(), new DatabaseTaskService(database), null, workflowservice, workflowcompiler);

            await workflowservice.CreateWorkflow(new WorkflowStructure {
                Name  = "Submarine",
                Nodes = new [] {
                    new NodeData {
                        Type = NodeType.Start
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Name       = "Subvalue",
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = "$job.id"
                        }
                    }
                },
                Transitions = new[] {
                    new IndexTransition {
                        OriginIndex = 0,
                        TargetIndex = 1
                    },
                }
            });

            WorkableTask task = await executionservice.Execute(await workflowcompiler.BuildWorkflow(new WorkflowStructure {
                Name  = "Subcall Test",
                Nodes = new[] {
                    new NodeData {
                        Type = NodeType.Start
                    },
                    new NodeData {
                        Type       = NodeType.Workflow,
                        Name       = "Call Submarine",
                        Parameters = new Dictionary <string, object> {
                            ["Name"]      = "Submarine",
                            ["Arguments"] = new Dictionary <string, object> {
                                ["job"] = new Dictionary <string, object> {
                                    ["id"] = 1.0
                                }
                            }
                        }
                    }
                },
                Transitions = new[] {
                    new IndexTransition {
                        OriginIndex = 0,
                        TargetIndex = 1
                    },
                }
            }), new Dictionary <string, object>(), true);

            await task.Task;

            Assert.AreEqual(TaskStatus.Success, task.Status);
            Assert.That(task.Log.Any(l => l.Contains("calls")));
            Assert.AreEqual(1.0, task.Result);
        }
 /// <summary>
 /// creates a new <see cref="WorkableLogger"/>
 /// </summary>
 /// <param name="logger">logger to send logs to</param>
 /// <param name="instance">script instance to add logs to</param>
 public WorkableLogger(ILogger logger, WorkableTask instance)
 {
     this.logger   = logger;
     this.instance = instance;
 }
        public async Task SumConditionalLoop()
        {
            IEntityManager           database         = TestSetup.CreateMemoryDatabase();
            CacheService             cache            = new CacheService(new NullLogger <CacheService>());
            IScriptCompiler          compiler         = new ScriptCompiler(new NullLogger <ScriptCompiler>(), new ScriptParser(), cache, null, new Mock <IScriptService>().Object, new Mock <IArchiveService>().Object, null, new Mock <IPythonService>().Object, null);
            WorkflowCompiler         workflowcompiler = new WorkflowCompiler(new NullLogger <WorkflowCompiler>(), cache, null, compiler);
            WorkflowExecutionService executionservice = new WorkflowExecutionService(new NullLogger <WorkflowExecutionService>(), new DatabaseTaskService(database), null, null, workflowcompiler);

            WorkableTask task = await executionservice.Execute(await workflowcompiler.BuildWorkflow(new WorkflowStructure {
                Name  = "Test",
                Nodes = new[] {
                    new NodeData {
                        Type = NodeType.Start
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = 0
                        },
                        Variable = "result"
                    },
                    new NodeData {
                        Type       = NodeType.Iterator,
                        Parameters = new Dictionary <string, object> {
                            ["Collection"] = "[1,5,2,2,8,7,4]"
                        }
                    },
                    new NodeData {
                        Type       = NodeType.BinaryOperation,
                        Parameters = new Dictionary <string, object> {
                            ["lhs"]       = "$result",
                            ["rhs"]       = "$item",
                            ["operation"] = "Add"
                        },
                        Variable = "result"
                    },
                    new NodeData {
                        Type       = NodeType.Value,
                        Parameters = new Dictionary <string, object> {
                            ["Value"] = "$result"
                        }
                    }
                },
                Transitions = new[] {
                    new IndexTransition {
                        OriginIndex = 0,
                        TargetIndex = 1,
                    },
                    new IndexTransition {
                        OriginIndex = 1,
                        TargetIndex = 2,
                    },
                    new IndexTransition {
                        OriginIndex = 2,
                        TargetIndex = 3,
                        Type        = TransitionType.Loop,
                        Condition   = "$item&1==0"
                    },
                    new IndexTransition {
                        OriginIndex = 2,
                        TargetIndex = 4,
                    },
                    new IndexTransition {
                        OriginIndex = 3,
                        TargetIndex = 2
                    }
                }
            }), new Dictionary <string, object>(), false);

            await task.Task;

            Assert.AreEqual(Dto.TaskStatus.Success, task.Status);
            Assert.AreEqual(16, task.Result);
        }