Skip to content

Commit 890d0af

Browse files
committed
web: replace N+1 queries in todo list
The todo page runs one COUNT query per project to find how many patches are delegated to the current user. Replace this with a single GROUP BY query that counts all projects at once. Signed-off-by: Robin Jarry <robin@jarry.cc>
1 parent 950bfd0 commit 890d0af

1 file changed

Lines changed: 20 additions & 7 deletions

File tree

‎pkg/web/todo.go‎

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,30 @@ func (h *webHandler) TodoLists(w http.ResponseWriter, r *http.Request) {
2727
user := getWebUser(r)
2828
pc := h.pageCtx(r)
2929

30+
type countRow struct {
31+
ProjectID int `bun:"project_id"`
32+
Count int `bun:"count"`
33+
}
34+
var counts []countRow
35+
q.DB.NewSelect().Model((*db.Patch)(nil)).
36+
Column("project_id").
37+
ColumnExpr("count(*) AS count").
38+
Where("archived = ?", false).
39+
Where("delegate_id = ?", user.ID).
40+
Where("state_id IN (SELECT id FROM state WHERE action_required = ?)", true).
41+
GroupExpr("project_id").
42+
Scan(q.Ctx, &counts)
43+
44+
countByProject := make(map[int]int, len(counts))
45+
for _, c := range counts {
46+
countByProject[c.ProjectID] = c.Count
47+
}
48+
3049
projects, _ := q.ListProjects()
3150

3251
var todos []todoProject
3352
for _, p := range projects {
34-
count, _ := q.DB.NewSelect().Model((*db.Patch)(nil)).
35-
Where("project_id = ?", p.ID).
36-
Where("archived = ?", false).
37-
Where("delegate_id = ?", user.ID).
38-
Where("state_id IN (SELECT id FROM state WHERE action_required = ?)", true).
39-
Count(q.Ctx)
40-
if count > 0 {
53+
if count := countByProject[p.ID]; count > 0 {
4154
todos = append(todos, todoProject{Project: p, NPatches: count})
4255
}
4356
}

0 commit comments

Comments
 (0)