mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: implement reconciliation loop (#17261)
Closes https://github.com/coder/internal/issues/510 <details> <summary> Refactoring Summary </summary> ### 1) `CalculateActions` Function #### Issues Before Refactoring: - Large function (~150 lines), making it difficult to read and maintain. - The control flow is hard to follow due to complex conditional logic. - The `ReconciliationActions` struct was partially initialized early, then mutated in multiple places, making the flow error-prone. Original source: https://github.com/coder/coder/blob/fe60b569ad754245e28bac71e0ef3c83536631bb/coderd/prebuilds/state.go#L13-L167 #### Improvements After Refactoring: - Simplified and broken down into smaller, focused helper methods. - The flow of the function is now more linear and easier to understand. - Struct initialization is cleaner, avoiding partial and incremental mutations. Refactored function: https://github.com/coder/coder/blob/eeb0407d783cdda71ec2418c113f325542c47b1c/coderd/prebuilds/state.go#L67-L84 --- ### 2) `ReconciliationActions` Struct #### Issues Before Refactoring: - The struct mixed both actionable decisions and diagnostic state, which blurred its purpose. - It was unclear which fields were necessary for reconciliation logic, and which were purely for logging/observability. #### Improvements After Refactoring: - Split into two clear, purpose-specific structs: - **`ReconciliationActions`** — defines the intended reconciliation action. - **`ReconciliationState`** — captures runtime state and metadata, primarily for logging and diagnostics. Original struct: https://github.com/coder/coder/blob/fe60b569ad754245e28bac71e0ef3c83536631bb/coderd/prebuilds/reconcile.go#L29-L41 </details> --------- Signed-off-by: Danny Kopping <dannykopping@gmail.com> Co-authored-by: Sas Swart <sas.swart.cdk@gmail.com> Co-authored-by: Danny Kopping <dannykopping@gmail.com> Co-authored-by: Dean Sheather <dean@deansheather.com> Co-authored-by: Spike Curtis <spike@coder.com> Co-authored-by: Danny Kopping <danny@coder.com>
This commit is contained in:
co-authored by
Sas Swart
Danny Kopping
Dean Sheather
Spike Curtis
Danny Kopping
parent
6a79965948
commit
27bc60d1b9
@@ -12,8 +12,7 @@ const (
|
||||
LockIDDBPurge
|
||||
LockIDNotificationsReportGenerator
|
||||
LockIDCryptoKeyRotation
|
||||
LockIDReconcileTemplatePrebuilds
|
||||
LockIDDeterminePrebuildsState
|
||||
LockIDReconcilePrebuilds
|
||||
)
|
||||
|
||||
// GenLockID generates a unique and consistent lock ID from a given string.
|
||||
|
||||
@@ -64,7 +64,7 @@ type sqlcQuerier interface {
|
||||
CleanTailnetCoordinators(ctx context.Context) error
|
||||
CleanTailnetLostPeers(ctx context.Context) error
|
||||
CleanTailnetTunnels(ctx context.Context) error
|
||||
// CountInProgressPrebuilds returns the number of in-progress prebuilds, grouped by template version ID and transition.
|
||||
// CountInProgressPrebuilds returns the number of in-progress prebuilds, grouped by preset ID and transition.
|
||||
// Prebuild considered in-progress if it's in the "starting", "stopping", or "deleting" state.
|
||||
CountInProgressPrebuilds(ctx context.Context) ([]CountInProgressPrebuildsRow, error)
|
||||
CountUnreadInboxNotificationsByUserID(ctx context.Context, userID uuid.UUID) (int64, error)
|
||||
|
||||
@@ -5938,7 +5938,7 @@ func (q *sqlQuerier) ClaimPrebuiltWorkspace(ctx context.Context, arg ClaimPrebui
|
||||
}
|
||||
|
||||
const countInProgressPrebuilds = `-- name: CountInProgressPrebuilds :many
|
||||
SELECT t.id AS template_id, wpb.template_version_id, wpb.transition, COUNT(wpb.transition)::int AS count
|
||||
SELECT t.id AS template_id, wpb.template_version_id, wpb.transition, COUNT(wpb.transition)::int AS count, wlb.template_version_preset_id as preset_id
|
||||
FROM workspace_latest_builds wlb
|
||||
INNER JOIN workspace_prebuild_builds wpb ON wpb.id = wlb.id
|
||||
-- We only need these counts for active template versions.
|
||||
@@ -5949,7 +5949,7 @@ FROM workspace_latest_builds wlb
|
||||
-- prebuilds that are still building.
|
||||
INNER JOIN templates t ON t.active_version_id = wlb.template_version_id
|
||||
WHERE wlb.job_status IN ('pending'::provisioner_job_status, 'running'::provisioner_job_status)
|
||||
GROUP BY t.id, wpb.template_version_id, wpb.transition
|
||||
GROUP BY t.id, wpb.template_version_id, wpb.transition, wlb.template_version_preset_id
|
||||
`
|
||||
|
||||
type CountInProgressPrebuildsRow struct {
|
||||
@@ -5957,9 +5957,10 @@ type CountInProgressPrebuildsRow struct {
|
||||
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
|
||||
Transition WorkspaceTransition `db:"transition" json:"transition"`
|
||||
Count int32 `db:"count" json:"count"`
|
||||
PresetID uuid.NullUUID `db:"preset_id" json:"preset_id"`
|
||||
}
|
||||
|
||||
// CountInProgressPrebuilds returns the number of in-progress prebuilds, grouped by template version ID and transition.
|
||||
// CountInProgressPrebuilds returns the number of in-progress prebuilds, grouped by preset ID and transition.
|
||||
// Prebuild considered in-progress if it's in the "starting", "stopping", or "deleting" state.
|
||||
func (q *sqlQuerier) CountInProgressPrebuilds(ctx context.Context) ([]CountInProgressPrebuildsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, countInProgressPrebuilds)
|
||||
@@ -5975,6 +5976,7 @@ func (q *sqlQuerier) CountInProgressPrebuilds(ctx context.Context) ([]CountInPro
|
||||
&i.TemplateVersionID,
|
||||
&i.Transition,
|
||||
&i.Count,
|
||||
&i.PresetID,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -57,9 +57,9 @@ WHERE (b.transition = 'start'::workspace_transition
|
||||
AND b.job_status = 'succeeded'::provisioner_job_status);
|
||||
|
||||
-- name: CountInProgressPrebuilds :many
|
||||
-- CountInProgressPrebuilds returns the number of in-progress prebuilds, grouped by template version ID and transition.
|
||||
-- CountInProgressPrebuilds returns the number of in-progress prebuilds, grouped by preset ID and transition.
|
||||
-- Prebuild considered in-progress if it's in the "starting", "stopping", or "deleting" state.
|
||||
SELECT t.id AS template_id, wpb.template_version_id, wpb.transition, COUNT(wpb.transition)::int AS count
|
||||
SELECT t.id AS template_id, wpb.template_version_id, wpb.transition, COUNT(wpb.transition)::int AS count, wlb.template_version_preset_id as preset_id
|
||||
FROM workspace_latest_builds wlb
|
||||
INNER JOIN workspace_prebuild_builds wpb ON wpb.id = wlb.id
|
||||
-- We only need these counts for active template versions.
|
||||
@@ -70,7 +70,7 @@ FROM workspace_latest_builds wlb
|
||||
-- prebuilds that are still building.
|
||||
INNER JOIN templates t ON t.active_version_id = wlb.template_version_id
|
||||
WHERE wlb.job_status IN ('pending'::provisioner_job_status, 'running'::provisioner_job_status)
|
||||
GROUP BY t.id, wpb.template_version_id, wpb.transition;
|
||||
GROUP BY t.id, wpb.template_version_id, wpb.transition, wlb.template_version_preset_id;
|
||||
|
||||
-- GetPresetsBackoff groups workspace builds by preset ID.
|
||||
-- Each preset is associated with exactly one template version ID.
|
||||
|
||||
Reference in New Issue
Block a user