atc: behavior: make resource build creation kinder
rather than running a blind DELETE query followed by an INSERT and
catching the conflict error, just check to see if a build exists first.
this cleans up noisy postgres error logs.
@@ -365,8 +365,29 @@ func (r *resource) CreateBuild(ctx context.Context, manuallyTriggered bool) (Bui
if !manuallyTriggered {
params["resource_id"] = r.id
+
+ var completed, noBuild bool
+ err = psql.Select("completed").
+ From("builds").
+ Where(sq.Eq{"resource_id": r.id}).
+ RunWith(tx).
+ QueryRow().
+ Scan(&completed)
+ if err != nil {
+ if err == sql.ErrNoRows {
+ noBuild = true
+ } else {
+ return nil, false, err
+ }
+ }
+
+ if !noBuild && !completed {
+ // a build is already running; leave it be
+ return nil, false, nil
}
+ if completed {
+ // previous build finished; clear it out
_, err = psql.Delete("builds").
Where(sq.Eq{
"resource_id": r.id,
@@ -377,11 +398,15 @@ func (r *resource) CreateBuild(ctx context.Context, manuallyTriggered bool) (Bui
if err != nil {
return nil, false, fmt.Errorf("delete previous build: %w", err)
}
+ }
+ }
build := newEmptyBuild(r.conn, r.lockFactory)
err = createBuild(tx, build, params)
if err != nil {
if pqErr, ok := err.(*pq.Error); ok && pqErr.Code.Name() == pqUniqueViolationErrCode {
+ // handle unique violation, though this shouldn't ever happen due to the
+ // above checks
return nil, false, nil
}
