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  }