Skip to content

Commit 2bd6c7e

Browse files
authored
Merge branch 'main' into pb/terraform-install-test-flake-2
2 parents e4fc1c8 + 1483fd1 commit 2bd6c7e

File tree

8 files changed

+355
-56
lines changed

8 files changed

+355
-56
lines changed

coderd/database/dump.sql

Lines changed: 36 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
-- Restore previous view.
2+
DROP VIEW IF EXISTS tasks_with_status;
3+
4+
CREATE VIEW
5+
tasks_with_status
6+
AS
7+
SELECT
8+
tasks.*,
9+
CASE
10+
WHEN tasks.workspace_id IS NULL OR latest_build.job_status IS NULL THEN 'pending'::task_status
11+
12+
WHEN latest_build.job_status = 'failed' THEN 'error'::task_status
13+
14+
WHEN latest_build.transition IN ('stop', 'delete')
15+
AND latest_build.job_status = 'succeeded' THEN 'paused'::task_status
16+
17+
WHEN latest_build.transition = 'start'
18+
AND latest_build.job_status = 'pending' THEN 'initializing'::task_status
19+
20+
WHEN latest_build.transition = 'start' AND latest_build.job_status IN ('running', 'succeeded') THEN
21+
CASE
22+
WHEN agent_status.none THEN 'initializing'::task_status
23+
WHEN agent_status.connecting THEN 'initializing'::task_status
24+
WHEN agent_status.connected THEN
25+
CASE
26+
WHEN app_status.any_unhealthy THEN 'error'::task_status
27+
WHEN app_status.any_initializing THEN 'initializing'::task_status
28+
WHEN app_status.all_healthy_or_disabled THEN 'active'::task_status
29+
ELSE 'unknown'::task_status
30+
END
31+
ELSE 'unknown'::task_status
32+
END
33+
34+
ELSE 'unknown'::task_status
35+
END AS status,
36+
task_app.*,
37+
task_owner.*
38+
FROM
39+
tasks
40+
CROSS JOIN LATERAL (
41+
SELECT
42+
vu.username AS owner_username,
43+
vu.name AS owner_name,
44+
vu.avatar_url AS owner_avatar_url
45+
FROM visible_users vu
46+
WHERE vu.id = tasks.owner_id
47+
) task_owner
48+
LEFT JOIN LATERAL (
49+
SELECT workspace_build_number, workspace_agent_id, workspace_app_id
50+
FROM task_workspace_apps task_app
51+
WHERE task_id = tasks.id
52+
ORDER BY workspace_build_number DESC
53+
LIMIT 1
54+
) task_app ON TRUE
55+
LEFT JOIN LATERAL (
56+
SELECT
57+
workspace_build.transition,
58+
provisioner_job.job_status,
59+
workspace_build.job_id
60+
FROM workspace_builds workspace_build
61+
JOIN provisioner_jobs provisioner_job ON provisioner_job.id = workspace_build.job_id
62+
WHERE workspace_build.workspace_id = tasks.workspace_id
63+
AND workspace_build.build_number = task_app.workspace_build_number
64+
) latest_build ON TRUE
65+
CROSS JOIN LATERAL (
66+
SELECT
67+
COUNT(*) = 0 AS none,
68+
bool_or(workspace_agent.lifecycle_state IN ('created', 'starting')) AS connecting,
69+
bool_and(workspace_agent.lifecycle_state = 'ready') AS connected
70+
FROM workspace_agents workspace_agent
71+
WHERE workspace_agent.id = task_app.workspace_agent_id
72+
) agent_status
73+
CROSS JOIN LATERAL (
74+
SELECT
75+
bool_or(workspace_app.health = 'unhealthy') AS any_unhealthy,
76+
bool_or(workspace_app.health = 'initializing') AS any_initializing,
77+
bool_and(workspace_app.health IN ('healthy', 'disabled')) AS all_healthy_or_disabled
78+
FROM workspace_apps workspace_app
79+
WHERE workspace_app.id = task_app.workspace_app_id
80+
) app_status
81+
WHERE
82+
tasks.deleted_at IS NULL;
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
-- Update task status in view.
2+
DROP VIEW IF EXISTS tasks_with_status;
3+
4+
CREATE VIEW
5+
tasks_with_status
6+
AS
7+
SELECT
8+
tasks.*,
9+
-- Combine component statuses with precedence: build -> agent -> app.
10+
CASE
11+
WHEN tasks.workspace_id IS NULL THEN 'pending'::task_status
12+
WHEN build_status.status != 'active' THEN build_status.status::task_status
13+
WHEN agent_status.status != 'active' THEN agent_status.status::task_status
14+
ELSE app_status.status::task_status
15+
END AS status,
16+
-- Attach debug information for troubleshooting status.
17+
jsonb_build_object(
18+
'build', jsonb_build_object(
19+
'transition', latest_build_raw.transition,
20+
'job_status', latest_build_raw.job_status,
21+
'computed', build_status.status
22+
),
23+
'agent', jsonb_build_object(
24+
'lifecycle_state', agent_raw.lifecycle_state,
25+
'computed', agent_status.status
26+
),
27+
'app', jsonb_build_object(
28+
'health', app_raw.health,
29+
'computed', app_status.status
30+
)
31+
) AS status_debug,
32+
task_app.*,
33+
agent_raw.lifecycle_state AS workspace_agent_lifecycle_state,
34+
app_raw.health AS workspace_app_health,
35+
task_owner.*
36+
FROM
37+
tasks
38+
CROSS JOIN LATERAL (
39+
SELECT
40+
vu.username AS owner_username,
41+
vu.name AS owner_name,
42+
vu.avatar_url AS owner_avatar_url
43+
FROM
44+
visible_users vu
45+
WHERE
46+
vu.id = tasks.owner_id
47+
) task_owner
48+
LEFT JOIN LATERAL (
49+
SELECT
50+
task_app.workspace_build_number,
51+
task_app.workspace_agent_id,
52+
task_app.workspace_app_id
53+
FROM
54+
task_workspace_apps task_app
55+
WHERE
56+
task_id = tasks.id
57+
ORDER BY
58+
task_app.workspace_build_number DESC
59+
LIMIT 1
60+
) task_app ON TRUE
61+
62+
-- Join the raw data for computing task status.
63+
LEFT JOIN LATERAL (
64+
SELECT
65+
workspace_build.transition,
66+
provisioner_job.job_status,
67+
workspace_build.job_id
68+
FROM
69+
workspace_builds workspace_build
70+
JOIN
71+
provisioner_jobs provisioner_job
72+
ON provisioner_job.id = workspace_build.job_id
73+
WHERE
74+
workspace_build.workspace_id = tasks.workspace_id
75+
AND workspace_build.build_number = task_app.workspace_build_number
76+
) latest_build_raw ON TRUE
77+
LEFT JOIN LATERAL (
78+
SELECT
79+
workspace_agent.lifecycle_state
80+
FROM
81+
workspace_agents workspace_agent
82+
WHERE
83+
workspace_agent.id = task_app.workspace_agent_id
84+
) agent_raw ON TRUE
85+
LEFT JOIN LATERAL (
86+
SELECT
87+
workspace_app.health
88+
FROM
89+
workspace_apps workspace_app
90+
WHERE
91+
workspace_app.id = task_app.workspace_app_id
92+
) app_raw ON TRUE
93+
94+
-- Compute the status for each component.
95+
CROSS JOIN LATERAL (
96+
SELECT
97+
CASE
98+
WHEN latest_build_raw.job_status IS NULL THEN 'pending'::task_status
99+
WHEN latest_build_raw.job_status IN ('failed', 'canceling', 'canceled') THEN 'error'::task_status
100+
WHEN
101+
latest_build_raw.transition IN ('stop', 'delete')
102+
AND latest_build_raw.job_status = 'succeeded' THEN 'paused'::task_status
103+
WHEN
104+
latest_build_raw.transition = 'start'
105+
AND latest_build_raw.job_status = 'pending' THEN 'initializing'::task_status
106+
-- Build is running or done, defer to agent/app status.
107+
WHEN
108+
latest_build_raw.transition = 'start'
109+
AND latest_build_raw.job_status IN ('running', 'succeeded') THEN 'active'::task_status
110+
ELSE 'unknown'::task_status
111+
END AS status
112+
) build_status
113+
CROSS JOIN LATERAL (
114+
SELECT
115+
CASE
116+
-- No agent or connecting.
117+
WHEN
118+
agent_raw.lifecycle_state IS NULL
119+
OR agent_raw.lifecycle_state IN ('created', 'starting') THEN 'initializing'::task_status
120+
-- Agent is running, defer to app status.
121+
-- NOTE(mafredri): The start_error/start_timeout states means connected, but some startup script failed.
122+
-- This may or may not affect the task status but this has to be caught by app health check.
123+
WHEN agent_raw.lifecycle_state IN ('ready', 'start_timeout', 'start_error') THEN 'active'::task_status
124+
-- If the agent is shutting down or turned off, this is an unknown state because we would expect a stop
125+
-- build to be running.
126+
-- This is essentially equal to: `IN ('shutting_down', 'shutdown_timeout', 'shutdown_error', 'off')`,
127+
-- but we cannot use them because the values were added in a migration.
128+
WHEN agent_raw.lifecycle_state NOT IN ('created', 'starting', 'ready', 'start_timeout', 'start_error') THEN 'unknown'::task_status
129+
ELSE 'unknown'::task_status
130+
END AS status
131+
) agent_status
132+
CROSS JOIN LATERAL (
133+
SELECT
134+
CASE
135+
WHEN app_raw.health = 'initializing' THEN 'initializing'::task_status
136+
WHEN app_raw.health = 'unhealthy' THEN 'error'::task_status
137+
WHEN app_raw.health IN ('healthy', 'disabled') THEN 'active'::task_status
138+
ELSE 'unknown'::task_status
139+
END AS status
140+
) app_status
141+
WHERE
142+
tasks.deleted_at IS NULL;

coderd/database/models.go

Lines changed: 20 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)