func (s *Server) addTask(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { tr, err := marshalTask(r.Body) if err != nil { respond(500, rbody.FromError(err), w) return } sch, err := makeSchedule(tr.Schedule) if err != nil { respond(500, rbody.FromError(err), w) return } var opts []core.TaskOption if tr.Deadline != "" { dl, err := time.ParseDuration(tr.Deadline) if err != nil { respond(500, rbody.FromError(err), w) return } opts = append(opts, core.TaskDeadlineDuration(dl)) } if tr.Name != "" { opts = append(opts, core.SetTaskName(tr.Name)) } opts = append(opts, core.OptionStopOnFailure(10)) task, errs := s.mt.CreateTask(sch, tr.Workflow, tr.Start, opts...) if errs != nil && len(errs.Errors()) != 0 { var errMsg string for _, e := range errs.Errors() { errMsg = errMsg + e.Error() + " -- " } respond(500, rbody.FromError(errors.New(errMsg[:len(errMsg)-4])), w) return } taskB := rbody.AddSchedulerTaskFromTask(task) taskB.Href = taskURI(r.Host, task) respond(201, taskB, w) }
func TestTask(t *testing.T) { log.SetLevel(log.FatalLevel) Convey("Task", t, func() { sampleWFMap := wmap.Sample() wf, errs := wmapToWorkflow(sampleWFMap) So(errs, ShouldBeEmpty) c := &mockMetricManager{} c.setAcceptedContentType("rabbitmq", core.PublisherPluginType, 5, []string{plugin.SnapGOBContentType}) mgrs := newManagers(c) err := wf.BindPluginContentTypes(&mgrs) So(err, ShouldBeNil) Convey("task + simple schedule", func() { sch := schedule.NewSimpleSchedule(time.Millisecond * 100) task, err := newTask(sch, wf, newWorkManager(), c, emitter) So(err, ShouldBeNil) task.Spin() time.Sleep(time.Millisecond * 10) // it is a race so we slow down the test So(task.state, ShouldEqual, core.TaskSpinning) task.Stop() }) Convey("Task specified-name test", func() { sch := schedule.NewSimpleSchedule(time.Millisecond * 100) task, err := newTask(sch, wf, newWorkManager(), c, emitter, core.SetTaskName("My name is unique")) So(err, ShouldBeNil) task.Spin() So(task.GetName(), ShouldResemble, "My name is unique") }) Convey("Task default-name test", func() { sch := schedule.NewSimpleSchedule(time.Millisecond * 100) task, err := newTask(sch, wf, newWorkManager(), c, emitter) So(err, ShouldBeNil) task.Spin() So(task.GetName(), ShouldResemble, "Task-"+task.ID()) }) Convey("Task deadline duration test", func() { sch := schedule.NewSimpleSchedule(time.Millisecond * 100) task, err := newTask(sch, wf, newWorkManager(), c, emitter, core.TaskDeadlineDuration(20*time.Second)) So(err, ShouldBeNil) task.Spin() So(task.deadlineDuration, ShouldEqual, 20*time.Second) task.Option(core.TaskDeadlineDuration(20 * time.Second)) So(core.TaskDeadlineDuration(2*time.Second), ShouldNotBeEmpty) }) Convey("Tasks are created and creation of task table is checked", func() { sch := schedule.NewSimpleSchedule(time.Millisecond * 100) task, err := newTask(sch, wf, newWorkManager(), c, emitter) So(err, ShouldBeNil) task1, err := newTask(sch, wf, newWorkManager(), c, emitter) So(err, ShouldBeNil) task1.Spin() task.Spin() tC := newTaskCollection() tC.add(task) tC.add(task1) taskTable := tC.Table() So(len(taskTable), ShouldEqual, 2) }) Convey("Task is created and starts to spin", func() { sch := schedule.NewSimpleSchedule(time.Second * 5) task, err := newTask(sch, wf, newWorkManager(), c, emitter) So(err, ShouldBeNil) task.Spin() So(task.state, ShouldEqual, core.TaskSpinning) Convey("Task is Stopped", func() { task.Stop() time.Sleep(time.Millisecond * 10) // it is a race so we slow down the test So(task.state, ShouldEqual, core.TaskStopped) }) }) Convey("task fires", func() { sch := schedule.NewSimpleSchedule(time.Nanosecond * 100) task, err := newTask(sch, wf, newWorkManager(), c, emitter) So(err, ShouldBeNil) task.Spin() time.Sleep(time.Millisecond * 50) So(task.hitCount, ShouldBeGreaterThan, 2) So(task.missedIntervals, ShouldBeGreaterThan, 2) task.Stop() }) Convey("Enable a running task", func() { sch := schedule.NewSimpleSchedule(time.Millisecond * 10) task, err := newTask(sch, wf, newWorkManager(), c, emitter) So(err, ShouldBeNil) task.Spin() err = task.Enable() So(err, ShouldNotBeNil) So(task.State(), ShouldEqual, core.TaskSpinning) }) Convey("Enable a disabled task", func() { sch := schedule.NewSimpleSchedule(time.Millisecond * 10) task, err := newTask(sch, wf, newWorkManager(), c, emitter) So(err, ShouldBeNil) task.state = core.TaskDisabled err = task.Enable() So(err, ShouldBeNil) So(task.State(), ShouldEqual, core.TaskStopped) }) }) Convey("Create task collection", t, func() { sampleWFMap := wmap.Sample() wf, errs := wmapToWorkflow(sampleWFMap) So(errs, ShouldBeEmpty) sch := schedule.NewSimpleSchedule(time.Millisecond * 10) task, err := newTask(sch, wf, newWorkManager(), &mockMetricManager{}, emitter) So(err, ShouldBeNil) So(task.id, ShouldNotBeEmpty) So(task.id, ShouldNotBeNil) taskCollection := newTaskCollection() Convey("Add task to collection", func() { err := taskCollection.add(task) So(err, ShouldBeNil) So(len(taskCollection.table), ShouldEqual, 1) Convey("Attempt to add the same task again", func() { err := taskCollection.add(task) So(err, ShouldNotBeNil) }) Convey("Get task from collection", func() { t := taskCollection.Get(task.id) So(t, ShouldNotBeNil) So(t.ID(), ShouldEqual, task.id) So(t.CreationTime().Nanosecond(), ShouldBeLessThan, time.Now().Nanosecond()) So(t.HitCount(), ShouldEqual, 0) So(t.MissedCount(), ShouldEqual, 0) So(t.State(), ShouldEqual, core.TaskStopped) So(t.Status(), ShouldEqual, core.WorkflowStopped) So(t.LastRunTime().IsZero(), ShouldBeTrue) }) Convey("Attempt to get task with an invalid Id", func() { t := taskCollection.Get("1234") So(t, ShouldBeNil) }) Convey("Create another task and compare the id", func() { task2, err := newTask(sch, wf, newWorkManager(), &mockMetricManager{}, emitter) So(err, ShouldBeNil) So(task2.id, ShouldNotEqual, task.ID()) }) }) }) }
func (t *mockTask) Option(...core.TaskOption) core.TaskOption { return core.TaskDeadlineDuration(0) }
func TestScheduler(t *testing.T) { log.SetLevel(log.FatalLevel) Convey("NewTask", t, func() { c := new(mockMetricManager) c.setAcceptedContentType("machine", core.ProcessorPluginType, 1, []string{"snap.*", "snap.gob", "foo.bar"}) c.setReturnedContentType("machine", core.ProcessorPluginType, 1, []string{"snap.gob"}) c.setAcceptedContentType("rmq", core.PublisherPluginType, -1, []string{"snap.json", "snap.gob"}) c.setAcceptedContentType("file", core.PublisherPluginType, -1, []string{"snap.json"}) cfg := GetDefaultConfig() s := New(cfg) s.SetMetricManager(c) w := wmap.NewWorkflowMap() // Collection node w.CollectNode.AddMetric("/foo/bar", 1) w.CollectNode.AddMetric("/foo/baz", 2) w.CollectNode.AddConfigItem("/foo/bar", "username", "root") w.CollectNode.AddConfigItem("/foo/bar", "port", 8080) w.CollectNode.AddConfigItem("/foo/bar", "ratio", 0.32) w.CollectNode.AddConfigItem("/foo/bar", "yesorno", true) // Add a process node pr1 := wmap.NewProcessNode("machine", 1) pr1.AddConfigItem("username", "wat") pr1.AddConfigItem("howmuch", 9999) // Add a process node pr12 := wmap.NewProcessNode("machine", 1) pr12.AddConfigItem("username", "wat2") pr12.AddConfigItem("howmuch", 99992) // Publish node for our process node pu1 := wmap.NewPublishNode("rmq", -1) pu1.AddConfigItem("birthplace", "dallas") pu1.AddConfigItem("monies", 2) // Publish node direct to collection pu2 := wmap.NewPublishNode("file", -1) pu2.AddConfigItem("color", "brown") pu2.AddConfigItem("purpose", 42) pr12.Add(pu2) pr1.Add(pr12) w.CollectNode.Add(pr1) w.CollectNode.Add(pu1) e := s.Start() So(e, ShouldBeNil) t, te := s.CreateTask(schedule.NewSimpleSchedule(time.Second*1), w, false) So(te.Errors(), ShouldBeEmpty) for _, i := range t.(*task).workflow.processNodes { testInboundContentType(i) } for _, i := range t.(*task).workflow.publishNodes { testInboundContentType(i) } So(t.(*task).workflow.processNodes[0].ProcessNodes[0].PublishNodes[0].InboundContentType, ShouldEqual, "snap.json") Convey("returns errors when metrics do not validate", func() { c.failValidatingMetrics = true c.failValidatingMetricsAfter = 1 _, err := s.CreateTask(schedule.NewSimpleSchedule(time.Second*1), w, false) So(err, ShouldNotBeNil) fmt.Printf("%d", len(err.Errors())) So(len(err.Errors()), ShouldBeGreaterThan, 0) So(err.Errors()[0], ShouldResemble, serror.New(errors.New("metric validation error"))) }) Convey("returns an error when scheduler started and MetricManager is not set", func() { s1 := New(GetDefaultConfig()) err := s1.Start() So(err, ShouldNotBeNil) fmt.Printf("%v", err) So(err, ShouldResemble, ErrMetricManagerNotSet) }) Convey("returns an error when wrong namespace is given wo workflowmap ", func() { w.CollectNode.AddMetric("****/&&&", 3) w.CollectNode.AddConfigItem("****/&&&", "username", "user") _, err := s.CreateTask(schedule.NewSimpleSchedule(time.Second*1), w, false) So(len(err.Errors()), ShouldBeGreaterThan, 0) }) // TODO NICK Convey("returns an error when a schedule does not validate", func() { s1 := New(GetDefaultConfig()) s1.Start() _, err := s1.CreateTask(schedule.NewSimpleSchedule(time.Second*1), w, false) So(err, ShouldNotBeNil) So(len(err.Errors()), ShouldBeGreaterThan, 0) So(err.Errors()[0], ShouldResemble, serror.New(ErrSchedulerNotStarted)) s1.metricManager = c s1.Start() _, err1 := s1.CreateTask(schedule.NewSimpleSchedule(time.Second*0), w, false) So(err1.Errors()[0].Error(), ShouldResemble, "Interval must be greater than 0") }) // // TODO NICK Convey("create a task", func() { tsk, err := s.CreateTask(schedule.NewSimpleSchedule(time.Second*5), w, false) So(len(err.Errors()), ShouldEqual, 0) So(tsk, ShouldNotBeNil) So(tsk.(*task).deadlineDuration, ShouldResemble, DefaultDeadlineDuration) So(len(s.GetTasks()), ShouldEqual, 2) Convey("error when attempting to add duplicate task", func() { err := s.tasks.add(tsk.(*task)) So(err, ShouldNotBeNil) }) Convey("get created task", func() { t, err := s.GetTask(tsk.ID()) So(err, ShouldBeNil) So(t, ShouldEqual, tsk) }) Convey("error when attempting to get a task that doesn't exist", func() { t, err := s.GetTask("1234") So(err, ShouldNotBeNil) So(t, ShouldBeNil) }) Convey("stop a stopped task", func() { err := s.StopTask(tsk.ID()) So(len(err), ShouldEqual, 1) So(err[0].Error(), ShouldEqual, "Task is already stopped.") }) }) // // // TODO NICK Convey("returns a task with a 6 second deadline duration", func() { tsk, err := s.CreateTask(schedule.NewSimpleSchedule(time.Second*6), w, false, core.TaskDeadlineDuration(6*time.Second)) So(len(err.Errors()), ShouldEqual, 0) So(tsk.(*task).deadlineDuration, ShouldResemble, time.Duration(6*time.Second)) prev := tsk.(*task).Option(core.TaskDeadlineDuration(1 * time.Second)) So(tsk.(*task).deadlineDuration, ShouldResemble, time.Duration(1*time.Second)) tsk.(*task).Option(prev) So(tsk.(*task).deadlineDuration, ShouldResemble, time.Duration(6*time.Second)) }) Convey("Enable a stopped task", func() { tsk, _ := s.CreateTask(schedule.NewSimpleSchedule(time.Millisecond*100), w, false) So(tsk, ShouldNotBeNil) _, err := s.EnableTask(tsk.ID()) So(err, ShouldNotBeNil) }) Convey("Enable a disabled task", func() { tsk, _ := s.CreateTask(schedule.NewSimpleSchedule(time.Millisecond*100), w, false) So(tsk, ShouldNotBeNil) t := s.tasks.Get(tsk.ID()) t.state = core.TaskDisabled etsk, err1 := s.EnableTask(tsk.ID()) So(err1, ShouldBeNil) So(etsk.State(), ShouldEqual, core.TaskStopped) }) Convey("Start disabled task", func() { tsk, _ := s.CreateTask(schedule.NewSimpleSchedule(time.Millisecond*100), w, false) So(tsk, ShouldNotBeNil) t := s.tasks.Get(tsk.ID()) t.state = core.TaskDisabled err := s.StartTask(tsk.ID()) So(err[0].Error(), ShouldResemble, "Task is disabled. Cannot be started.") So(t.state, ShouldEqual, core.TaskDisabled) }) }) Convey("Stop()", t, func() { Convey("Should set scheduler state to SchedulerStopped", func() { scheduler := New(GetDefaultConfig()) c := new(mockMetricManager) scheduler.metricManager = c scheduler.Start() scheduler.Stop() So(scheduler.state, ShouldEqual, schedulerStopped) }) }) Convey("SetMetricManager()", t, func() { Convey("Should set metricManager for scheduler", func() { scheduler := New(GetDefaultConfig()) c := new(mockMetricManager) scheduler.SetMetricManager(c) So(scheduler.metricManager, ShouldEqual, c) }) }) }