github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/gc/destroyer.go (about) 1 package gc 2 3 import ( 4 "errors" 5 6 "code.cloudfoundry.org/lager" 7 "github.com/pf-qiu/concourse/v6/atc/db" 8 "github.com/pf-qiu/concourse/v6/atc/metric" 9 ) 10 11 //go:generate counterfeiter . Destroyer 12 13 // TODO : consider making this just a struct with methods on it, 14 // we don't ever use the FakeDestroyer, so we don't even need the 15 // interface boundaries for testing 16 17 // Destroyer allows removal of containers and volumes from the database 18 type Destroyer interface { 19 FindDestroyingVolumesForGc(workerName string) ([]string, error) 20 DestroyContainers(workerName string, handles []string) error 21 DestroyVolumes(workerName string, handles []string) error 22 } 23 24 type destroyer struct { 25 logger lager.Logger 26 containerRepository db.ContainerRepository 27 volumeRepository db.VolumeRepository 28 } 29 30 // NewDestroyer provides a constructor for a Destroyer interface implementation 31 func NewDestroyer( 32 logger lager.Logger, 33 containerRepository db.ContainerRepository, 34 volumeRepository db.VolumeRepository, 35 ) Destroyer { 36 return &destroyer{ 37 logger: logger, 38 containerRepository: containerRepository, 39 volumeRepository: volumeRepository, 40 } 41 } 42 43 func (d *destroyer) DestroyContainers(workerName string, currentHandles []string) error { 44 if workerName == "" { 45 err := errors.New("worker-name-must-be-provided") 46 d.logger.Error("failed-to-destroy-containers", err) 47 48 return err 49 } 50 51 if currentHandles == nil { 52 return nil 53 } 54 55 deleted, err := d.containerRepository.RemoveDestroyingContainers(workerName, currentHandles) 56 if err != nil { 57 d.logger.Error("failed-to-destroy-containers", err) 58 return err 59 } 60 61 metric.Metrics.ContainersDeleted.IncDelta(deleted) 62 return nil 63 } 64 65 func (d *destroyer) DestroyVolumes(workerName string, currentHandles []string) error { 66 if workerName == "" { 67 err := errors.New("worker-name-must-be-provided") 68 d.logger.Error("failed-to-destroy-volumes", err) 69 70 return err 71 } 72 73 if currentHandles == nil { 74 return nil 75 } 76 77 deleted, err := d.volumeRepository.RemoveDestroyingVolumes(workerName, currentHandles) 78 if err != nil { 79 d.logger.Error("failed-to-destroy-volumes", err) 80 return err 81 } 82 83 metric.Metrics.VolumesDeleted.IncDelta(deleted) 84 return nil 85 } 86 87 // TODO : Remove this and call GetDestroyingVolumes directly on the volumeRepository 88 // feels odd to have a "Find*" on an interface named "Destroyer" 89 func (d *destroyer) FindDestroyingVolumesForGc(workerName string) ([]string, error) { 90 destroyingVolumesHandles, err := d.volumeRepository.GetDestroyingVolumes(workerName) 91 if err != nil { 92 d.logger.Error("failed-to-get-orphaned-volumes", err) 93 return nil, err 94 } 95 96 if len(destroyingVolumesHandles) > 0 { 97 d.logger.Debug("found-orphaned-volumes", lager.Data{ 98 "destroying": len(destroyingVolumesHandles), 99 }) 100 } 101 102 metric.DestroyingVolumesToBeGarbageCollected{ 103 Volumes: len(destroyingVolumesHandles), 104 }.Emit(d.logger) 105 106 return destroyingVolumesHandles, nil 107 }