fix(agents): stop listing soft-deleted agents
Deleting an agent looked like a no-op: it disappeared from the workforce but
stayed on the Team board, and deleting it again did nothing because the row was
already marked. Two queries selected from `agents` without `deleted_at IS NULL`:
routes/team.rs the leaderboard — the surface still showing them
routes/world.rs the "working" set — a deleted agent holding a stale
agent_containers row rendered as live
Observed on this deployment: /api/workforce correctly returned nothing while
/api/team/leaderboard returned two agents soft-deleted back in June.
NOT changed: those rows still exist. Making delete permanent means hard_purge,
which also deletes usage_events — billing history, 6 credits on one of these
two. Discarding that as a side effect of tidying a roster is an explicit
decision, not something a display fix should smuggle in.
.sqlx regenerated: team.rs uses the compile-time-checked query! macro, so the
cached entry no longer matched.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a494634f81
commit
ccbc387f4b
-16
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE topology_runs\n SET checkpoint = $2, last_event_id = $3, updated_at = now()\n WHERE id = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Jsonb",
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "5fcbd4d6adbf02489051e2fa63d1df670863bf90e55c1c0ac0ab011759cbd272"
|
|
||||||
}
|
|
||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE topology_runs\n SET status = 'queued', updated_at = now()\n WHERE status = 'running' AND updated_at < now() - make_interval(secs => $1)",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Float8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "7298995b5b58aed46888bb9e5c8d331483aee162fc6bcf1e53232d2afc7c3e62"
|
|
||||||
}
|
|
||||||
-56
@@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE topology_runs\n SET status = 'running', started_at = COALESCE(started_at, now()), updated_at = now()\n WHERE id = (\n SELECT id FROM topology_runs\n WHERE status = 'queued'\n ORDER BY created_at\n FOR UPDATE SKIP LOCKED\n LIMIT 1\n )\n RETURNING id, workspace_id, task, graph, checkpoint, last_event_id, tier",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "workspace_id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "task",
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "graph",
|
|
||||||
"type_info": "Jsonb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "checkpoint",
|
|
||||||
"type_info": "Jsonb"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "last_event_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "tier",
|
|
||||||
"type_info": "Text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": []
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "9eae6ca16ffc9346456128ce676ef04f3478f873d6ac5f95154b797f454f44c0"
|
|
||||||
}
|
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "PostgreSQL",
|
"db_name": "PostgreSQL",
|
||||||
"query": "SELECT a.id, a.name, a.accent,\n COALESCE(SUM(u.credits), 0)::BIGINT AS \"credits!\",\n COALESCE(SUM(u.tokens_in + u.tokens_out), 0)::BIGINT AS \"tokens!\",\n COUNT(u.id)::BIGINT AS \"runs!\"\n FROM agents a\n LEFT JOIN usage_events u ON u.agent_id = a.id\n WHERE a.workspace_id = $1\n GROUP BY a.id, a.name, a.accent\n ORDER BY \"credits!\" DESC, \"tokens!\" DESC, a.name",
|
"query": "SELECT a.id, a.name, a.accent,\n COALESCE(SUM(u.credits), 0)::BIGINT AS \"credits!\",\n COALESCE(SUM(u.tokens_in + u.tokens_out), 0)::BIGINT AS \"tokens!\",\n COUNT(u.id)::BIGINT AS \"runs!\"\n FROM agents a\n LEFT JOIN usage_events u ON u.agent_id = a.id\n -- deleted_at: a soft-deleted agent is gone everywhere else, so\n -- listing it here made deletion look like a no-op — the operator\n -- deletes it, the board still shows it, and deleting again does\n -- nothing because the row is already marked.\n WHERE a.workspace_id = $1 AND a.deleted_at IS NULL\n GROUP BY a.id, a.name, a.accent\n ORDER BY \"credits!\" DESC, \"tokens!\" DESC, a.name",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -48,5 +48,5 @@
|
|||||||
null
|
null
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "d4ef449c48b15519b7195be637dca3d456140ce477993d25a87e209174f79aba"
|
"hash": "d5bc028ca030daed4e6111990945d8d7011414d830f7d6d0a04980efb79af2a6"
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,11 @@ pub async fn leaderboard(
|
|||||||
COUNT(u.id)::BIGINT AS "runs!"
|
COUNT(u.id)::BIGINT AS "runs!"
|
||||||
FROM agents a
|
FROM agents a
|
||||||
LEFT JOIN usage_events u ON u.agent_id = a.id
|
LEFT JOIN usage_events u ON u.agent_id = a.id
|
||||||
WHERE a.workspace_id = $1
|
-- deleted_at: a soft-deleted agent is gone everywhere else, so
|
||||||
|
-- listing it here made deletion look like a no-op — the operator
|
||||||
|
-- deletes it, the board still shows it, and deleting again does
|
||||||
|
-- nothing because the row is already marked.
|
||||||
|
WHERE a.workspace_id = $1 AND a.deleted_at IS NULL
|
||||||
GROUP BY a.id, a.name, a.accent
|
GROUP BY a.id, a.name, a.accent
|
||||||
ORDER BY "credits!" DESC, "tokens!" DESC, a.name"#,
|
ORDER BY "credits!" DESC, "tokens!" DESC, a.name"#,
|
||||||
user.workspace_id.as_uuid(),
|
user.workspace_id.as_uuid(),
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ async fn working_agents(pool: &PgPool, ws: WorkspaceId) -> HashSet<String> {
|
|||||||
let rows = sqlx::query(
|
let rows = sqlx::query(
|
||||||
"SELECT DISTINCT a.id::text AS id
|
"SELECT DISTINCT a.id::text AS id
|
||||||
FROM agents a JOIN agent_containers ac ON ac.agent_id = a.id
|
FROM agents a JOIN agent_containers ac ON ac.agent_id = a.id
|
||||||
WHERE a.workspace_id = $1",
|
WHERE a.workspace_id = $1 AND a.deleted_at IS NULL",
|
||||||
)
|
)
|
||||||
.bind(ws.as_uuid())
|
.bind(ws.as_uuid())
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
|
|||||||
Reference in New Issue
Block a user