Skip to content

Commit 310511e

Browse files
committed
add check for available provisioners before we try to do a workspace
transition so that we don't accumulate autostart jobs that will eventually have to be cleaned up by the reaper routine Signed-off-by: Callum Styan <callumstyan@gmail.com>
1 parent 314bb66 commit 310511e

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

coderd/autobuild/lifecycle_executor.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/coder/coder/v2/coderd/database/dbauthz"
2727
"github.com/coder/coder/v2/coderd/database/dbtime"
2828
"github.com/coder/coder/v2/coderd/database/provisionerjobs"
29+
"github.com/coder/coder/v2/coderd/provisionerdserver"
2930
"github.com/coder/coder/v2/coderd/database/pubsub"
3031
"github.com/coder/coder/v2/coderd/notifications"
3132
"github.com/coder/coder/v2/coderd/schedule"
@@ -131,6 +132,30 @@ func (e *Executor) Run() {
131132
}()
132133
}
133134

135+
// Add this function to check for available provisioners
136+
func (e *Executor) hasAvailableProvisioners(ctx context.Context, tx database.Store, ws database.Workspace, templateVersionJob database.ProvisionerJob) (bool, error) {
137+
// Get eligible provisioner daemons for this workspace's template
138+
provisionerDaemons, err := tx.GetProvisionerDaemonsByOrganization(ctx, database.GetProvisionerDaemonsByOrganizationParams{
139+
OrganizationID: ws.OrganizationID,
140+
WantTags: templateVersionJob.Tags,
141+
})
142+
if err != nil {
143+
return false, xerrors.Errorf("get provisioner daemons: %w", err)
144+
}
145+
146+
// Check if any provisioners are active (not stale)
147+
now := dbtime.Now()
148+
for _, pd := range provisionerDaemons {
149+
if pd.LastSeenAt.Valid {
150+
age := now.Sub(pd.LastSeenAt.Time)
151+
if age <= provisionerdserver.StaleInterval {
152+
return true, nil
153+
}
154+
}
155+
}
156+
return false, nil
157+
}
158+
134159
func (e *Executor) runOnce(t time.Time) Stats {
135160
stats := Stats{
136161
Transitions: make(map[uuid.UUID]database.WorkspaceTransition),
@@ -280,6 +305,22 @@ func (e *Executor) runOnce(t time.Time) Stats {
280305
return nil
281306
}
282307

308+
// Get the template version job to access tags
309+
templateVersionJob, err := tx.GetProvisionerJobByID(e.ctx, activeTemplateVersion.JobID)
310+
if err != nil {
311+
return xerrors.Errorf("get template version job: %w", err)
312+
}
313+
314+
// Before creating the workspace build, check for available provisioners
315+
hasProvisioners, err := e.hasAvailableProvisioners(e.ctx, tx, ws, templateVersionJob)
316+
if err != nil {
317+
return xerrors.Errorf("check provisioner availability: %w", err)
318+
}
319+
if !hasProvisioners {
320+
log.Warn(e.ctx, "skipping autostart - no available provisioners")
321+
return nil // Skip this workspace
322+
}
323+
283324
if nextTransition != "" {
284325
builder := wsbuilder.New(ws, nextTransition, *e.buildUsageChecker.Load()).
285326
SetLastWorkspaceBuildInTx(&latestBuild).

0 commit comments

Comments
 (0)