github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/resource_cache_factory.go (about) 1 package db 2 3 import ( 4 "database/sql" 5 "encoding/json" 6 7 sq "github.com/Masterminds/squirrel" 8 "github.com/pf-qiu/concourse/v6/atc" 9 "github.com/pf-qiu/concourse/v6/atc/db/lock" 10 ) 11 12 //go:generate counterfeiter . ResourceCacheFactory 13 14 type ResourceCacheFactory interface { 15 FindOrCreateResourceCache( 16 resourceCacheUser ResourceCacheUser, 17 resourceTypeName string, 18 version atc.Version, 19 source atc.Source, 20 params atc.Params, 21 resourceTypes atc.VersionedResourceTypes, 22 ) (UsedResourceCache, error) 23 24 // changing resource cache to interface to allow updates on object is not feasible. 25 // Since we need to pass it recursively in ResourceConfig. 26 // Also, metadata will be available to us before we create resource cache so this 27 // method can be removed at that point. See https://github.com/pf-qiu/concourse/v6/issues/534 28 UpdateResourceCacheMetadata(UsedResourceCache, []atc.MetadataField) error 29 ResourceCacheMetadata(UsedResourceCache) (ResourceConfigMetadataFields, error) 30 31 FindResourceCacheByID(id int) (UsedResourceCache, bool, error) 32 } 33 34 type resourceCacheFactory struct { 35 conn Conn 36 lockFactory lock.LockFactory 37 } 38 39 func NewResourceCacheFactory(conn Conn, lockFactory lock.LockFactory) ResourceCacheFactory { 40 return &resourceCacheFactory{ 41 conn: conn, 42 lockFactory: lockFactory, 43 } 44 } 45 46 func (f *resourceCacheFactory) FindOrCreateResourceCache( 47 resourceCacheUser ResourceCacheUser, 48 resourceTypeName string, 49 version atc.Version, 50 source atc.Source, 51 params atc.Params, 52 resourceTypes atc.VersionedResourceTypes, 53 ) (UsedResourceCache, error) { 54 resourceConfigDescriptor, err := constructResourceConfigDescriptor(resourceTypeName, source, resourceTypes) 55 if err != nil { 56 return nil, err 57 } 58 59 resourceCache := ResourceCacheDescriptor{ 60 ResourceConfigDescriptor: resourceConfigDescriptor, 61 Version: version, 62 Params: params, 63 } 64 65 tx, err := f.conn.Begin() 66 if err != nil { 67 return nil, err 68 } 69 70 defer Rollback(tx) 71 72 usedResourceCache, err := resourceCache.findOrCreate(tx, f.lockFactory, f.conn) 73 if err != nil { 74 return nil, err 75 } 76 77 err = resourceCache.use(tx, usedResourceCache, resourceCacheUser) 78 if err != nil { 79 return nil, err 80 } 81 82 err = tx.Commit() 83 if err != nil { 84 return nil, err 85 } 86 87 return usedResourceCache, nil 88 } 89 90 func (f *resourceCacheFactory) UpdateResourceCacheMetadata(resourceCache UsedResourceCache, metadata []atc.MetadataField) error { 91 metadataJSON, err := json.Marshal(metadata) 92 if err != nil { 93 return err 94 } 95 _, err = psql.Update("resource_caches"). 96 Set("metadata", metadataJSON). 97 Where(sq.Eq{"id": resourceCache.ID()}). 98 RunWith(f.conn). 99 Exec() 100 return err 101 } 102 103 func (f *resourceCacheFactory) ResourceCacheMetadata(resourceCache UsedResourceCache) (ResourceConfigMetadataFields, error) { 104 var metadataJSON sql.NullString 105 err := psql.Select("metadata"). 106 From("resource_caches"). 107 Where(sq.Eq{"id": resourceCache.ID()}). 108 RunWith(f.conn). 109 QueryRow(). 110 Scan(&metadataJSON) 111 if err != nil { 112 return nil, err 113 } 114 115 var metadata []ResourceConfigMetadataField 116 if metadataJSON.Valid { 117 err = json.Unmarshal([]byte(metadataJSON.String), &metadata) 118 if err != nil { 119 return nil, err 120 } 121 } 122 123 return metadata, nil 124 } 125 126 func (f *resourceCacheFactory) FindResourceCacheByID(id int) (UsedResourceCache, bool, error) { 127 tx, err := f.conn.Begin() 128 if err != nil { 129 return nil, false, err 130 } 131 132 defer Rollback(tx) 133 134 return findResourceCacheByID(tx, id, f.lockFactory, f.conn) 135 } 136 137 func findResourceCacheByID(tx Tx, resourceCacheID int, lock lock.LockFactory, conn Conn) (UsedResourceCache, bool, error) { 138 var rcID int 139 var versionBytes string 140 141 err := psql.Select("resource_config_id", "version"). 142 From("resource_caches"). 143 Where(sq.Eq{"id": resourceCacheID}). 144 RunWith(tx). 145 QueryRow(). 146 Scan(&rcID, &versionBytes) 147 148 if err != nil { 149 if err == sql.ErrNoRows { 150 return nil, false, nil 151 } 152 return nil, false, err 153 } 154 155 var version atc.Version 156 err = json.Unmarshal([]byte(versionBytes), &version) 157 if err != nil { 158 return nil, false, err 159 } 160 161 rc, found, err := findResourceConfigByID(tx, rcID, lock, conn) 162 if err != nil { 163 return nil, false, err 164 } 165 166 if !found { 167 return nil, false, nil 168 } 169 170 usedResourceCache := &usedResourceCache{ 171 id: resourceCacheID, 172 version: version, 173 resourceConfig: rc, 174 lockFactory: lock, 175 conn: conn, 176 } 177 178 return usedResourceCache, true, nil 179 }