mirror of
https://github.com/coder/coder.git
synced 2026-06-03 04:58:23 +00:00
96695edfed
Previously, tasks with pending provisioner jobs (not yet picked up) were incorrectly reported as "initializing". Refs #21887
143 lines
4.6 KiB
SQL
143 lines
4.6 KiB
SQL
-- Update task status in view.
|
|
DROP VIEW IF EXISTS tasks_with_status;
|
|
|
|
CREATE VIEW
|
|
tasks_with_status
|
|
AS
|
|
SELECT
|
|
tasks.*,
|
|
-- Combine component statuses with precedence: build -> agent -> app.
|
|
CASE
|
|
WHEN tasks.workspace_id IS NULL THEN 'pending'::task_status
|
|
WHEN build_status.status != 'active' THEN build_status.status::task_status
|
|
WHEN agent_status.status != 'active' THEN agent_status.status::task_status
|
|
ELSE app_status.status::task_status
|
|
END AS status,
|
|
-- Attach debug information for troubleshooting status.
|
|
jsonb_build_object(
|
|
'build', jsonb_build_object(
|
|
'transition', latest_build_raw.transition,
|
|
'job_status', latest_build_raw.job_status,
|
|
'computed', build_status.status
|
|
),
|
|
'agent', jsonb_build_object(
|
|
'lifecycle_state', agent_raw.lifecycle_state,
|
|
'computed', agent_status.status
|
|
),
|
|
'app', jsonb_build_object(
|
|
'health', app_raw.health,
|
|
'computed', app_status.status
|
|
)
|
|
) AS status_debug,
|
|
task_app.*,
|
|
agent_raw.lifecycle_state AS workspace_agent_lifecycle_state,
|
|
app_raw.health AS workspace_app_health,
|
|
task_owner.*
|
|
FROM
|
|
tasks
|
|
CROSS JOIN LATERAL (
|
|
SELECT
|
|
vu.username AS owner_username,
|
|
vu.name AS owner_name,
|
|
vu.avatar_url AS owner_avatar_url
|
|
FROM
|
|
visible_users vu
|
|
WHERE
|
|
vu.id = tasks.owner_id
|
|
) task_owner
|
|
LEFT JOIN LATERAL (
|
|
SELECT
|
|
task_app.workspace_build_number,
|
|
task_app.workspace_agent_id,
|
|
task_app.workspace_app_id
|
|
FROM
|
|
task_workspace_apps task_app
|
|
WHERE
|
|
task_id = tasks.id
|
|
ORDER BY
|
|
task_app.workspace_build_number DESC
|
|
LIMIT 1
|
|
) task_app ON TRUE
|
|
|
|
-- Join the raw data for computing task status.
|
|
LEFT JOIN LATERAL (
|
|
SELECT
|
|
workspace_build.transition,
|
|
provisioner_job.job_status,
|
|
workspace_build.job_id
|
|
FROM
|
|
workspace_builds workspace_build
|
|
JOIN
|
|
provisioner_jobs provisioner_job
|
|
ON provisioner_job.id = workspace_build.job_id
|
|
WHERE
|
|
workspace_build.workspace_id = tasks.workspace_id
|
|
AND workspace_build.build_number = task_app.workspace_build_number
|
|
) latest_build_raw ON TRUE
|
|
LEFT JOIN LATERAL (
|
|
SELECT
|
|
workspace_agent.lifecycle_state
|
|
FROM
|
|
workspace_agents workspace_agent
|
|
WHERE
|
|
workspace_agent.id = task_app.workspace_agent_id
|
|
) agent_raw ON TRUE
|
|
LEFT JOIN LATERAL (
|
|
SELECT
|
|
workspace_app.health
|
|
FROM
|
|
workspace_apps workspace_app
|
|
WHERE
|
|
workspace_app.id = task_app.workspace_app_id
|
|
) app_raw ON TRUE
|
|
|
|
-- Compute the status for each component.
|
|
CROSS JOIN LATERAL (
|
|
SELECT
|
|
CASE
|
|
WHEN latest_build_raw.job_status IS NULL THEN 'pending'::task_status
|
|
WHEN latest_build_raw.job_status IN ('failed', 'canceling', 'canceled') THEN 'error'::task_status
|
|
WHEN
|
|
latest_build_raw.transition IN ('stop', 'delete')
|
|
AND latest_build_raw.job_status = 'succeeded' THEN 'paused'::task_status
|
|
WHEN
|
|
latest_build_raw.transition = 'start'
|
|
AND latest_build_raw.job_status = 'pending' THEN 'initializing'::task_status
|
|
-- Build is running or done, defer to agent/app status.
|
|
WHEN
|
|
latest_build_raw.transition = 'start'
|
|
AND latest_build_raw.job_status IN ('running', 'succeeded') THEN 'active'::task_status
|
|
ELSE 'unknown'::task_status
|
|
END AS status
|
|
) build_status
|
|
CROSS JOIN LATERAL (
|
|
SELECT
|
|
CASE
|
|
-- No agent or connecting.
|
|
WHEN
|
|
agent_raw.lifecycle_state IS NULL
|
|
OR agent_raw.lifecycle_state IN ('created', 'starting') THEN 'initializing'::task_status
|
|
-- Agent is running, defer to app status.
|
|
-- NOTE(mafredri): The start_error/start_timeout states means connected, but some startup script failed.
|
|
-- This may or may not affect the task status but this has to be caught by app health check.
|
|
WHEN agent_raw.lifecycle_state IN ('ready', 'start_timeout', 'start_error') THEN 'active'::task_status
|
|
-- If the agent is shutting down or turned off, this is an unknown state because we would expect a stop
|
|
-- build to be running.
|
|
-- This is essentially equal to: `IN ('shutting_down', 'shutdown_timeout', 'shutdown_error', 'off')`,
|
|
-- but we cannot use them because the values were added in a migration.
|
|
WHEN agent_raw.lifecycle_state NOT IN ('created', 'starting', 'ready', 'start_timeout', 'start_error') THEN 'unknown'::task_status
|
|
ELSE 'unknown'::task_status
|
|
END AS status
|
|
) agent_status
|
|
CROSS JOIN LATERAL (
|
|
SELECT
|
|
CASE
|
|
WHEN app_raw.health = 'initializing' THEN 'initializing'::task_status
|
|
WHEN app_raw.health = 'unhealthy' THEN 'error'::task_status
|
|
WHEN app_raw.health IN ('healthy', 'disabled') THEN 'active'::task_status
|
|
ELSE 'unknown'::task_status
|
|
END AS status
|
|
) app_status
|
|
WHERE
|
|
tasks.deleted_at IS NULL;
|