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 }