mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
Incorporate in-progress jobs into state calculation
Signed-off-by: Danny Kopping <danny@coder.com>
This commit is contained in:
16
coderd/database/dump.sql
generated
16
coderd/database/dump.sql
generated
@ -1823,7 +1823,21 @@ CREATE TABLE workspace_modules (
|
|||||||
);
|
);
|
||||||
|
|
||||||
CREATE VIEW workspace_prebuild_builds AS
|
CREATE VIEW workspace_prebuild_builds AS
|
||||||
SELECT workspace_builds.workspace_id
|
SELECT workspace_builds.id,
|
||||||
|
workspace_builds.created_at,
|
||||||
|
workspace_builds.updated_at,
|
||||||
|
workspace_builds.workspace_id,
|
||||||
|
workspace_builds.template_version_id,
|
||||||
|
workspace_builds.build_number,
|
||||||
|
workspace_builds.transition,
|
||||||
|
workspace_builds.initiator_id,
|
||||||
|
workspace_builds.provisioner_state,
|
||||||
|
workspace_builds.job_id,
|
||||||
|
workspace_builds.deadline,
|
||||||
|
workspace_builds.reason,
|
||||||
|
workspace_builds.daily_cost,
|
||||||
|
workspace_builds.max_deadline,
|
||||||
|
workspace_builds.template_version_preset_id
|
||||||
FROM workspace_builds
|
FROM workspace_builds
|
||||||
WHERE (workspace_builds.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid);
|
WHERE (workspace_builds.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid);
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ FROM workspaces
|
|||||||
WHERE owner_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0';
|
WHERE owner_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0';
|
||||||
|
|
||||||
CREATE VIEW workspace_prebuild_builds AS
|
CREATE VIEW workspace_prebuild_builds AS
|
||||||
SELECT workspace_id
|
SELECT *
|
||||||
FROM workspace_builds
|
FROM workspace_builds
|
||||||
WHERE initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0';
|
WHERE initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0';
|
||||||
|
|
||||||
|
@ -3407,7 +3407,21 @@ type WorkspacePrebuild struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WorkspacePrebuildBuild struct {
|
type WorkspacePrebuildBuild struct {
|
||||||
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
|
ID uuid.UUID `db:"id" json:"id"`
|
||||||
|
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||||
|
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||||
|
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
|
||||||
|
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
|
||||||
|
BuildNumber int32 `db:"build_number" json:"build_number"`
|
||||||
|
Transition WorkspaceTransition `db:"transition" json:"transition"`
|
||||||
|
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
|
||||||
|
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
|
||||||
|
JobID uuid.UUID `db:"job_id" json:"job_id"`
|
||||||
|
Deadline time.Time `db:"deadline" json:"deadline"`
|
||||||
|
Reason BuildReason `db:"reason" json:"reason"`
|
||||||
|
DailyCost int32 `db:"daily_cost" json:"daily_cost"`
|
||||||
|
MaxDeadline time.Time `db:"max_deadline" json:"max_deadline"`
|
||||||
|
TemplateVersionPresetID uuid.NullUUID `db:"template_version_preset_id" json:"template_version_preset_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WorkspaceProxy struct {
|
type WorkspaceProxy struct {
|
||||||
|
@ -5414,25 +5414,35 @@ WITH
|
|||||||
INNER JOIN template_version_presets tvp ON tvp.template_version_id = tv.id
|
INNER JOIN template_version_presets tvp ON tvp.template_version_id = tv.id
|
||||||
INNER JOIN template_version_preset_prebuilds tvpp ON tvpp.preset_id = tvp.id
|
INNER JOIN template_version_preset_prebuilds tvpp ON tvpp.preset_id = tvp.id
|
||||||
WHERE t.id = $1::uuid
|
WHERE t.id = $1::uuid
|
||||||
GROUP BY t.id, tv.id, tvpp.id)
|
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
|
||||||
|
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
|
||||||
|
WHERE pj.job_status NOT IN
|
||||||
|
('succeeded'::provisioner_job_status, 'canceled'::provisioner_job_status,
|
||||||
|
'failed'::provisioner_job_status))
|
||||||
SELECT t.template_id,
|
SELECT t.template_id,
|
||||||
COUNT(p.id) AS actual, -- running prebuilds for active version
|
CAST(COUNT(p.id) AS INT) AS actual, -- running prebuilds for active version
|
||||||
MAX(CASE WHEN t.using_active_version THEN t.desired_instances ELSE 0 END) AS desired, -- we only care about the active version's desired instances
|
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
|
||||||
SUM(CASE WHEN t.using_active_version THEN 0 ELSE 1 END) AS extraneous, -- running prebuilds for inactive version
|
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.deleted,
|
||||||
t.deprecated
|
t.deprecated
|
||||||
FROM templates_with_prebuilds t
|
FROM templates_with_prebuilds t
|
||||||
LEFT JOIN running_prebuilds p ON p.template_version_id = t.template_version_id
|
LEFT JOIN running_prebuilds p ON p.template_version_id = t.template_version_id
|
||||||
GROUP BY t.template_id, p.id, t.deleted, t.deprecated
|
LEFT JOIN prebuilds_in_progress pip ON pip.template_version_id = t.template_version_id
|
||||||
|
GROUP BY t.template_id, p.id, t.deleted, t.deprecated, pip.template_version_id
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetTemplatePrebuildStateRow struct {
|
type GetTemplatePrebuildStateRow struct {
|
||||||
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
||||||
Actual int64 `db:"actual" json:"actual"`
|
Actual int32 `db:"actual" json:"actual"`
|
||||||
Desired interface{} `db:"desired" json:"desired"`
|
Desired int32 `db:"desired" json:"desired"`
|
||||||
Extraneous int64 `db:"extraneous" json:"extraneous"`
|
Extraneous int32 `db:"extraneous" json:"extraneous"`
|
||||||
Deleted bool `db:"deleted" json:"deleted"`
|
InProgress int32 `db:"in_progress" json:"in_progress"`
|
||||||
Deprecated bool `db:"deprecated" json:"deprecated"`
|
Deleted bool `db:"deleted" json:"deleted"`
|
||||||
|
Deprecated bool `db:"deprecated" json:"deprecated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *sqlQuerier) GetTemplatePrebuildState(ctx context.Context, templateID uuid.UUID) ([]GetTemplatePrebuildStateRow, error) {
|
func (q *sqlQuerier) GetTemplatePrebuildState(ctx context.Context, templateID uuid.UUID) ([]GetTemplatePrebuildStateRow, error) {
|
||||||
@ -5449,6 +5459,7 @@ func (q *sqlQuerier) GetTemplatePrebuildState(ctx context.Context, templateID uu
|
|||||||
&i.Actual,
|
&i.Actual,
|
||||||
&i.Desired,
|
&i.Desired,
|
||||||
&i.Extraneous,
|
&i.Extraneous,
|
||||||
|
&i.InProgress,
|
||||||
&i.Deleted,
|
&i.Deleted,
|
||||||
&i.Deprecated,
|
&i.Deprecated,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
|
@ -17,13 +17,22 @@ WITH
|
|||||||
INNER JOIN template_version_presets tvp ON tvp.template_version_id = tv.id
|
INNER JOIN template_version_presets tvp ON tvp.template_version_id = tv.id
|
||||||
INNER JOIN template_version_preset_prebuilds tvpp ON tvpp.preset_id = tvp.id
|
INNER JOIN template_version_preset_prebuilds tvpp ON tvpp.preset_id = tvp.id
|
||||||
WHERE t.id = @template_id::uuid
|
WHERE t.id = @template_id::uuid
|
||||||
GROUP BY t.id, tv.id, tvpp.id)
|
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
|
||||||
|
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
|
||||||
|
WHERE pj.job_status NOT IN
|
||||||
|
('succeeded'::provisioner_job_status, 'canceled'::provisioner_job_status,
|
||||||
|
'failed'::provisioner_job_status))
|
||||||
SELECT t.template_id,
|
SELECT t.template_id,
|
||||||
COUNT(p.id) AS actual, -- running prebuilds for active version
|
CAST(COUNT(p.id) AS INT) AS actual, -- running prebuilds for active version
|
||||||
MAX(CASE WHEN t.using_active_version THEN t.desired_instances ELSE 0 END) AS desired, -- we only care about the active version's desired instances
|
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
|
||||||
SUM(CASE WHEN t.using_active_version THEN 0 ELSE 1 END) AS extraneous, -- running prebuilds for inactive version
|
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.deleted,
|
||||||
t.deprecated
|
t.deprecated
|
||||||
FROM templates_with_prebuilds t
|
FROM templates_with_prebuilds t
|
||||||
LEFT JOIN running_prebuilds p ON p.template_version_id = t.template_version_id
|
LEFT JOIN running_prebuilds p ON p.template_version_id = t.template_version_id
|
||||||
GROUP BY t.template_id, p.id, t.deleted, t.deprecated;
|
LEFT JOIN prebuilds_in_progress pip ON pip.template_version_id = t.template_version_id
|
||||||
|
GROUP BY t.template_id, p.id, t.deleted, t.deprecated, pip.template_version_id;
|
||||||
|
@ -3,6 +3,7 @@ package prebuilds
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"cdr.dev/slog"
|
"cdr.dev/slog"
|
||||||
@ -145,7 +146,7 @@ func (c Controller) reconcileTemplate(ctx context.Context, template database.Tem
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
desired, actual, extraneous := result.Desired, result.Actual, result.Extraneous
|
desired, actual, extraneous, inProgress := result.Desired, result.Actual, result.Extraneous, result.InProgress
|
||||||
|
|
||||||
// If the template has become deleted or deprecated since the last reconciliation, we need to ensure we
|
// If the template has become deleted or deprecated since the last reconciliation, we need to ensure we
|
||||||
// scale those prebuilds down to zero.
|
// scale those prebuilds down to zero.
|
||||||
@ -153,9 +154,14 @@ func (c Controller) reconcileTemplate(ctx context.Context, template database.Tem
|
|||||||
desired = 0
|
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))
|
||||||
|
|
||||||
c.logger.Info(innerCtx, "template prebuild state retrieved",
|
c.logger.Info(innerCtx, "template prebuild state retrieved",
|
||||||
slog.F("template_id", template.ID),
|
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("desired", desired), slog.F("actual", actual),
|
||||||
|
slog.F("extraneous", extraneous), slog.F("in_progress", inProgress))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
Reference in New Issue
Block a user