public void HandlesExceptionsFromBadLuaInAFailingWorkflow() { var cases = new[] { TestCase.FailTask, TestCase.PopFailedWorkflow }; foreach (var testCase in cases) { var lua = new BadLua(testCase); var message = "HandlesExceptionsFromBadLuaInAFailingWorkflow:" + testCase; var db = _mux.GetDatabase(); db.ScriptEvaluate("print(\"" + message + "\")"); db.ScriptEvaluate("redis.call(\"flushdb\")"); var th = new ErroringTestWithLongRunnerTaskHandler("Node4", "Node3"); var complete = new ManualResetEvent(false); var failed = new ManualResetEvent(false); var exception = new ManualResetEvent(false); var events = new List <string>(); var wh = new WorkflowHandler(); wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); }; wh.WorkflowFailed += (s, w) => { events.Add("failed"); failed.Set(); }; EventHandler <Exception> eh = (s, e) => { events.Add(e.Message); exception.Set(); }; using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, lua, eh, Behaviours.Processor | Behaviours.Submitter)) { var t1 = new TaskName("TestNode1"); var t2 = new TaskName("TestNode2"); var t3 = new TaskName("TestNode3"); var t4 = new TaskName("TestNode4"); var workflow = new Workflow(new WorkflowName("TestWorkflow")); workflow.AddTask(t1, new Payload("Node1"), NoType, SimplePriority, EmptyTaskList, new [] { t2 }); workflow.AddTask(t2, new Payload("Node2"), NoType, SimplePriority, new [] { t1 }, new [] { t3, t4 }); workflow.AddTask(t3, new Payload("Node3"), NoType, SimplePriority, new [] { t2 }, EmptyTaskList); workflow.AddTask(t4, new Payload("Node4"), NoType, SimplePriority, new [] { t2 }, EmptyTaskList); wm.PushWorkflow(workflow); var waitResult = WaitHandle.WaitAny(new[] { exception, failed, complete }, 2000); Assert.AreEqual(0, waitResult); } } }
public void CanCleanUpAfterAFailedWorkflow() { var db = _mux.GetDatabase(); db.ScriptEvaluate("print(\"CanCleanUpAfterAFailedWorkflow\")"); db.ScriptEvaluate("redis.call(\"flushdb\")"); var th = new ErroringTestWithLongRunnerTaskHandler("Node4", "Node3"); var complete = new ManualResetEvent(false); var failed = new ManualResetEvent(false); var exception = new ManualResetEvent(false); var events = new List<string>(); var wh = new WorkflowHandler(); wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); }; wh.WorkflowFailed += (s, w) => { events.Add("failed"); failed.Set(); }; EventHandler<Exception> eh = (s, e) => { events.Add(e.Message); exception.Set(); }; using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), eh)) { var t1 = new TaskName("TestNode1"); var t2 = new TaskName("TestNode2"); var t3 = new TaskName("TestNode3"); var t4 = new TaskName("TestNode4"); var workflow = new Workflow(new WorkflowName("TestWorkflow")); workflow.AddTask(t1, new Payload("Node1"), NoType, SimplePriority, EmptyTaskList, new [] { t2 }); workflow.AddTask(t2, new Payload("Node2"), NoType, SimplePriority, new [] { t1 }, new [] { t3, t4 }); workflow.AddTask(t3, new Payload("Node3"), NoType, SimplePriority, new [] { t2 }, EmptyTaskList); workflow.AddTask(t4, new Payload("Node4"), NoType, SimplePriority, new [] { t2 }, EmptyTaskList); var workflowId = wm.PushWorkflow(workflow); var result = WaitHandle.WaitAny(new[] { exception, failed, complete }, 2000); if(result == 0) throw new Exception("Failed in workflow operation"); // in a real app, handler could add exception to a list to process // In principle this is a failed workflow, as one of the tasks will fail // However, if all tasks get started, then the succeeding leaf node finishes first, this will be marked successful // Is a workflow considered complete when all tasks have started, or when all tasks have finished? // CHoose latter. Console.WriteLine("TaskHandler events"); foreach (var ev in th.Events) Console.WriteLine("TH event: " + ev); Console.WriteLine("WM events"); foreach (var ev in events) Console.WriteLine("Event: " + ev); Assert.AreEqual(1, result); wm.CleanUp(workflowId.ToString()); } // Should leave highwatermark id keys alone db = _mux.GetDatabase(); for (var t = 0; t < 4; t++) { Assert.IsFalse(db.KeyExists("task:" + t)); Assert.IsFalse(db.KeyExists("parents-" + t)); Assert.IsFalse(db.KeyExists("children-" + t)); Assert.IsFalse(db.SetContains("tasks", t)); Assert.IsFalse(db.SetContains("submitted", t)); Assert.IsFalse(db.SetContains("complete", t)); Assert.IsFalse(db.SetContains("failed", t)); if (t == 3) { Assert.IsTrue(db.SetContains("abandoned", t)); db.SetRemove("abandoned", t); } else Assert.IsFalse(db.SetContains("abandoned", t)); Assert.AreEqual(false, db.SetRemove("running", t)); } Assert.AreEqual(0, db.ListRemove("workflowComplete", "1")); Assert.AreEqual(0, db.ListRemove("workflowFailed", "1")); Assert.IsFalse(db.KeyExists("workflow-tasks-1")); Assert.IsFalse(db.KeyExists("workflow-remaining-1")); Assert.IsFalse(db.SetContains("workflows", "1")); }
public void HandlesExceptionsFromBadLuaInAFailingWorkflow() { var cases = new[] { TestCase.FailTask, TestCase.PopFailedWorkflow }; foreach (var testCase in cases) { var lua = new BadLua(testCase); var message = "HandlesExceptionsFromBadLuaInAFailingWorkflow:" + testCase; var db = _mux.GetDatabase(); db.ScriptEvaluate("print(\"" + message + "\")"); db.ScriptEvaluate("redis.call(\"flushdb\")"); var th = new ErroringTestWithLongRunnerTaskHandler("Node4", "Node3"); var complete = new ManualResetEvent(false); var failed = new ManualResetEvent(false); var exception = new ManualResetEvent(false); var events = new List<string>(); var wh = new WorkflowHandler(); wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); }; wh.WorkflowFailed += (s, w) => { events.Add("failed"); failed.Set(); }; EventHandler<Exception> eh = (s, e) => { events.Add(e.Message); exception.Set(); }; using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, lua, eh, Behaviours.Processor | Behaviours.Submitter)) { var t1 = new TaskName("TestNode1"); var t2 = new TaskName("TestNode2"); var t3 = new TaskName("TestNode3"); var t4 = new TaskName("TestNode4"); var workflow = new Workflow(new WorkflowName("TestWorkflow")); workflow.AddTask(t1, new Payload("Node1"), NoType, SimplePriority, EmptyTaskList, new [] { t2 }); workflow.AddTask(t2, new Payload("Node2"), NoType, SimplePriority, new [] { t1 }, new [] { t3, t4 }); workflow.AddTask(t3, new Payload("Node3"), NoType, SimplePriority, new [] { t2 }, EmptyTaskList); workflow.AddTask(t4, new Payload("Node4"), NoType, SimplePriority, new [] { t2 }, EmptyTaskList); wm.PushWorkflow(workflow); var waitResult = WaitHandle.WaitAny(new[] { exception, failed, complete }, 2000); Assert.AreEqual(0, waitResult); } } }
public void HandlesExceptionsFromBadLuaInAFailingWorkflow() { var cases = new[] { TestCase.FailTask, TestCase.PopFailedWorkflow }; foreach (var testCase in cases) { var lua = new BadLua(testCase); var message = "HandlesExceptionsFromBadLuaInAFailingWorkflow:" + testCase; var db = _mux.GetDatabase(); db.ScriptEvaluate("print(\"" + message + "\")"); db.ScriptEvaluate("redis.call(\"flushdb\")"); var th = new ErroringTestWithLongRunnerTaskHandler("Node4", "Node3"); var complete = new ManualResetEvent(false); var failed = new ManualResetEvent(false); var exception = new ManualResetEvent(false); var events = new List<string>(); var wh = new WorkflowHandler(); wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); }; wh.WorkflowFailed += (s, w) => { events.Add("failed"); failed.Set(); }; EventHandler<Exception> eh = (s, e) => { events.Add(e.Message); exception.Set(); }; using (var wm = new WorkflowManagement(_mux, th, wh, "test", null, lua, eh, Behaviours.Processor | Behaviours.Submitter)) { var workflowName = "TestWorkflow"; var tasks = new List<Task>(); tasks.Add(new Task { Type = "", Name = "TestNode1", Payload = "Node1", Parents = new string[] { }, Children = new string[] { "TestNode2" }, Workflow = workflowName }); tasks.Add(new Task { Type = "", Name = "TestNode2", Payload = "Node2", Parents = new string[] { "TestNode1" }, Children = new string[] { "TestNode3", "TestNode4" }, Workflow = workflowName }); tasks.Add(new Task { Type = "", Name = "TestNode3", Payload = "Node3", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName }); tasks.Add(new Task { Type = "", Name = "TestNode4", Payload = "Node4", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName }); var workflow = new Workflow { Name = workflowName, Tasks = tasks }; wm.PushWorkflow(workflow); var waitResult = WaitHandle.WaitAny(new[] { exception, failed, complete }, 2000); Assert.AreEqual(0, waitResult); } } }
public void CanCleanUpAfterAFailedWorkflow() { var db = _mux.GetDatabase(); db.ScriptEvaluate("print(\"CanCleanUpAfterAFailedWorkflow\")"); db.ScriptEvaluate("redis.call(\"flushdb\")"); var th = new ErroringTestWithLongRunnerTaskHandler("Node4", "Node3"); var complete = new ManualResetEvent(false); var failed = new ManualResetEvent(false); var exception = new ManualResetEvent(false); var events = new List <string>(); var wh = new WorkflowHandler(); wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); }; wh.WorkflowFailed += (s, w) => { events.Add("failed"); failed.Set(); }; EventHandler <Exception> eh = (s, e) => { events.Add(e.Message); exception.Set(); }; using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), eh)) { var t1 = new TaskName("TestNode1"); var t2 = new TaskName("TestNode2"); var t3 = new TaskName("TestNode3"); var t4 = new TaskName("TestNode4"); var workflow = new Workflow(new WorkflowName("TestWorkflow")); workflow.AddTask(t1, new Payload("Node1"), NoType, SimplePriority, EmptyTaskList, new [] { t2 }); workflow.AddTask(t2, new Payload("Node2"), NoType, SimplePriority, new [] { t1 }, new [] { t3, t4 }); workflow.AddTask(t3, new Payload("Node3"), NoType, SimplePriority, new [] { t2 }, EmptyTaskList); workflow.AddTask(t4, new Payload("Node4"), NoType, SimplePriority, new [] { t2 }, EmptyTaskList); var workflowId = wm.PushWorkflow(workflow); var result = WaitHandle.WaitAny(new[] { exception, failed, complete }, 2000); if (result == 0) { throw new Exception("Failed in workflow operation"); // in a real app, handler could add exception to a list to process } // In principle this is a failed workflow, as one of the tasks will fail // However, if all tasks get started, then the succeeding leaf node finishes first, this will be marked successful // Is a workflow considered complete when all tasks have started, or when all tasks have finished? // CHoose latter. Console.WriteLine("TaskHandler events"); foreach (var ev in th.Events) { Console.WriteLine("TH event: " + ev); } Console.WriteLine("WM events"); foreach (var ev in events) { Console.WriteLine("Event: " + ev); } Assert.AreEqual(1, result); wm.CleanUp(workflowId.ToString()); } // Should leave highwatermark id keys alone db = _mux.GetDatabase(); for (var t = 0; t < 4; t++) { Assert.IsFalse(db.KeyExists("task:" + t)); Assert.IsFalse(db.KeyExists("parents-" + t)); Assert.IsFalse(db.KeyExists("children-" + t)); Assert.IsFalse(db.SetContains("tasks", t)); Assert.IsFalse(db.SetContains("submitted", t)); Assert.IsFalse(db.SetContains("complete", t)); Assert.IsFalse(db.SetContains("failed", t)); if (t == 3) { Assert.IsTrue(db.SetContains("abandoned", t)); db.SetRemove("abandoned", t); } else { Assert.IsFalse(db.SetContains("abandoned", t)); } Assert.AreEqual(false, db.SetRemove("running", t)); } Assert.AreEqual(0, db.ListRemove("workflowComplete", "1")); Assert.AreEqual(0, db.ListRemove("workflowFailed", "1")); Assert.IsFalse(db.KeyExists("workflow-tasks-1")); Assert.IsFalse(db.KeyExists("workflow-remaining-1")); Assert.IsFalse(db.SetContains("workflows", "1")); }