fix(coderd/database): improve task status in tasks_with_status view (#20683)

This change restructures the `tasks_with_status` view query to:

- Improve debuggability by adding a `status_debug` column to better
understand the outcome
- Reduce clutter from `bool_or`, `bool_and` which are aggregate
functions that did not actually have serve a purpose (each join is 0-1
rows)
- Improve agent lifecycle state coverage, `start_timeout` and
`start_error` were omitted
- These states are easy to trigger even in a perfectly functioning
workspace/task so we now rely on app health to report whether or not
there was an issue
- Mark canceling and canceled workspace build jobs as error state
- Agent stop states were implicitly `unknown`, now there are explicit (I
initially considered `error`, could go either way)
This commit is contained in:
Mathias Fredriksson
2025-11-14 19:52:26 +02:00
committed by GitHub
parent 6067aa3aa1
commit 1483fd11ff
7 changed files with 354 additions and 55 deletions
+36 -28
View File
@@ -1965,32 +1965,21 @@ CREATE VIEW tasks_with_status AS
tasks.created_at,
tasks.deleted_at,
CASE
WHEN ((tasks.workspace_id IS NULL) OR (latest_build.job_status IS NULL)) THEN 'pending'::task_status
WHEN (latest_build.job_status = 'failed'::provisioner_job_status) THEN 'error'::task_status
WHEN ((latest_build.transition = ANY (ARRAY['stop'::workspace_transition, 'delete'::workspace_transition])) AND (latest_build.job_status = 'succeeded'::provisioner_job_status)) THEN 'paused'::task_status
WHEN ((latest_build.transition = 'start'::workspace_transition) AND (latest_build.job_status = 'pending'::provisioner_job_status)) THEN 'initializing'::task_status
WHEN ((latest_build.transition = 'start'::workspace_transition) AND (latest_build.job_status = ANY (ARRAY['running'::provisioner_job_status, 'succeeded'::provisioner_job_status]))) THEN
CASE
WHEN agent_status."none" THEN 'initializing'::task_status
WHEN agent_status.connecting THEN 'initializing'::task_status
WHEN agent_status.connected THEN
CASE
WHEN app_status.any_unhealthy THEN 'error'::task_status
WHEN app_status.any_initializing THEN 'initializing'::task_status
WHEN app_status.all_healthy_or_disabled THEN 'active'::task_status
ELSE 'unknown'::task_status
END
ELSE 'unknown'::task_status
END
ELSE 'unknown'::task_status
WHEN (tasks.workspace_id IS NULL) THEN 'pending'::task_status
WHEN (build_status.status <> 'active'::task_status) THEN build_status.status
WHEN (agent_status.status <> 'active'::task_status) THEN agent_status.status
ELSE app_status.status
END AS 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.workspace_build_number,
task_app.workspace_agent_id,
task_app.workspace_app_id,
agent_raw.lifecycle_state AS workspace_agent_lifecycle_state,
app_raw.health AS workspace_app_health,
task_owner.owner_username,
task_owner.owner_name,
task_owner.owner_avatar_url
FROM (((((tasks
FROM ((((((((tasks
CROSS JOIN LATERAL ( SELECT vu.username AS owner_username,
vu.name AS owner_name,
vu.avatar_url AS owner_avatar_url
@@ -2008,17 +1997,36 @@ CREATE VIEW tasks_with_status AS
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 ON (true))
CROSS JOIN LATERAL ( SELECT (count(*) = 0) AS "none",
bool_or((workspace_agent.lifecycle_state = ANY (ARRAY['created'::workspace_agent_lifecycle_state, 'starting'::workspace_agent_lifecycle_state]))) AS connecting,
bool_and((workspace_agent.lifecycle_state = 'ready'::workspace_agent_lifecycle_state)) AS connected
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_status)
CROSS JOIN LATERAL ( SELECT bool_or((workspace_app.health = 'unhealthy'::workspace_app_health)) AS any_unhealthy,
bool_or((workspace_app.health = 'initializing'::workspace_app_health)) AS any_initializing,
bool_and((workspace_app.health = ANY (ARRAY['healthy'::workspace_app_health, 'disabled'::workspace_app_health]))) AS all_healthy_or_disabled
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_status)
WHERE (workspace_app.id = task_app.workspace_app_id)) app_raw ON (true))
CROSS JOIN LATERAL ( SELECT
CASE
WHEN (latest_build_raw.job_status IS NULL) THEN 'pending'::task_status
WHEN (latest_build_raw.job_status = ANY (ARRAY['failed'::provisioner_job_status, 'canceling'::provisioner_job_status, 'canceled'::provisioner_job_status])) THEN 'error'::task_status
WHEN ((latest_build_raw.transition = ANY (ARRAY['stop'::workspace_transition, 'delete'::workspace_transition])) AND (latest_build_raw.job_status = 'succeeded'::provisioner_job_status)) THEN 'paused'::task_status
WHEN ((latest_build_raw.transition = 'start'::workspace_transition) AND (latest_build_raw.job_status = 'pending'::provisioner_job_status)) THEN 'initializing'::task_status
WHEN ((latest_build_raw.transition = 'start'::workspace_transition) AND (latest_build_raw.job_status = ANY (ARRAY['running'::provisioner_job_status, 'succeeded'::provisioner_job_status]))) THEN 'active'::task_status
ELSE 'unknown'::task_status
END AS status) build_status)
CROSS JOIN LATERAL ( SELECT
CASE
WHEN ((agent_raw.lifecycle_state IS NULL) OR (agent_raw.lifecycle_state = ANY (ARRAY['created'::workspace_agent_lifecycle_state, 'starting'::workspace_agent_lifecycle_state]))) THEN 'initializing'::task_status
WHEN (agent_raw.lifecycle_state = ANY (ARRAY['ready'::workspace_agent_lifecycle_state, 'start_timeout'::workspace_agent_lifecycle_state, 'start_error'::workspace_agent_lifecycle_state])) THEN 'active'::task_status
WHEN (agent_raw.lifecycle_state <> ALL (ARRAY['created'::workspace_agent_lifecycle_state, 'starting'::workspace_agent_lifecycle_state, 'ready'::workspace_agent_lifecycle_state, 'start_timeout'::workspace_agent_lifecycle_state, 'start_error'::workspace_agent_lifecycle_state])) THEN 'unknown'::task_status
ELSE 'unknown'::task_status
END AS status) agent_status)
CROSS JOIN LATERAL ( SELECT
CASE
WHEN (app_raw.health = 'initializing'::workspace_app_health) THEN 'initializing'::task_status
WHEN (app_raw.health = 'unhealthy'::workspace_app_health) THEN 'error'::task_status
WHEN (app_raw.health = ANY (ARRAY['healthy'::workspace_app_health, 'disabled'::workspace_app_health])) THEN 'active'::task_status
ELSE 'unknown'::task_status
END AS status) app_status)
WHERE (tasks.deleted_at IS NULL);
CREATE TABLE telemetry_items (
@@ -0,0 +1,82 @@
-- Restore previous view.
DROP VIEW IF EXISTS tasks_with_status;
CREATE VIEW
tasks_with_status
AS
SELECT
tasks.*,
CASE
WHEN tasks.workspace_id IS NULL OR latest_build.job_status IS NULL THEN 'pending'::task_status
WHEN latest_build.job_status = 'failed' THEN 'error'::task_status
WHEN latest_build.transition IN ('stop', 'delete')
AND latest_build.job_status = 'succeeded' THEN 'paused'::task_status
WHEN latest_build.transition = 'start'
AND latest_build.job_status = 'pending' THEN 'initializing'::task_status
WHEN latest_build.transition = 'start' AND latest_build.job_status IN ('running', 'succeeded') THEN
CASE
WHEN agent_status.none THEN 'initializing'::task_status
WHEN agent_status.connecting THEN 'initializing'::task_status
WHEN agent_status.connected THEN
CASE
WHEN app_status.any_unhealthy THEN 'error'::task_status
WHEN app_status.any_initializing THEN 'initializing'::task_status
WHEN app_status.all_healthy_or_disabled THEN 'active'::task_status
ELSE 'unknown'::task_status
END
ELSE 'unknown'::task_status
END
ELSE 'unknown'::task_status
END AS status,
task_app.*,
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 workspace_build_number, workspace_agent_id, workspace_app_id
FROM task_workspace_apps task_app
WHERE task_id = tasks.id
ORDER BY workspace_build_number DESC
LIMIT 1
) task_app ON TRUE
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 ON TRUE
CROSS JOIN LATERAL (
SELECT
COUNT(*) = 0 AS none,
bool_or(workspace_agent.lifecycle_state IN ('created', 'starting')) AS connecting,
bool_and(workspace_agent.lifecycle_state = 'ready') AS connected
FROM workspace_agents workspace_agent
WHERE workspace_agent.id = task_app.workspace_agent_id
) agent_status
CROSS JOIN LATERAL (
SELECT
bool_or(workspace_app.health = 'unhealthy') AS any_unhealthy,
bool_or(workspace_app.health = 'initializing') AS any_initializing,
bool_and(workspace_app.health IN ('healthy', 'disabled')) AS all_healthy_or_disabled
FROM workspace_apps workspace_app
WHERE workspace_app.id = task_app.workspace_app_id
) app_status
WHERE
tasks.deleted_at IS NULL;
@@ -0,0 +1,142 @@
-- 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;
+20 -17
View File
@@ -4208,23 +4208,26 @@ type TailnetTunnel struct {
}
type Task struct {
ID uuid.UUID `db:"id" json:"id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
Name string `db:"name" json:"name"`
WorkspaceID uuid.NullUUID `db:"workspace_id" json:"workspace_id"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
TemplateParameters json.RawMessage `db:"template_parameters" json:"template_parameters"`
Prompt string `db:"prompt" json:"prompt"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
DeletedAt sql.NullTime `db:"deleted_at" json:"deleted_at"`
Status TaskStatus `db:"status" json:"status"`
WorkspaceBuildNumber sql.NullInt32 `db:"workspace_build_number" json:"workspace_build_number"`
WorkspaceAgentID uuid.NullUUID `db:"workspace_agent_id" json:"workspace_agent_id"`
WorkspaceAppID uuid.NullUUID `db:"workspace_app_id" json:"workspace_app_id"`
OwnerUsername string `db:"owner_username" json:"owner_username"`
OwnerName string `db:"owner_name" json:"owner_name"`
OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"`
ID uuid.UUID `db:"id" json:"id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
Name string `db:"name" json:"name"`
WorkspaceID uuid.NullUUID `db:"workspace_id" json:"workspace_id"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
TemplateParameters json.RawMessage `db:"template_parameters" json:"template_parameters"`
Prompt string `db:"prompt" json:"prompt"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
DeletedAt sql.NullTime `db:"deleted_at" json:"deleted_at"`
Status TaskStatus `db:"status" json:"status"`
StatusDebug json.RawMessage `db:"status_debug" json:"status_debug"`
WorkspaceBuildNumber sql.NullInt32 `db:"workspace_build_number" json:"workspace_build_number"`
WorkspaceAgentID uuid.NullUUID `db:"workspace_agent_id" json:"workspace_agent_id"`
WorkspaceAppID uuid.NullUUID `db:"workspace_app_id" json:"workspace_app_id"`
WorkspaceAgentLifecycleState NullWorkspaceAgentLifecycleState `db:"workspace_agent_lifecycle_state" json:"workspace_agent_lifecycle_state"`
WorkspaceAppHealth NullWorkspaceAppHealth `db:"workspace_app_health" json:"workspace_app_health"`
OwnerUsername string `db:"owner_username" json:"owner_username"`
OwnerName string `db:"owner_name" json:"owner_name"`
OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"`
}
type TaskTable struct {
+49 -6
View File
@@ -6664,6 +6664,23 @@ func TestTasksWithStatusView(t *testing.T) {
StartedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
CompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
}
case database.ProvisionerJobStatusCanceling:
jobParams = database.ProvisionerJob{
OrganizationID: org.ID,
Type: database.ProvisionerJobTypeWorkspaceBuild,
InitiatorID: user.ID,
StartedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
CanceledAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
}
case database.ProvisionerJobStatusCanceled:
jobParams = database.ProvisionerJob{
OrganizationID: org.ID,
Type: database.ProvisionerJobTypeWorkspaceBuild,
InitiatorID: user.ID,
StartedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
CompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
CanceledAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
}
default:
t.Errorf("invalid build status: %v", buildStatus)
}
@@ -6816,6 +6833,28 @@ func TestTasksWithStatusView(t *testing.T) {
expectWorkspaceAgentValid: false,
expectWorkspaceAppValid: false,
},
{
name: "CancelingBuild",
buildStatus: database.ProvisionerJobStatusCanceling,
buildTransition: database.WorkspaceTransitionStart,
expectedStatus: database.TaskStatusError,
description: "Latest workspace build is canceling",
expectBuildNumberValid: true,
expectBuildNumber: 1,
expectWorkspaceAgentValid: false,
expectWorkspaceAppValid: false,
},
{
name: "CanceledBuild",
buildStatus: database.ProvisionerJobStatusCanceled,
buildTransition: database.WorkspaceTransitionStart,
expectedStatus: database.TaskStatusError,
description: "Latest workspace build was canceled",
expectBuildNumberValid: true,
expectBuildNumber: 1,
expectWorkspaceAgentValid: false,
expectWorkspaceAppValid: false,
},
{
name: "StoppedWorkspace",
buildStatus: database.ProvisionerJobStatusSucceeded,
@@ -6943,24 +6982,26 @@ func TestTasksWithStatusView(t *testing.T) {
buildStatus: database.ProvisionerJobStatusSucceeded,
buildTransition: database.WorkspaceTransitionStart,
agentState: database.WorkspaceAgentLifecycleStateStartTimeout,
expectedStatus: database.TaskStatusUnknown,
description: "Agent start timed out",
appHealths: []database.WorkspaceAppHealth{database.WorkspaceAppHealthHealthy},
expectedStatus: database.TaskStatusActive,
description: "Agent start timed out but app is healthy, defer to app",
expectBuildNumberValid: true,
expectBuildNumber: 1,
expectWorkspaceAgentValid: true,
expectWorkspaceAppValid: false,
expectWorkspaceAppValid: true,
},
{
name: "AgentStartError",
buildStatus: database.ProvisionerJobStatusSucceeded,
buildTransition: database.WorkspaceTransitionStart,
agentState: database.WorkspaceAgentLifecycleStateStartError,
expectedStatus: database.TaskStatusUnknown,
description: "Agent failed to start",
appHealths: []database.WorkspaceAppHealth{database.WorkspaceAppHealthHealthy},
expectedStatus: database.TaskStatusActive,
description: "Agent start failed but app is healthy, defer to app",
expectBuildNumberValid: true,
expectBuildNumber: 1,
expectWorkspaceAgentValid: true,
expectWorkspaceAppValid: false,
expectWorkspaceAppValid: true,
},
{
name: "AgentShuttingDown",
@@ -7081,6 +7122,8 @@ func TestTasksWithStatusView(t *testing.T) {
got, err := db.GetTaskByID(ctx, task.ID)
require.NoError(t, err)
t.Logf("Task status debug: %s", got.StatusDebug)
require.Equal(t, tt.expectedStatus, got.Status)
require.Equal(t, tt.expectBuildNumberValid, got.WorkspaceBuildNumber.Valid)
+16 -4
View File
@@ -13072,7 +13072,7 @@ func (q *sqlQuerier) DeleteTask(ctx context.Context, arg DeleteTaskParams) (Task
}
const getTaskByID = `-- name: GetTaskByID :one
SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, workspace_build_number, workspace_agent_id, workspace_app_id, owner_username, owner_name, owner_avatar_url FROM tasks_with_status WHERE id = $1::uuid
SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, status_debug, workspace_build_number, workspace_agent_id, workspace_app_id, workspace_agent_lifecycle_state, workspace_app_health, owner_username, owner_name, owner_avatar_url FROM tasks_with_status WHERE id = $1::uuid
`
func (q *sqlQuerier) GetTaskByID(ctx context.Context, id uuid.UUID) (Task, error) {
@@ -13090,9 +13090,12 @@ func (q *sqlQuerier) GetTaskByID(ctx context.Context, id uuid.UUID) (Task, error
&i.CreatedAt,
&i.DeletedAt,
&i.Status,
&i.StatusDebug,
&i.WorkspaceBuildNumber,
&i.WorkspaceAgentID,
&i.WorkspaceAppID,
&i.WorkspaceAgentLifecycleState,
&i.WorkspaceAppHealth,
&i.OwnerUsername,
&i.OwnerName,
&i.OwnerAvatarUrl,
@@ -13101,7 +13104,7 @@ func (q *sqlQuerier) GetTaskByID(ctx context.Context, id uuid.UUID) (Task, error
}
const getTaskByOwnerIDAndName = `-- name: GetTaskByOwnerIDAndName :one
SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, workspace_build_number, workspace_agent_id, workspace_app_id, owner_username, owner_name, owner_avatar_url FROM tasks_with_status
SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, status_debug, workspace_build_number, workspace_agent_id, workspace_app_id, workspace_agent_lifecycle_state, workspace_app_health, owner_username, owner_name, owner_avatar_url FROM tasks_with_status
WHERE
owner_id = $1::uuid
AND deleted_at IS NULL
@@ -13128,9 +13131,12 @@ func (q *sqlQuerier) GetTaskByOwnerIDAndName(ctx context.Context, arg GetTaskByO
&i.CreatedAt,
&i.DeletedAt,
&i.Status,
&i.StatusDebug,
&i.WorkspaceBuildNumber,
&i.WorkspaceAgentID,
&i.WorkspaceAppID,
&i.WorkspaceAgentLifecycleState,
&i.WorkspaceAppHealth,
&i.OwnerUsername,
&i.OwnerName,
&i.OwnerAvatarUrl,
@@ -13139,7 +13145,7 @@ func (q *sqlQuerier) GetTaskByOwnerIDAndName(ctx context.Context, arg GetTaskByO
}
const getTaskByWorkspaceID = `-- name: GetTaskByWorkspaceID :one
SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, workspace_build_number, workspace_agent_id, workspace_app_id, owner_username, owner_name, owner_avatar_url FROM tasks_with_status WHERE workspace_id = $1::uuid
SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, status_debug, workspace_build_number, workspace_agent_id, workspace_app_id, workspace_agent_lifecycle_state, workspace_app_health, owner_username, owner_name, owner_avatar_url FROM tasks_with_status WHERE workspace_id = $1::uuid
`
func (q *sqlQuerier) GetTaskByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (Task, error) {
@@ -13157,9 +13163,12 @@ func (q *sqlQuerier) GetTaskByWorkspaceID(ctx context.Context, workspaceID uuid.
&i.CreatedAt,
&i.DeletedAt,
&i.Status,
&i.StatusDebug,
&i.WorkspaceBuildNumber,
&i.WorkspaceAgentID,
&i.WorkspaceAppID,
&i.WorkspaceAgentLifecycleState,
&i.WorkspaceAppHealth,
&i.OwnerUsername,
&i.OwnerName,
&i.OwnerAvatarUrl,
@@ -13216,7 +13225,7 @@ func (q *sqlQuerier) InsertTask(ctx context.Context, arg InsertTaskParams) (Task
}
const listTasks = `-- name: ListTasks :many
SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, workspace_build_number, workspace_agent_id, workspace_app_id, owner_username, owner_name, owner_avatar_url FROM tasks_with_status tws
SELECT id, organization_id, owner_id, name, workspace_id, template_version_id, template_parameters, prompt, created_at, deleted_at, status, status_debug, workspace_build_number, workspace_agent_id, workspace_app_id, workspace_agent_lifecycle_state, workspace_app_health, owner_username, owner_name, owner_avatar_url FROM tasks_with_status tws
WHERE tws.deleted_at IS NULL
AND CASE WHEN $1::UUID != '00000000-0000-0000-0000-000000000000' THEN tws.owner_id = $1::UUID ELSE TRUE END
AND CASE WHEN $2::UUID != '00000000-0000-0000-0000-000000000000' THEN tws.organization_id = $2::UUID ELSE TRUE END
@@ -13251,9 +13260,12 @@ func (q *sqlQuerier) ListTasks(ctx context.Context, arg ListTasksParams) ([]Task
&i.CreatedAt,
&i.DeletedAt,
&i.Status,
&i.StatusDebug,
&i.WorkspaceBuildNumber,
&i.WorkspaceAgentID,
&i.WorkspaceAppID,
&i.WorkspaceAgentLifecycleState,
&i.WorkspaceAppHealth,
&i.OwnerUsername,
&i.OwnerName,
&i.OwnerAvatarUrl,
+9
View File
@@ -106,6 +106,15 @@ sql:
# Workaround for sqlc not interpreting the left join correctly.
- column: "tasks_with_status.workspace_build_number"
go_type: "database/sql.NullInt32"
- column: "tasks_with_status.status"
go_type:
type: "TaskStatus"
- column: "tasks_with_status.workspace_agent_lifecycle_state"
go_type:
type: "NullWorkspaceAgentLifecycleState"
- column: "tasks_with_status.workspace_app_health"
go_type:
type: "NullWorkspaceAppHealth"
rename:
group_member: GroupMemberTable
group_members_expanded: GroupMember