fix(coderd/database/dbfake): prevent cross-test job stealing in WorkspaceBuildBuilder (#22598)

Previously, WorkspaceBuildBuilder.doInTX() inserted provisioner jobs
with empty tags and used a loop in AcquireProvisionerJob that could
match other tests' pending jobs when parallel tests share a database.

Add a unique tag (jobID -> "true") to each provisioner job at insert
time, then use that tag in AcquireProvisionerJob to target only the
correct job. This follows the same pattern used in dbgen.ProvisionerJob.

Closes coder/internal#1367
This commit is contained in:
Mathias Fredriksson
2026-03-04 19:47:34 +02:00
committed by GitHub
parent 1a30ca1a2a
commit c7dd429bbf
+24 -24
View File
@@ -372,6 +372,12 @@ func (b WorkspaceBuildBuilder) doInTX() WorkspaceResponse {
})
require.NoError(b.t, err)
// Tag the job so AcquireProvisionerJob only matches this
// builder's job, preventing cross-test interference when
// parallel tests share a database. Same pattern as
// dbgen.ProvisionerJob.
tags := database.StringMap{jobID.String(): "true", "scope": "organization"}
job, err := b.db.InsertProvisionerJob(ownerCtx, database.InsertProvisionerJobParams{
ID: jobID,
CreatedAt: takeFirstTime(b.jobCreatedAt, b.ws.CreatedAt, dbtime.Now()),
@@ -383,7 +389,7 @@ func (b WorkspaceBuildBuilder) doInTX() WorkspaceResponse {
FileID: uuid.New(),
Type: database.ProvisionerJobTypeWorkspaceBuild,
Input: payload,
Tags: map[string]string{},
Tags: tags,
TraceMetadata: pqtype.NullRawMessage{},
LogsOverflowed: false,
})
@@ -395,30 +401,24 @@ func (b WorkspaceBuildBuilder) doInTX() WorkspaceResponse {
// Provisioner jobs are created in 'pending' status
b.logger.Debug(context.Background(), "pending the provisioner job")
case database.ProvisionerJobStatusRunning:
// might need to do this multiple times if we got a template version
// import job as well
b.logger.Debug(context.Background(), "looping to acquire provisioner job")
b.logger.Debug(context.Background(), "acquiring the provisioner job")
startedAt := takeFirstTime(b.jobStartedAt, dbtime.Now())
for {
j, err := b.db.AcquireProvisionerJob(ownerCtx, database.AcquireProvisionerJobParams{
OrganizationID: job.OrganizationID,
StartedAt: sql.NullTime{
Time: startedAt,
Valid: true,
},
WorkerID: uuid.NullUUID{
UUID: uuid.New(),
Valid: true,
},
Types: []database.ProvisionerType{database.ProvisionerTypeEcho},
ProvisionerTags: []byte(`{"scope": "organization"}`),
})
require.NoError(b.t, err, "acquire starting job")
if j.ID == job.ID {
b.logger.Debug(context.Background(), "acquired provisioner job", slog.F("job_id", job.ID))
break
}
}
j, err := b.db.AcquireProvisionerJob(ownerCtx, database.AcquireProvisionerJobParams{
OrganizationID: job.OrganizationID,
StartedAt: sql.NullTime{
Time: startedAt,
Valid: true,
},
WorkerID: uuid.NullUUID{
UUID: uuid.New(),
Valid: true,
},
Types: []database.ProvisionerType{database.ProvisionerTypeEcho},
ProvisionerTags: must(json.Marshal(tags)),
})
require.NoError(b.t, err, "acquire the provisioner job")
require.Equal(b.t, job.ID, j.ID, "acquired wrong provisioner job")
b.logger.Debug(context.Background(), "acquired provisioner job", slog.F("job_id", job.ID))
if !b.jobUpdatedAt.IsZero() {
err = b.db.UpdateProvisionerJobByID(ownerCtx, database.UpdateProvisionerJobByIDParams{
ID: job.ID,