167 lines
4.0 KiB
Go
167 lines
4.0 KiB
Go
package db
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
|
|
sq "github.com/Masterminds/squirrel"
|
|
"github.com/concourse/concourse/atc"
|
|
"github.com/concourse/concourse/atc/db/lock"
|
|
)
|
|
|
|
//go:generate counterfeiter . ResourceCacheFactory
|
|
|
|
type ResourceCacheFactory interface {
|
|
FindOrCreateResourceCache(
|
|
resourceCacheUser ResourceCacheUser,
|
|
resourceTypeName string,
|
|
version atc.Version,
|
|
source atc.Source,
|
|
params atc.Params,
|
|
resourceTypes atc.VersionedResourceTypes,
|
|
) (UsedResourceCache, error)
|
|
|
|
// changing resource cache to interface to allow updates on object is not feasible.
|
|
// Since we need to pass it recursively in ResourceConfig.
|
|
// Also, metadata will be available to us before we create resource cache so this
|
|
// method can be removed at that point. See https://github.com/concourse/concourse/issues/534
|
|
UpdateResourceCacheMetadata(UsedResourceCache, []atc.MetadataField) error
|
|
ResourceCacheMetadata(UsedResourceCache) (ResourceConfigMetadataFields, error)
|
|
}
|
|
|
|
type resourceCacheFactory struct {
|
|
conn Conn
|
|
lockFactory lock.LockFactory
|
|
}
|
|
|
|
func NewResourceCacheFactory(conn Conn, lockFactory lock.LockFactory) ResourceCacheFactory {
|
|
return &resourceCacheFactory{
|
|
conn: conn,
|
|
lockFactory: lockFactory,
|
|
}
|
|
}
|
|
|
|
func (f *resourceCacheFactory) FindOrCreateResourceCache(
|
|
resourceCacheUser ResourceCacheUser,
|
|
resourceTypeName string,
|
|
version atc.Version,
|
|
source atc.Source,
|
|
params atc.Params,
|
|
resourceTypes atc.VersionedResourceTypes,
|
|
) (UsedResourceCache, error) {
|
|
resourceConfigDescriptor, err := constructResourceConfigDescriptor(resourceTypeName, source, resourceTypes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resourceCache := ResourceCacheDescriptor{
|
|
ResourceConfigDescriptor: resourceConfigDescriptor,
|
|
Version: version,
|
|
Params: params,
|
|
}
|
|
|
|
tx, err := f.conn.Begin()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer Rollback(tx)
|
|
|
|
usedResourceCache, err := resourceCache.findOrCreate(tx, f.lockFactory, f.conn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = resourceCache.use(tx, usedResourceCache, resourceCacheUser)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return usedResourceCache, nil
|
|
}
|
|
|
|
func (f *resourceCacheFactory) UpdateResourceCacheMetadata(resourceCache UsedResourceCache, metadata []atc.MetadataField) error {
|
|
metadataJSON, err := json.Marshal(metadata)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = psql.Update("resource_caches").
|
|
Set("metadata", metadataJSON).
|
|
Where(sq.Eq{"id": resourceCache.ID()}).
|
|
RunWith(f.conn).
|
|
Exec()
|
|
return err
|
|
}
|
|
|
|
func (f *resourceCacheFactory) ResourceCacheMetadata(resourceCache UsedResourceCache) (ResourceConfigMetadataFields, error) {
|
|
var metadataJSON sql.NullString
|
|
err := psql.Select("metadata").
|
|
From("resource_caches").
|
|
Where(sq.Eq{"id": resourceCache.ID()}).
|
|
RunWith(f.conn).
|
|
QueryRow().
|
|
Scan(&metadataJSON)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var metadata []ResourceConfigMetadataField
|
|
if metadataJSON.Valid {
|
|
err = json.Unmarshal([]byte(metadataJSON.String), &metadata)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return metadata, nil
|
|
}
|
|
|
|
func findResourceCacheByID(tx Tx, resourceCacheID int, lock lock.LockFactory, conn Conn) (UsedResourceCache, bool, error) {
|
|
var rcID int
|
|
var versionBytes string
|
|
|
|
err := psql.Select("resource_config_id", "version").
|
|
From("resource_caches").
|
|
Where(sq.Eq{"id": resourceCacheID}).
|
|
RunWith(tx).
|
|
QueryRow().
|
|
Scan(&rcID, &versionBytes)
|
|
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, false, nil
|
|
}
|
|
return nil, false, err
|
|
}
|
|
|
|
var version atc.Version
|
|
err = json.Unmarshal([]byte(versionBytes), &version)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
rc, found, err := findResourceConfigByID(tx, rcID, lock, conn)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
if !found {
|
|
return nil, false, nil
|
|
}
|
|
|
|
usedResourceCache := &usedResourceCache{
|
|
id: resourceCacheID,
|
|
version: version,
|
|
resourceConfig: rc,
|
|
lockFactory: lock,
|
|
conn: conn,
|
|
}
|
|
|
|
return usedResourceCache, true, nil
|
|
}
|