github.com/Axway/agent-sdk@v1.1.101/pkg/jobs/intervaljob.go (about)

     1  package jobs
     2  
     3  import (
     4  	"time"
     5  )
     6  
     7  type intervalJobProps struct {
     8  	interval time.Duration
     9  	stopChan chan bool
    10  }
    11  
    12  type intervalJob struct {
    13  	baseJob
    14  	intervalJobProps
    15  }
    16  
    17  // newIntervalJob - creates an interval run job
    18  func newIntervalJob(newJob Job, interval time.Duration, name string, failJobChan chan string, opts ...jobOpt) (JobExecution, error) {
    19  	thisJob := intervalJob{
    20  		createBaseJob(newJob, failJobChan, name, JobTypeInterval),
    21  		intervalJobProps{
    22  			interval: interval,
    23  			stopChan: make(chan bool, 1),
    24  		},
    25  	}
    26  
    27  	for _, o := range opts {
    28  		o(&thisJob.baseJob)
    29  	}
    30  
    31  	go thisJob.start()
    32  	return &thisJob, nil
    33  }
    34  
    35  func (b *intervalJob) handleExecution() {
    36  	// Execute the job now and then start the interval period
    37  	b.executeCronJob()
    38  	if b.getError() != nil {
    39  		b.setExecutionError()
    40  		b.logger.Error(b.getError())
    41  		b.setConsecutiveFails(b.getConsecutiveFails() + 1)
    42  		return
    43  	}
    44  	b.setConsecutiveFails(0)
    45  }
    46  
    47  // start - calls the Execute function from the Job definition
    48  func (b *intervalJob) start() {
    49  	b.startLog()
    50  	b.waitForReady()
    51  
    52  	// This could happen while rescheduling the job, pool tries to start
    53  	// and one of the job fails which triggers stop setting the flag to not ready
    54  	// Return in this case to allow pool to reschedule the job
    55  	if !b.IsReady() {
    56  		return
    57  	}
    58  
    59  	b.setIsStopped(false)
    60  	b.SetStatus(JobStatusRunning)
    61  
    62  	// Execute the job now and then start the interval period
    63  	b.handleExecution()
    64  
    65  	ticker := time.NewTicker(b.interval)
    66  	defer ticker.Stop()
    67  	for {
    68  		// Non-blocking channel read, if stopped then exit
    69  		select {
    70  		case <-b.stopChan:
    71  			b.SetStatus(JobStatusStopped)
    72  			return
    73  		case <-ticker.C:
    74  			b.handleExecution()
    75  			ticker.Stop()
    76  			ticker = time.NewTicker(b.interval)
    77  		}
    78  	}
    79  }
    80  
    81  // stop - write to the stop channel to stop the execution loop
    82  func (b *intervalJob) stop() {
    83  	if b.getIsStopped() {
    84  		b.logger.Tracef("job has already been stopped")
    85  		return
    86  	}
    87  	b.stopLog()
    88  	if b.IsReady() {
    89  		b.logger.Tracef("writing to %s stop channel", b.GetName())
    90  		b.stopChan <- true
    91  		b.logger.Tracef("wrote to %s stop channel", b.GetName())
    92  		b.UnsetIsReady()
    93  	} else {
    94  		b.stopReadyIfWaiting(0)
    95  	}
    96  	b.setIsStopped(true)
    97  }