From d3b9385c90102d96fe948b2608455c0b8ad86eff Mon Sep 17 00:00:00 2001 From: Louis Knight-Webb Date: Fri, 4 Jul 2025 14:01:51 +0100 Subject: [PATCH] Fixed! The issue was in the SQL query in [`backend/src/models/task.rs`](file:///private/var/folders/kr/jdxkcn7129j376nrg0stj9zm0000gn/T/vk-d725-failed-att/backend/src/models/task.rs#L134-L169). The `failed_attempts` subquery was checking for ANY failed attempt, but now it: (#73) 1. First gets the latest attempt for each task (using `ROW_NUMBER() OVER (PARTITION BY task_id ORDER BY created_at DESC)`) 2. Only considers non-merged attempts (`WHERE merge_commit IS NULL`) 3. Only shows the failed indicator if the latest attempt has failed Now the red circle cross will only appear for tasks where the most recent attempt failed, not for any task that has ever had a failed attempt. --- ...61205da09c67a18907bbf562b6177f8bc8bc0bc.json} | 4 ++-- backend/src/models/task.rs | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) rename backend/.sqlx/{query-b7d9fc7198a30ad4e88d7cdd7b59a1a73018de16506003622cd7f779028c0fa8.json => query-9c615a14edb0886be82b9004961205da09c67a18907bbf562b6177f8bc8bc0bc.json} (66%) diff --git a/backend/.sqlx/query-b7d9fc7198a30ad4e88d7cdd7b59a1a73018de16506003622cd7f779028c0fa8.json b/backend/.sqlx/query-9c615a14edb0886be82b9004961205da09c67a18907bbf562b6177f8bc8bc0bc.json similarity index 66% rename from backend/.sqlx/query-b7d9fc7198a30ad4e88d7cdd7b59a1a73018de16506003622cd7f779028c0fa8.json rename to backend/.sqlx/query-9c615a14edb0886be82b9004961205da09c67a18907bbf562b6177f8bc8bc0bc.json index 6c779920..63883b07 100644 --- a/backend/.sqlx/query-b7d9fc7198a30ad4e88d7cdd7b59a1a73018de16506003622cd7f779028c0fa8.json +++ b/backend/.sqlx/query-9c615a14edb0886be82b9004961205da09c67a18907bbf562b6177f8bc8bc0bc.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "SELECT \n t.id AS \"id!: Uuid\", \n t.project_id AS \"project_id!: Uuid\", \n t.title, \n t.description, \n t.status AS \"status!: TaskStatus\", \n t.created_at AS \"created_at!: DateTime\", \n t.updated_at AS \"updated_at!: DateTime\",\n CASE \n WHEN in_progress_attempts.task_id IS NOT NULL THEN true \n ELSE false \n END AS \"has_in_progress_attempt!: i64\",\n CASE \n WHEN merged_attempts.task_id IS NOT NULL THEN true \n ELSE false \n END AS \"has_merged_attempt!\",\n CASE \n WHEN failed_attempts.task_id IS NOT NULL THEN true \n ELSE false \n END AS \"has_failed_attempt!\"\n FROM tasks t\n LEFT JOIN (\n SELECT DISTINCT ta.task_id\n FROM task_attempts ta\n JOIN execution_processes ep \n ON ta.id = ep.task_attempt_id\n JOIN (\n -- pick exactly one “latest” activity per process,\n -- tiebreaking so that running‐states are lower priority\n SELECT execution_process_id, status\n FROM (\n SELECT\n execution_process_id,\n status,\n ROW_NUMBER() OVER (\n PARTITION BY execution_process_id\n ORDER BY\n created_at DESC,\n CASE \n WHEN status IN ('setuprunning','executorrunning') THEN 1 \n ELSE 0 \n END\n ) AS rn\n FROM task_attempt_activities\n ) sub\n WHERE rn = 1\n ) latest_act \n ON ep.id = latest_act.execution_process_id\n WHERE latest_act.status IN ('setuprunning','executorrunning')\n ) in_progress_attempts \n ON t.id = in_progress_attempts.task_id\n LEFT JOIN (\n SELECT DISTINCT ta.task_id\n FROM task_attempts ta\n WHERE ta.merge_commit IS NOT NULL\n ) merged_attempts \n ON t.id = merged_attempts.task_id\n LEFT JOIN (\n SELECT DISTINCT ta.task_id\n FROM task_attempts ta\n JOIN execution_processes ep \n ON ta.id = ep.task_attempt_id\n JOIN (\n -- pick exactly one \"latest\" activity per process,\n -- tiebreaking so that running‐states are lower priority\n SELECT execution_process_id, status\n FROM (\n SELECT\n execution_process_id,\n status,\n ROW_NUMBER() OVER (\n PARTITION BY execution_process_id\n ORDER BY\n created_at DESC,\n CASE \n WHEN status IN ('setuprunning','executorrunning') THEN 1 \n ELSE 0 \n END\n ) AS rn\n FROM task_attempt_activities\n ) sub\n WHERE rn = 1\n ) latest_act \n ON ep.id = latest_act.execution_process_id\n WHERE latest_act.status IN ('setupfailed','executorfailed')\n AND ta.merge_commit IS NULL -- Don't show as failed if already merged\n ) failed_attempts \n ON t.id = failed_attempts.task_id\n WHERE t.project_id = $1\n ORDER BY t.created_at DESC;\n ", + "query": "SELECT \n t.id AS \"id!: Uuid\", \n t.project_id AS \"project_id!: Uuid\", \n t.title, \n t.description, \n t.status AS \"status!: TaskStatus\", \n t.created_at AS \"created_at!: DateTime\", \n t.updated_at AS \"updated_at!: DateTime\",\n CASE \n WHEN in_progress_attempts.task_id IS NOT NULL THEN true \n ELSE false \n END AS \"has_in_progress_attempt!: i64\",\n CASE \n WHEN merged_attempts.task_id IS NOT NULL THEN true \n ELSE false \n END AS \"has_merged_attempt!\",\n CASE \n WHEN failed_attempts.task_id IS NOT NULL THEN true \n ELSE false \n END AS \"has_failed_attempt!\"\n FROM tasks t\n LEFT JOIN (\n SELECT DISTINCT ta.task_id\n FROM task_attempts ta\n JOIN execution_processes ep \n ON ta.id = ep.task_attempt_id\n JOIN (\n -- pick exactly one “latest” activity per process,\n -- tiebreaking so that running‐states are lower priority\n SELECT execution_process_id, status\n FROM (\n SELECT\n execution_process_id,\n status,\n ROW_NUMBER() OVER (\n PARTITION BY execution_process_id\n ORDER BY\n created_at DESC,\n CASE \n WHEN status IN ('setuprunning','executorrunning') THEN 1 \n ELSE 0 \n END\n ) AS rn\n FROM task_attempt_activities\n ) sub\n WHERE rn = 1\n ) latest_act \n ON ep.id = latest_act.execution_process_id\n WHERE latest_act.status IN ('setuprunning','executorrunning')\n ) in_progress_attempts \n ON t.id = in_progress_attempts.task_id\n LEFT JOIN (\n SELECT DISTINCT ta.task_id\n FROM task_attempts ta\n WHERE ta.merge_commit IS NOT NULL\n ) merged_attempts \n ON t.id = merged_attempts.task_id\n LEFT JOIN (\n SELECT DISTINCT latest_attempts.task_id\n FROM (\n -- Get the latest attempt for each task\n SELECT task_id, id as attempt_id, created_at,\n ROW_NUMBER() OVER (PARTITION BY task_id ORDER BY created_at DESC) AS rn\n FROM task_attempts\n WHERE merge_commit IS NULL -- Don't show as failed if already merged\n ) latest_attempts\n JOIN execution_processes ep \n ON latest_attempts.attempt_id = ep.task_attempt_id\n JOIN (\n -- pick exactly one \"latest\" activity per process,\n -- tiebreaking so that running‐states are lower priority\n SELECT execution_process_id, status\n FROM (\n SELECT\n execution_process_id,\n status,\n ROW_NUMBER() OVER (\n PARTITION BY execution_process_id\n ORDER BY\n created_at DESC,\n CASE \n WHEN status IN ('setuprunning','executorrunning') THEN 1 \n ELSE 0 \n END\n ) AS rn\n FROM task_attempt_activities\n ) sub\n WHERE rn = 1\n ) latest_act \n ON ep.id = latest_act.execution_process_id\n WHERE latest_attempts.rn = 1 -- Only consider the latest attempt\n AND latest_act.status IN ('setupfailed','executorfailed')\n ) failed_attempts \n ON t.id = failed_attempts.task_id\n WHERE t.project_id = $1\n ORDER BY t.created_at DESC;\n ", "describe": { "columns": [ { @@ -70,5 +70,5 @@ false ] }, - "hash": "b7d9fc7198a30ad4e88d7cdd7b59a1a73018de16506003622cd7f779028c0fa8" + "hash": "9c615a14edb0886be82b9004961205da09c67a18907bbf562b6177f8bc8bc0bc" } diff --git a/backend/src/models/task.rs b/backend/src/models/task.rs index 7f98fb3a..aa56b149 100644 --- a/backend/src/models/task.rs +++ b/backend/src/models/task.rs @@ -132,10 +132,16 @@ impl Task { ) merged_attempts ON t.id = merged_attempts.task_id LEFT JOIN ( - SELECT DISTINCT ta.task_id - FROM task_attempts ta + SELECT DISTINCT latest_attempts.task_id + FROM ( + -- Get the latest attempt for each task + SELECT task_id, id as attempt_id, created_at, + ROW_NUMBER() OVER (PARTITION BY task_id ORDER BY created_at DESC) AS rn + FROM task_attempts + WHERE merge_commit IS NULL -- Don't show as failed if already merged + ) latest_attempts JOIN execution_processes ep - ON ta.id = ep.task_attempt_id + ON latest_attempts.attempt_id = ep.task_attempt_id JOIN ( -- pick exactly one "latest" activity per process, -- tiebreaking so that running‐states are lower priority @@ -158,8 +164,8 @@ impl Task { WHERE rn = 1 ) latest_act ON ep.id = latest_act.execution_process_id - WHERE latest_act.status IN ('setupfailed','executorfailed') - AND ta.merge_commit IS NULL -- Don't show as failed if already merged + WHERE latest_attempts.rn = 1 -- Only consider the latest attempt + AND latest_act.status IN ('setupfailed','executorfailed') ) failed_attempts ON t.id = failed_attempts.task_id WHERE t.project_id = $1