diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 5efb8c9b37..3dff0f7f63 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -5415,7 +5415,7 @@ WITH INNER JOIN template_version_preset_prebuilds tvpp ON tvpp.preset_id = tvp.id WHERE t.id = $1::uuid GROUP BY t.id, tv.id, tvpp.id), - prebuilds_in_progress AS (SELECT wpb.template_version_id, pj.id AS job_id, pj.type, pj.job_status + prebuilds_in_progress AS (SELECT wpb.template_version_id, pj.id AS job_id, pj.type, pj.job_status, wpb.transition FROM workspace_prebuild_builds wpb INNER JOIN workspace_latest_build wlb ON wpb.workspace_id = wlb.workspace_id INNER JOIN provisioner_jobs pj ON wlb.job_id = pj.id @@ -5423,12 +5423,17 @@ WITH ('succeeded'::provisioner_job_status, 'canceled'::provisioner_job_status, 'failed'::provisioner_job_status)) SELECT t.template_id, - CAST(COUNT(p.id) AS INT) AS actual, -- running prebuilds for active version - CAST(MAX(CASE WHEN t.using_active_version THEN t.desired_instances ELSE 0 END) AS int) AS desired, -- we only care about the active version's desired instances - CAST(SUM(CASE WHEN t.using_active_version THEN 0 ELSE 1 END) AS INT) AS extraneous, -- running prebuilds for inactive version - CAST(COUNT(pip.template_version_id) AS INT) AS in_progress, - t.deleted, - t.deprecated + CAST(COUNT(p.id) AS INT) AS actual, -- running prebuilds for active version + CAST(MAX(CASE WHEN t.using_active_version THEN t.desired_instances ELSE 0 END) AS int) AS desired, -- we only care about the active version's desired instances + CAST(SUM(CASE WHEN t.using_active_version THEN 0 ELSE 1 END) AS INT) AS extraneous, -- running prebuilds for inactive version + CAST(SUM(CASE + WHEN pip.transition = 'start'::workspace_transition THEN 1 + ELSE 0 END) AS INT) AS starting, + CAST(SUM(CASE + WHEN pip.transition = 'delete'::workspace_transition THEN 1 + ELSE 0 END) AS INT) AS deleting, + t.deleted AS template_deleted, + t.deprecated AS template_deprecated FROM templates_with_prebuilds t LEFT JOIN running_prebuilds p ON p.template_version_id = t.template_version_id LEFT JOIN prebuilds_in_progress pip ON pip.template_version_id = t.template_version_id @@ -5436,13 +5441,14 @@ GROUP BY t.template_id, p.id, t.deleted, t.deprecated, pip.template_version_id ` type GetTemplatePrebuildStateRow struct { - TemplateID uuid.UUID `db:"template_id" json:"template_id"` - Actual int32 `db:"actual" json:"actual"` - Desired int32 `db:"desired" json:"desired"` - Extraneous int32 `db:"extraneous" json:"extraneous"` - InProgress int32 `db:"in_progress" json:"in_progress"` - Deleted bool `db:"deleted" json:"deleted"` - Deprecated bool `db:"deprecated" json:"deprecated"` + TemplateID uuid.UUID `db:"template_id" json:"template_id"` + Actual int32 `db:"actual" json:"actual"` + Desired int32 `db:"desired" json:"desired"` + Extraneous int32 `db:"extraneous" json:"extraneous"` + Starting int32 `db:"starting" json:"starting"` + Deleting int32 `db:"deleting" json:"deleting"` + TemplateDeleted bool `db:"template_deleted" json:"template_deleted"` + TemplateDeprecated bool `db:"template_deprecated" json:"template_deprecated"` } func (q *sqlQuerier) GetTemplatePrebuildState(ctx context.Context, templateID uuid.UUID) ([]GetTemplatePrebuildStateRow, error) { @@ -5459,9 +5465,10 @@ func (q *sqlQuerier) GetTemplatePrebuildState(ctx context.Context, templateID uu &i.Actual, &i.Desired, &i.Extraneous, - &i.InProgress, - &i.Deleted, - &i.Deprecated, + &i.Starting, + &i.Deleting, + &i.TemplateDeleted, + &i.TemplateDeprecated, ); err != nil { return nil, err } diff --git a/coderd/database/queries/prebuilds.sql b/coderd/database/queries/prebuilds.sql index 78bddc5116..91fe9c6831 100644 --- a/coderd/database/queries/prebuilds.sql +++ b/coderd/database/queries/prebuilds.sql @@ -18,7 +18,7 @@ WITH INNER JOIN template_version_preset_prebuilds tvpp ON tvpp.preset_id = tvp.id WHERE t.id = @template_id::uuid GROUP BY t.id, tv.id, tvpp.id), - prebuilds_in_progress AS (SELECT wpb.template_version_id, pj.id AS job_id, pj.type, pj.job_status + prebuilds_in_progress AS (SELECT wpb.template_version_id, pj.id AS job_id, pj.type, pj.job_status, wpb.transition FROM workspace_prebuild_builds wpb INNER JOIN workspace_latest_build wlb ON wpb.workspace_id = wlb.workspace_id INNER JOIN provisioner_jobs pj ON wlb.job_id = pj.id @@ -26,12 +26,17 @@ WITH ('succeeded'::provisioner_job_status, 'canceled'::provisioner_job_status, 'failed'::provisioner_job_status)) SELECT t.template_id, - CAST(COUNT(p.id) AS INT) AS actual, -- running prebuilds for active version - CAST(MAX(CASE WHEN t.using_active_version THEN t.desired_instances ELSE 0 END) AS int) AS desired, -- we only care about the active version's desired instances - CAST(SUM(CASE WHEN t.using_active_version THEN 0 ELSE 1 END) AS INT) AS extraneous, -- running prebuilds for inactive version - CAST(COUNT(pip.template_version_id) AS INT) AS in_progress, - t.deleted, - t.deprecated + CAST(COUNT(p.id) AS INT) AS actual, -- running prebuilds for active version + CAST(MAX(CASE WHEN t.using_active_version THEN t.desired_instances ELSE 0 END) AS int) AS desired, -- we only care about the active version's desired instances + CAST(SUM(CASE WHEN t.using_active_version THEN 0 ELSE 1 END) AS INT) AS extraneous, -- running prebuilds for inactive version + CAST(SUM(CASE + WHEN pip.transition = 'start'::workspace_transition THEN 1 + ELSE 0 END) AS INT) AS starting, + CAST(SUM(CASE + WHEN pip.transition = 'delete'::workspace_transition THEN 1 + ELSE 0 END) AS INT) AS deleting, + t.deleted AS template_deleted, + t.deprecated AS template_deprecated FROM templates_with_prebuilds t LEFT JOIN running_prebuilds p ON p.template_version_id = t.template_version_id LEFT JOIN prebuilds_in_progress pip ON pip.template_version_id = t.template_version_id diff --git a/coderd/prebuilds/controller.go b/coderd/prebuilds/controller.go index dccd87f341..4fcbdbb266 100644 --- a/coderd/prebuilds/controller.go +++ b/coderd/prebuilds/controller.go @@ -146,22 +146,21 @@ func (c Controller) reconcileTemplate(ctx context.Context, template database.Tem } for _, result := range results { - desired, actual, extraneous, inProgress := result.Desired, result.Actual, result.Extraneous, result.InProgress + desired, actual, extraneous, starting, deleting := result.Desired, result.Actual, result.Extraneous, result.Starting, result.Deleting // If the template has become deleted or deprecated since the last reconciliation, we need to ensure we // scale those prebuilds down to zero. - if result.Deleted || result.Deprecated { + if result.TemplateDeleted || result.TemplateDeprecated { desired = 0 } - toCreate := math.Max(0, float64(desired-(actual+inProgress))) - // TODO: we might need to get inProgress here by job type (i.e. create or destroy), then we wouldn't have this ambiguity - toDestroy := math.Max(0, float64(extraneous-inProgress)) + toCreate := math.Max(0, float64(desired-(actual+starting))) + toDestroy := math.Max(0, float64(extraneous-deleting)) c.logger.Info(innerCtx, "template prebuild state retrieved", slog.F("template_id", template.ID), slog.F("to_create", toCreate), slog.F("to_destroy", toDestroy), slog.F("desired", desired), slog.F("actual", actual), - slog.F("extraneous", extraneous), slog.F("in_progress", inProgress)) + slog.F("extraneous", extraneous), slog.F("starting", starting), slog.F("deleting", deleting)) } return nil