github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/worker/volume_sweeper.go (about) 1 package worker 2 3 import ( 4 "context" 5 "os" 6 "sync" 7 "time" 8 9 "code.cloudfoundry.org/lager" 10 "code.cloudfoundry.org/lager/lagerctx" 11 "github.com/concourse/baggageclaim" 12 ) 13 14 // volumeSweeper is an ifrit.Runner that periodically reports and 15 // garbage-collects a worker's volumes 16 type volumeSweeper struct { 17 logger lager.Logger 18 interval time.Duration 19 tsaClient TSAClient 20 baggageclaimClient baggageclaim.Client 21 maxInFlight uint16 22 } 23 24 func NewVolumeSweeper( 25 logger lager.Logger, 26 sweepInterval time.Duration, 27 tsaClient TSAClient, 28 bcClient baggageclaim.Client, 29 maxInFlight uint16, 30 ) *volumeSweeper { 31 return &volumeSweeper{ 32 logger: logger, 33 interval: sweepInterval, 34 tsaClient: tsaClient, 35 baggageclaimClient: bcClient, 36 maxInFlight: maxInFlight, 37 } 38 } 39 40 func (sweeper *volumeSweeper) Run(signals <-chan os.Signal, ready chan<- struct{}) error { 41 timer := time.NewTicker(sweeper.interval) 42 43 close(ready) 44 45 for { 46 select { 47 case <-timer.C: 48 sweeper.sweep(sweeper.logger.Session("tick")) 49 50 case sig := <-signals: 51 sweeper.logger.Info("sweep-cancelled-by-signal", lager.Data{"signal": sig}) 52 return nil 53 } 54 } 55 } 56 57 func (sweeper *volumeSweeper) sweep(logger lager.Logger) { 58 ctx := lagerctx.NewContext(context.Background(), logger) 59 60 volumes, err := sweeper.baggageclaimClient.ListVolumes(logger.Session("list-volumes"), baggageclaim.VolumeProperties{}) 61 if err != nil { 62 logger.Error("failed-to-list-volumes", err) 63 } else { 64 handles := []string{} 65 for _, volume := range volumes { 66 handles = append(handles, volume.Handle()) 67 } 68 69 err := sweeper.tsaClient.ReportVolumes(ctx, handles) 70 if err != nil { 71 logger.Error("failed-to-report-volumes", err) 72 } 73 } 74 75 volumeHandles, err := sweeper.tsaClient.VolumesToDestroy(ctx) 76 if err != nil { 77 logger.Error("failed-to-get-volumes-to-destroy", err) 78 } else { 79 var wg sync.WaitGroup 80 maxInFlight := make(chan int, sweeper.maxInFlight) 81 82 for _, handle := range volumeHandles { 83 maxInFlight <- 1 84 wg.Add(1) 85 86 go func(handle string) { 87 err := sweeper.baggageclaimClient.DestroyVolume(logger.Session("destroy-volumes"), handle) 88 if err != nil { 89 logger.WithData(lager.Data{"handle": handle}).Error("failed-to-destroy-volume", err) 90 } 91 92 <-maxInFlight 93 wg.Done() 94 }(handle) 95 } 96 wg.Wait() 97 } 98 }