github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/resource_cache_lifecycle.go (about) 1 package db 2 3 import ( 4 "strings" 5 6 "code.cloudfoundry.org/lager" 7 sq "github.com/Masterminds/squirrel" 8 "github.com/lib/pq" 9 ) 10 11 //go:generate counterfeiter . ResourceCacheLifecycle 12 13 type ResourceCacheLifecycle interface { 14 CleanUsesForFinishedBuilds(lager.Logger) error 15 CleanBuildImageResourceCaches(lager.Logger) error 16 CleanUpInvalidCaches(lager.Logger) error 17 } 18 19 type resourceCacheLifecycle struct { 20 conn Conn 21 } 22 23 func NewResourceCacheLifecycle(conn Conn) ResourceCacheLifecycle { 24 return &resourceCacheLifecycle{ 25 conn: conn, 26 } 27 } 28 29 func (f *resourceCacheLifecycle) CleanBuildImageResourceCaches(logger lager.Logger) error { 30 _, err := sq.Delete("build_image_resource_caches birc USING builds b"). 31 Where("birc.build_id = b.id"). 32 Where(sq.Expr("((now() - b.end_time) > '24 HOURS'::INTERVAL)")). 33 Where(sq.Eq{"job_id": nil}). 34 RunWith(f.conn). 35 Exec() 36 return err 37 } 38 39 func (f *resourceCacheLifecycle) CleanUsesForFinishedBuilds(logger lager.Logger) error { 40 _, err := psql.Delete("resource_cache_uses rcu USING builds b"). 41 Where(sq.And{ 42 sq.Expr("rcu.build_id = b.id"), 43 sq.Expr("b.interceptible = false"), 44 }). 45 RunWith(f.conn). 46 Exec() 47 return err 48 } 49 50 func (f *resourceCacheLifecycle) CleanUpInvalidCaches(logger lager.Logger) error { 51 stillInUseCacheIds, _, err := sq. 52 Select("resource_cache_id"). 53 From("resource_cache_uses"). 54 ToSql() 55 if err != nil { 56 return err 57 } 58 59 resourceConfigCacheIds, _, err := sq. 60 Select("resource_cache_id"). 61 From("resource_configs"). 62 Where(sq.NotEq{"resource_cache_id": nil}). 63 ToSql() 64 if err != nil { 65 return err 66 } 67 68 buildImageCacheIds, _, err := sq. 69 Select("resource_cache_id"). 70 From("build_image_resource_caches"). 71 ToSql() 72 if err != nil { 73 return err 74 } 75 76 nextBuildInputsCacheIds, _, err := sq. 77 Select("r_cache.id"). 78 From("next_build_inputs nbi"). 79 Join("resources r ON r.id = nbi.resource_id"). 80 Join("resource_config_versions rcv ON rcv.version_md5 = nbi.version_md5 AND rcv.resource_config_scope_id = r.resource_config_scope_id"). 81 Join("resource_caches r_cache ON r_cache.resource_config_id = r.resource_config_id AND r_cache.version_md5 = rcv.version_md5"). 82 Join("jobs j ON nbi.job_id = j.id"). 83 Join("pipelines p ON j.pipeline_id = p.id"). 84 Where(sq.Expr("p.paused = false")). 85 ToSql() 86 if err != nil { 87 return err 88 } 89 90 query, args, err := sq.Delete("resource_caches"). 91 Where("id NOT IN (" + strings.Join([]string{ 92 stillInUseCacheIds, 93 resourceConfigCacheIds, 94 buildImageCacheIds, 95 nextBuildInputsCacheIds, 96 }, " UNION ") + ")"). 97 Suffix("RETURNING id"). 98 PlaceholderFormat(sq.Dollar). 99 ToSql() 100 if err != nil { 101 return err 102 } 103 104 rows, err := f.conn.Query(query, args...) 105 if err != nil { 106 if pqErr, ok := err.(*pq.Error); ok && pqErr.Code.Name() == pqFKeyViolationErrCode { 107 // this can happen if a use or resource cache is created referencing the 108 // config; as the subqueries above are not atomic 109 return nil 110 } 111 112 return err 113 } 114 115 defer Close(rows) 116 117 var deletedCacheIDs []int 118 for rows.Next() { 119 var cacheID int 120 err = rows.Scan(&cacheID) 121 if err != nil { 122 return nil 123 } 124 125 deletedCacheIDs = append(deletedCacheIDs, cacheID) 126 } 127 128 if len(deletedCacheIDs) > 0 { 129 logger.Debug("deleted-resource-caches", lager.Data{"id": deletedCacheIDs}) 130 } 131 132 return nil 133 } 134 135 func (f *resourceCacheLifecycle) CleanUsesForPausedPipelineResources() error { 136 pausedPipelineIds, _, err := sq. 137 Select("id"). 138 Distinct(). 139 From("pipelines"). 140 Where(sq.Expr("paused = false")). 141 ToSql() 142 if err != nil { 143 return err 144 } 145 146 _, err = psql.Delete("resource_cache_uses rcu USING resources r"). 147 Where(sq.And{ 148 sq.Expr("r.pipeline_id NOT IN (" + pausedPipelineIds + ")"), 149 sq.Expr("rcu.resource_id = r.id"), 150 }). 151 RunWith(f.conn). 152 Exec() 153 154 return err 155 }