perf: GetSessions runs 11 correlated subqueries per row despite its doc comment #453
Labels
No labels
backend
bug
chore
duplication
effort:complex
effort:medium
effort:trivial
enhancement
frontend
fullstack
priority:high
ready-for-agent
refactor
security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
dries/ocman#453
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Code-quality audit (P2).
internal/db/sessions.go:22-101.The doc comment is wrong. The query runs 11 correlated subqueries per session row:
count(*)overmessageSUM(...)scans overmessage... ORDER BY time_created DESC LIMIT 1subqueries that each re-find the same last message:last_role,last_finish,last_error,last_error_name,last_error_message,last_error_at,last_synth_terminal.The N+1 was moved from Go into SQL, not removed. There is also no
LIMITon the statement, so an unfiltered call does all of this for every session in the table.Why it matters
This is on the
/api/sessionsrequest path — the dashboard's first paint and every poll. Cost grows with total session count, not page size, and each of the 7 last-message subqueries re-scans the samemessagerows. Combined with the missingExecContext/QueryContext(separate ticket), a slow run cannot even be cancelled.Suggested fix
Collapse the 7 into one
LEFT JOINagainst alast_messageCTE keyed onsession_id:Same treatment for the 3
SUMs +count(*)via a single grouped aggregate CTE. Fix the doc comment either way. Consider aLIMITon the unfiltered path.Acceptance criteria
messageper aggregate concern instead of 11 correlated subqueries.GetSessionstests pass unchanged, including thelast_synth_terminalshell-envelope case.Effort: M.