public void ThrowsIfAWorkflowHasNoRootParents()
        {
            var db = _mux.GetDatabase();

            db.ScriptEvaluate("print(\"ThrowsIfAWorkflowHasNoRootParents\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler();

            th.LetRun.Set();

            var complete = new ManualResetEvent(false);

            var events = new List <string>();

            var wh = new WorkflowHandler();

            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                var workflow = new Workflow(new WorkflowName("TestWorkflow"));
                workflow.AddTask(new TaskName("TestNode1"), new Payload("Node1"), NoType, SimplePriority, new [] { new TaskName("SomeParent") }, EmptyTaskList);

                wm.PushWorkflow(workflow);

                var result = WaitHandle.WaitAny(new[] { complete }, 2000);

                Assert.AreEqual(0, result);
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanResetOwnTypedTasks()
        {
            var db = _mux.GetDatabase();

            db.ScriptEvaluate("print(\"CanSubmitAndRunAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th  = new BlockingTaskHandler("1");
            var th2 = new BlockingTaskHandler("2");

            var complete = new ManualResetEvent(false);

            var events = new List <string>();

            var wh = new WorkflowHandler();

            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            var t1 = new TaskName("TestNode1");
            var t2 = new TaskName("TestNode2");
            var t3 = new TaskName("TestNode3");
            var t4 = new TaskName("TestNode4");
            var t5 = new TaskName("TestNode5");
            var t6 = new TaskName("TestNode6");

            var type1 = new TaskType("testTaskType");

            var workflow = new Workflow(new WorkflowName("TestWorkflow"));

            workflow.AddTask(t1, new Payload("Node1"), type1, SimplePriority, EmptyTaskList, new[] { t2 });
            workflow.AddTask(t2, new Payload("Node2"), type1, SimplePriority, new[] { t1 }, new[] { t3, t4, t5, t6 });
            workflow.AddTask(t3, new Payload("Node3"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t4, new Payload("Node4"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t5, new Payload("Node5"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t6, new Payload("Node6"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), new[] { type1 }, new Lua()))
            {
                wm.PushWorkflow(workflow);

                // we've picked up the first task, and don't want to pick up any more
                th.Gate.WaitOne();

                Assert.AreEqual(0, db.SortedSetLength("submitted:testTaskType"));
            }

            // create a new wm to simulate a restart of a component
            using (var wm2 = new WorkflowManagement(_mux, th2, wh, new WorkflowManagementId("test"), new[] { type1 }, new Lua()))
            {
                Assert.AreEqual(1, db.SortedSetLength("submitted:testTaskType"));

                th.Abort.Set();
                th2.LetRun.Set();

                var result = complete.WaitOne();
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanReleaseAWorkflow()
        {
            var db = _mux.GetDatabase();

            db.ScriptEvaluate("print(\"CanPauseAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler("1");

            var complete = new ManualResetEvent(false);

            var events = new List <string>();

            var wh = new WorkflowHandler();

            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            var t1 = new TaskName("TestNode1");
            var t2 = new TaskName("TestNode2");
            var t3 = new TaskName("TestNode3");
            var t4 = new TaskName("TestNode4");
            var t5 = new TaskName("TestNode5");
            var t6 = new TaskName("TestNode6");

            var type1 = new TaskType("testTaskType");

            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, EmptyTaskList, new[] { t3, t4, t5, t6 });
            workflow.AddTask(t3, new Payload("Node3"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t4, new Payload("Node4"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t5, new Payload("Node5"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t6, new Payload("Node6"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                var workflowId = wm.PushWorkflow(workflow);

                th.Gate.WaitOne();

                wm.PauseWorkflow(workflowId);

                wm.ReleaseWorkflow(workflowId);

                Assert.AreEqual(1, db.ListLength("submitted"));
                Assert.AreEqual(1, db.SetLength("running"));
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanSubmitAWorkflow()
        {
            var db = _mux.GetDatabase();

            db.ScriptEvaluate("print(\"CanSubmitAndRunAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler();

            th.LetRun.Set();

            var complete = new ManualResetEvent(false);

            var events = new List <string>();

            var wh = new WorkflowHandler();

            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                var t1 = new TaskName("TestNode1");
                var t2 = new TaskName("TestNode2");
                var t3 = new TaskName("TestNode3");
                var t4 = new TaskName("TestNode4");
                var t5 = new TaskName("TestNode5");
                var t6 = new TaskName("TestNode6");

                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, t5, t6 });
                workflow.AddTask(t3, new Payload("Node3"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
                workflow.AddTask(t4, new Payload("Node4"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
                workflow.AddTask(t5, new Payload("Node5"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
                workflow.AddTask(t6, new Payload("Node6"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);

                wm.PushWorkflow(workflow);

                var result = WaitHandle.WaitAny(new[] { complete }, 2000);

                Assert.AreEqual(0, result);
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanQueryForOwnTasks()
        {
            var db = _mux.GetDatabase();

            db.ScriptEvaluate("print(\"CanSubmitAndRunAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler();

            var complete = new ManualResetEvent(false);

            var events = new List <string>();

            var wh = new WorkflowHandler();

            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                var workflow = new Workflow(new WorkflowName("TestWorkflow"));
                workflow.AddTask(new TaskName("TestNode1"), new Payload("Node1"), NoType, SimplePriority, EmptyTaskList, EmptyTaskList);

                wm.PushWorkflow(workflow);

                var taskWasStarted = th.Gate.WaitOne(2000);

                Assert.IsTrue(taskWasStarted);

                var myTasks = wm.FindTasks();

                Assert.AreEqual(1, myTasks.Length);
                Assert.AreEqual("1", myTasks[0]);
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanResetOwnTasks()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanSubmitAndRunAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler("1");
            var th2 = new BlockingTaskHandler("2");

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            var t1 = new TaskName("TestNode1");
            var t2 = new TaskName("TestNode2");
            var t3 = new TaskName("TestNode3");
            var t4 = new TaskName("TestNode4");
            var t5 = new TaskName("TestNode5");
            var t6 = new TaskName("TestNode6");

            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, t5, t6 });
            workflow.AddTask(t3, new Payload("Node3"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t4, new Payload("Node4"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t5, new Payload("Node5"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t6, new Payload("Node6"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                wm.PushWorkflow(workflow);

                // we've picked up the first task, and don't want to pick up any more
                th.Gate.WaitOne();

                Assert.AreEqual(0, db.ListLength("submitted"));
            }

            // create a new wm to simulate a restart of a component
            using (var wm2 = new WorkflowManagement(_mux, th2, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                Assert.AreEqual(1, db.SortedSetLength("submitted"));

                th.Abort.Set();
                th2.LetRun.Set();

                complete.WaitOne();
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanQueryForOwnTasks()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanSubmitAndRunAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler();

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                var workflow = new Workflow(new WorkflowName("TestWorkflow"));
                workflow.AddTask(new TaskName("TestNode1"), new Payload("Node1"), NoType, SimplePriority, EmptyTaskList, EmptyTaskList);

                wm.PushWorkflow(workflow);

                var taskWasStarted = th.Gate.WaitOne(2000);

                Assert.IsTrue(taskWasStarted);

                var myTasks = wm.FindTasks();

                Assert.AreEqual(1, myTasks.Length);
                Assert.AreEqual("1", myTasks[0]);
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanSubmitAWorkflowAsync()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanSubmitAndRunAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler();
            th.LetRun.Set();

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                var t1 = new TaskName("TestNode1");
                var t2 = new TaskName("TestNode2");
                var t3 = new TaskName("TestNode3");
                var t4 = new TaskName("TestNode4");
                var t5 = new TaskName("TestNode5");
                var t6 = new TaskName("TestNode6");

                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, t5, t6 });
                workflow.AddTask(t3, new Payload("Node3"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
                workflow.AddTask(t4, new Payload("Node4"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
                workflow.AddTask(t5, new Payload("Node5"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
                workflow.AddTask(t6, new Payload("Node6"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);

                var id = wm.PushWorkflowAsync(workflow);

                id.Wait();
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void ThrowsIfAWorkflowHasNoRootParents()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"ThrowsIfAWorkflowHasNoRootParents\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler();
            th.LetRun.Set();

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                var workflow = new Workflow(new WorkflowName("TestWorkflow"));
                workflow.AddTask(new TaskName("TestNode1"), new Payload("Node1"), NoType, SimplePriority, new [] { new TaskName("SomeParent") }, EmptyTaskList);
                
                wm.PushWorkflow(workflow);

                var result = WaitHandle.WaitAny(new[] { complete }, 2000);

                Assert.AreEqual(0, result);
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanPauseAWorkflow()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanPauseAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler("1");

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            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[] { }, Children = new string[] { "TestNode3", "TestNode4", "TestNode5", "TestNode6" }, 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 });
            tasks.Add(new Task { Type = "", Name = "TestNode5", Payload = "Node5", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });
            tasks.Add(new Task { Type = "", Name = "TestNode6", Payload = "Node6", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });

            var workflow = new Workflow { Name = workflowName, Tasks = tasks };

            using (var wm = new WorkflowManagement(_mux, th, wh, "test", null, new Lua()))
            {
                var workflowId = wm.PushWorkflow(workflow);

                th.Gate.WaitOne();

                Assert.AreEqual(1, db.SortedSetLength("submitted"));
                Assert.AreEqual(1, db.SetLength("running"));

                wm.PauseWorkflow(workflowId);

                var expected = new List<string> { "1", "2" };
                var state = "paused";

                CheckSetContent(db, expected, state);

                // The running task will run bang into the new state
                th.LetRun.Set();

                Thread.Sleep(500); // gah, honestly. I won't get a signal because no new tasks should be submitted

                expected = new List<string> { "2" };
                state = "paused";

                CheckSetContent(db, expected, state);

                expected = new List<string> { "2" };
                state = "running";

                CheckSetContent(db, expected, state, false);

                // If this is checked before the task has completed then there'll be two paused tasks
                // We've got no hook into the completion event as yet
                Assert.AreEqual(1, db.SetLength("paused")); 
                Assert.AreEqual(1, db.SetLength("paused:1"));
                Assert.AreEqual(0, db.SortedSetLength("submitted"));
                Assert.AreEqual(0, db.SetLength("running"));
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanReleaseAWorkflowWithTypedTasks()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanPauseAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler("1");

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            var workflowName = "TestWorkflow";

            var tasks = new List<Task>();
            tasks.Add(new Task { Type = "testTaskType", Name = "TestNode1", Payload = "Node1", Parents = new string[] { }, Children = new string[] { "TestNode2" }, Workflow = workflowName });
            tasks.Add(new Task { Type = "testTaskType", Name = "TestNode2", Payload = "Node2", Parents = new string[] { }, Children = new string[] { "TestNode3", "TestNode4", "TestNode5", "TestNode6" }, Workflow = workflowName });
            tasks.Add(new Task { Type = "testTaskType", Name = "TestNode3", Payload = "Node3", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });
            tasks.Add(new Task { Type = "testTaskType", Name = "TestNode4", Payload = "Node4", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });
            tasks.Add(new Task { Type = "testTaskType", Name = "TestNode5", Payload = "Node5", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });
            tasks.Add(new Task { Type = "testTaskType", Name = "TestNode6", Payload = "Node6", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });

            var workflow = new Workflow { Name = workflowName, Tasks = tasks };

            using (var wm = new WorkflowManagement(_mux, th, wh, "test", new[] { "testTaskType" }, new Lua()))
            {
                var workflowId = wm.PushWorkflow(workflow);

                th.Gate.WaitOne();

                wm.PauseWorkflow(workflowId);

                wm.ReleaseWorkflow(workflowId);

                Assert.AreEqual(1, db.ListLength("submitted:testTaskType"));
                Assert.AreEqual(1, db.SetLength("running"));
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanQueryForOwnTasks()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanSubmitAndRunAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler();

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            using (var wm = new WorkflowManagement(_mux, th, wh, "test", null, new Lua()))
            {
                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 });

                var workflow = new Workflow { Name = workflowName, Tasks = tasks };

                wm.PushWorkflow(workflow);

                var taskWasStarted = th.Gate.WaitOne(2000);

                Assert.IsTrue(taskWasStarted);

                var myTasks = wm.FindTasks();

                Assert.AreEqual(1, myTasks.Length);
                Assert.AreEqual("1", myTasks[0]);
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanSubmitAWorkflowAsync()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanSubmitAndRunAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler();
            th.LetRun.Set();

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            using (var wm = new WorkflowManagement(_mux, th, wh, "test", null, new Lua()))
            {
                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", "TestNode5", "TestNode6" }, 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 });
                tasks.Add(new Task { Type = "", Name = "TestNode5", Payload = "Node5", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });
                tasks.Add(new Task { Type = "", Name = "TestNode6", Payload = "Node6", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });

                var workflow = new Workflow { Name = workflowName, Tasks = tasks };

                var id = wm.PushWorkflowAsync(workflow);

                id.Wait();
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void ThrowsIfAWorkflowHasNoRootParents()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"ThrowsIfAWorkflowHasNoRootParents\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler();
            th.LetRun.Set();

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            using (var wm = new WorkflowManagement(_mux, th, wh, "test", null, new Lua()))
            {
                var workflowName = "TestWorkflow";

                var tasks = new List<Task>();
                tasks.Add(new Task { Name = "TestNode1", Payload = "Node1", Parents = new string[] { "TestNode0" }, Children = new string[] { }, Workflow = workflowName });

                var workflow = new Workflow { Name = workflowName, Tasks = tasks };

                wm.PushWorkflow(workflow);

                var result = WaitHandle.WaitAny(new[] { complete }, 2000);

                Assert.AreEqual(0, result);
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanPauseAWorkflowWithTypedTasks()
        {
            var db = _mux.GetDatabase();

            db.ScriptEvaluate("print(\"CanPauseAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler("1");

            var complete = new ManualResetEvent(false);

            var events = new List <string>();

            var wh = new WorkflowHandler();

            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            var t1 = new TaskName("TestNode1");
            var t2 = new TaskName("TestNode2");
            var t3 = new TaskName("TestNode3");
            var t4 = new TaskName("TestNode4");
            var t5 = new TaskName("TestNode5");
            var t6 = new TaskName("TestNode6");

            var type1 = new TaskType("testTaskType");

            var workflow = new Workflow(new WorkflowName("TestWorkflow"));

            workflow.AddTask(t1, new Payload("Node1"), type1, SimplePriority, EmptyTaskList, new[] { t2 });
            workflow.AddTask(t2, new Payload("Node2"), type1, SimplePriority, EmptyTaskList, new[] { t3, t4, t5, t6 });
            workflow.AddTask(t3, new Payload("Node3"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t4, new Payload("Node4"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t5, new Payload("Node5"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t6, new Payload("Node6"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), new[] { type1 }, new Lua()))
            {
                var workflowId = wm.PushWorkflow(workflow);

                th.Gate.WaitOne();

                Assert.AreEqual(1, db.SortedSetLength("submitted:testTaskType"));
                Assert.AreEqual(1, db.SetLength("running"));

                wm.PauseWorkflow(workflowId);

                var expected = new List <string> {
                    "1", "2"
                };
                var state = "paused";

                CheckSetContent(db, expected, state);

                // The running task will run bang into the new state
                th.LetRun.Set();

                Thread.Sleep(500); // gah, honestly. I won't get a signal because no new tasks should be submitted

                expected = new List <string> {
                    "2"
                };
                state = "paused";

                CheckSetContent(db, expected, state);

                expected = new List <string> {
                    "2"
                };
                state = "running";

                CheckSetContent(db, expected, state, false);

                // If this is checked before the task has completed then there'll be two paused tasks
                // We've got no hook into the completion event as yet
                Assert.AreEqual(1, db.SetLength("paused"));
                Assert.AreEqual(1, db.SetLength("paused:1"));
                Assert.AreEqual(0, db.ListLength("submitted:testTaskType"));
                Assert.AreEqual(0, db.SetLength("running"));
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanReleaseAWorkflowWithTypedTasks()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanPauseAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler("1");

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            var t1 = new TaskName("TestNode1");
            var t2 = new TaskName("TestNode2");
            var t3 = new TaskName("TestNode3");
            var t4 = new TaskName("TestNode4");
            var t5 = new TaskName("TestNode5");
            var t6 = new TaskName("TestNode6");

            var type1 = new TaskType("testTaskType");

            var workflow = new Workflow(new WorkflowName("TestWorkflow"));
            workflow.AddTask(t1, new Payload("Node1"), type1, SimplePriority, EmptyTaskList, new[] { t2 });
            workflow.AddTask(t2, new Payload("Node2"), type1, SimplePriority, EmptyTaskList, new[] { t3, t4, t5, t6 });
            workflow.AddTask(t3, new Payload("Node3"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t4, new Payload("Node4"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t5, new Payload("Node5"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t6, new Payload("Node6"), type1, SimplePriority, new[] { t2 }, EmptyTaskList);

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), new[] { type1 }, new Lua()))
            {
                var workflowId = wm.PushWorkflow(workflow);

                th.Gate.WaitOne();

                wm.PauseWorkflow(workflowId);

                wm.ReleaseWorkflow(workflowId);

                Assert.AreEqual(1, db.ListLength("submitted:testTaskType"));
                Assert.AreEqual(1, db.SetLength("running"));
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanPauseAWorkflow()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanPauseAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler("1");

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };

            var t1 = new TaskName("TestNode1");
            var t2 = new TaskName("TestNode2");
            var t3 = new TaskName("TestNode3");
            var t4 = new TaskName("TestNode4");
            var t5 = new TaskName("TestNode5");
            var t6 = new TaskName("TestNode6");

            var type1 = new TaskType("testTaskType");

            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, EmptyTaskList, new[] { t3, t4, t5, t6 });
            workflow.AddTask(t3, new Payload("Node3"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t4, new Payload("Node4"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t5, new Payload("Node5"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);
            workflow.AddTask(t6, new Payload("Node6"), NoType, SimplePriority, new[] { t2 }, EmptyTaskList);

            using (var wm = new WorkflowManagement(_mux, th, wh, new WorkflowManagementId("test"), null, new Lua()))
            {
                var workflowId = wm.PushWorkflow(workflow);

                var waitResult = th.Gate.WaitOne(/*2000*/);

                Assert.IsTrue(waitResult);
                Assert.AreEqual(1, db.SortedSetLength("submitted"));
                Assert.AreEqual(1, db.SetLength("running"));

                wm.PauseWorkflow(workflowId);

                var expected = new List<string> { "1", "2" };
                var state = "paused";

                CheckSetContent(db, expected, state);

                // The running task will run bang into the new state
                th.LetRun.Set();

                Thread.Sleep(500); // gah, honestly. I won't get a signal because no new tasks should be submitted

                expected = new List<string> { "2" };
                state = "paused";

                CheckSetContent(db, expected, state);

                expected = new List<string> { "2" };
                state = "running";

                CheckSetContent(db, expected, state, false);

                // If this is checked before the task has completed then there'll be two paused tasks
                // We've got no hook into the completion event as yet
                Assert.AreEqual(1, db.SetLength("paused")); 
                Assert.AreEqual(1, db.SetLength("paused:1"));
                Assert.AreEqual(0, db.SortedSetLength("submitted"));
                Assert.AreEqual(0, db.SetLength("running"));
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }
        public void CanResetOwnTasks()
        {
            var db = _mux.GetDatabase();
            db.ScriptEvaluate("print(\"CanSubmitAndRunAWorkflow\")");
            db.ScriptEvaluate("redis.call(\"flushdb\")");

            var th = new BlockingTaskHandler("1");
            var th2 = new BlockingTaskHandler("2");

            var complete = new ManualResetEvent(false);

            var events = new List<string>();

            var wh = new WorkflowHandler();
            wh.WorkflowComplete += (s, w) => { events.Add("complete"); complete.Set(); };


            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", "TestNode5", "TestNode6" }, 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 });
            tasks.Add(new Task { Type = "", Name = "TestNode5", Payload = "Node5", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });
            tasks.Add(new Task { Type = "", Name = "TestNode6", Payload = "Node6", Parents = new string[] { "TestNode2" }, Children = new string[] { }, Workflow = workflowName });

            var workflow = new Workflow { Name = workflowName, Tasks = tasks };

            using (var wm = new WorkflowManagement(_mux, th, wh, "test", null, new Lua()))
            {
                wm.PushWorkflow(workflow);

                // we've picked up the first task, and don't want to pick up any more
                th.Gate.WaitOne();

                Assert.AreEqual(0, db.ListLength("submitted"));
            }

            // create a new wm to simulate a restart of a component
            using (var wm2 = new WorkflowManagement(_mux, th2, wh, "test", null, new Lua()))
            {
                Assert.AreEqual(1, db.SortedSetLength("submitted"));

                th.Abort.Set();
                th2.LetRun.Set();

                complete.WaitOne();
            }

            db.ScriptEvaluate("redis.call(\"flushdb\")");
        }