github.com/cloudfoundry-attic/ltc@v0.0.0-20151123212628-098adc7919fc/task_runner/task_runner.go (about) 1 package task_runner 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "time" 8 9 "github.com/cloudfoundry-incubator/ltc/logs/reserved_app_ids" 10 "github.com/cloudfoundry-incubator/ltc/task_examiner" 11 "github.com/cloudfoundry-incubator/receptor" 12 "github.com/pivotal-golang/clock" 13 ) 14 15 const ( 16 AttemptedToCreateLatticeDebugErrorMessage = reserved_app_ids.LatticeDebugLogStreamAppId + " is a reserved app name. It is used internally to stream debug logs for lattice components." 17 18 taskDomain = "lattice" 19 ) 20 21 //go:generate counterfeiter -o fake_task_runner/fake_task_runner.go . TaskRunner 22 type TaskRunner interface { 23 CreateTask(createTaskParams CreateTaskParams) error 24 SubmitTask(submitTaskJson []byte) (string, error) 25 DeleteTask(taskGuid string) error 26 CancelTask(taskGuid string) error 27 } 28 29 type taskRunner struct { 30 receptorClient receptor.Client 31 taskExaminer task_examiner.TaskExaminer 32 clock clock.Clock 33 } 34 35 func New(receptorClient receptor.Client, taskExaminer task_examiner.TaskExaminer, clock clock.Clock) TaskRunner { 36 return &taskRunner{receptorClient, taskExaminer, clock} 37 } 38 39 func (taskRunner *taskRunner) CreateTask(createTaskParams CreateTaskParams) error { 40 task := createTaskParams.GetReceptorRequest() 41 42 if task.TaskGuid == reserved_app_ids.LatticeDebugLogStreamAppId { 43 return errors.New(AttemptedToCreateLatticeDebugErrorMessage) 44 } 45 46 submittedTasks, err := taskRunner.receptorClient.Tasks() 47 if err != nil { 48 return err 49 } 50 for _, submittedTask := range submittedTasks { 51 if task.TaskGuid == submittedTask.TaskGuid { 52 return errors.New(task.TaskGuid + " has already been submitted") 53 } 54 } 55 56 if err := taskRunner.receptorClient.UpsertDomain("lattice", 0); err != nil { 57 return err 58 } 59 60 return taskRunner.receptorClient.CreateTask(task) 61 } 62 63 func (taskRunner *taskRunner) SubmitTask(submitTaskJson []byte) (string, error) { 64 task := receptor.TaskCreateRequest{} 65 if err := json.Unmarshal(submitTaskJson, &task); err != nil { 66 return "", err 67 } 68 69 if task.TaskGuid == reserved_app_ids.LatticeDebugLogStreamAppId { 70 return task.TaskGuid, errors.New(AttemptedToCreateLatticeDebugErrorMessage) 71 } 72 73 submittedTasks, err := taskRunner.receptorClient.Tasks() 74 if err != nil { 75 return task.TaskGuid, err 76 } 77 for _, submittedTask := range submittedTasks { 78 if task.TaskGuid == submittedTask.TaskGuid { 79 return task.TaskGuid, errors.New(task.TaskGuid + " has already been submitted") 80 } 81 } 82 83 if err := taskRunner.receptorClient.UpsertDomain("lattice", 0); err != nil { 84 return task.TaskGuid, err 85 } 86 87 return task.TaskGuid, taskRunner.receptorClient.CreateTask(task) 88 } 89 90 func (e *taskRunner) DeleteTask(taskGuid string) error { 91 92 /*Ignoring the error of cancel task */ 93 e.receptorClient.CancelTask(taskGuid) 94 95 timeout := e.clock.NewTimer(30 * time.Second) 96 for { 97 select { 98 case <-timeout.C(): 99 return errors.New("Delete Task failed: task cancellation timed out") 100 case <-e.clock.NewTimer(1 * time.Second).C(): 101 taskInfo, err := e.taskExaminer.TaskStatus(taskGuid) 102 if err == nil && taskInfo.State == receptor.TaskStateCompleted { 103 err := e.receptorClient.DeleteTask(taskGuid) 104 return err 105 } 106 } 107 } 108 } 109 110 func (e *taskRunner) CancelTask(taskGuid string) error { 111 taskInfo, err := e.taskExaminer.TaskStatus(taskGuid) 112 if err != nil { 113 return err 114 } 115 if taskInfo.State != receptor.TaskStatePending && taskInfo.State != receptor.TaskStateRunning { 116 return fmt.Errorf("Unable to cancel %s task", taskInfo.State) 117 } 118 return e.receptorClient.CancelTask(taskGuid) 119 }