github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/component/runner.go (about)

     1  package component
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/clock"
     9  	"code.cloudfoundry.org/lager"
    10  	"code.cloudfoundry.org/lager/lagerctx"
    11  )
    12  
    13  var Clock = clock.NewClock()
    14  
    15  type NotificationsBus interface {
    16  	Listen(string) (chan bool, error)
    17  	Unlisten(string, chan bool) error
    18  }
    19  
    20  // Schedulable represents a workload that is executed normally on a periodic
    21  // schedule, but can also be run immediately.
    22  type Schedulable interface {
    23  	RunPeriodically(context.Context)
    24  	RunImmediately(context.Context)
    25  }
    26  
    27  // Runner runs a workload periodically, or immediately upon receiving a
    28  // notification.
    29  type Runner struct {
    30  	Logger lager.Logger
    31  
    32  	Interval  time.Duration
    33  	Component Component
    34  	Bus       NotificationsBus
    35  
    36  	Schedulable Schedulable
    37  }
    38  
    39  func (scheduler *Runner) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
    40  	scheduler.Logger.Debug("start")
    41  	defer scheduler.Logger.Debug("done")
    42  
    43  	notifier, err := scheduler.Bus.Listen(scheduler.Component.Name())
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	defer scheduler.Bus.Unlisten(scheduler.Component.Name(), notifier)
    49  
    50  	ctx, cancel := context.WithCancel(context.Background())
    51  	go func() {
    52  		<-signals
    53  		cancel()
    54  	}()
    55  
    56  	close(ready)
    57  
    58  	for {
    59  		timer := Clock.NewTimer(scheduler.Interval)
    60  
    61  		select {
    62  		case <-notifier:
    63  			timer.Stop()
    64  			runCtx := lagerctx.NewContext(ctx, scheduler.Logger.Session("notify"))
    65  			scheduler.Schedulable.RunImmediately(runCtx)
    66  
    67  		case <-timer.C():
    68  			runCtx := lagerctx.NewContext(ctx, scheduler.Logger.Session("tick"))
    69  			scheduler.Schedulable.RunPeriodically(runCtx)
    70  
    71  		case <-ctx.Done():
    72  			timer.Stop()
    73  			return nil
    74  		}
    75  	}
    76  }