Supervisors and volunteers pages load every case contact in the org (13s requests, memory spikes)
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 58/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 领域
- backend, performance
调研方向
Start with app/policies/supervisor_policy.rb and app/models/user.rb, then trace how app/views/supervisors/index.html.erb uses volunteer counts. Run the policy and system specs named in the issue; use the suggested console data and compare query counts for both pages. Done means the pages avoid loading every contact and the N+1 queries, while the existing counts and specs remain unchanged.
由索引模型根据 Issue 内容生成。
描述
Problem
/supervisors and /volunteers are the slowest pages in production. They also allocate the most memory, which likely contributes to the R14 memory errors in #7218.
From Scout APM, last 7 days:
| Endpoint | Avg response | Slowest trace | Allocations |
|---|---|---|---|
supervisors/index |
3.5 s | 13.4 s | ~800k |
volunteers/index |
1.2 s | 13.8 s | ~600k |
In both slow traces, one preload query takes 12–13 s and loads ~29,600 CaseContact rows. That's every case contact written by every volunteer in the org, loaded on every page view.
Root cause
app/policies/supervisor_policy.rb:
class Scope < ApplicationPolicy::Scope
def resolve
scope.includes(
:volunteers,
volunteers: [:supervisor, :case_assignments, :case_contacts]
)
end
end
The preload doesn't even help:
/volunteers(VolunteersController#index, line ~11) only uses@supervisorsfor the supervisor filter dropdown and its ids. It never touches contacts./supervisorscallsSupervisor#no_attempt_for_two_weeks(app/models/user.rb). That method callsvolunteer.case_contacts.none?andvolunteer.case_contacts.maximum(:created_at), which run fresh SQL anyway. The trace shows ~120 of each on top of the preload. It also runsSELECT * FROM case_assignments WHERE volunteer_id = ?161 times, an N+1.
Suggested fix
- Remove
:case_contacts(and probably all theincludes) fromSupervisorPolicy::Scope#resolve. A policy scope should filter, not eager-load. Add the includes the page needs at the call site instead. - Rewrite
no_attempt_for_two_weeksas one query per supervisor, or one grouped query for all supervisors. For example, count active volunteers with an active case assignment and nocase_contactscreated in the last 14 days. UseNOT EXISTSorMAX(created_at)grouped bycreator_id, not Ruby loops. - Fix the
case_assignmentsN+1 on/supervisors(volunteer.case_assignments.any?(&:active?)inside the loop). - Keep the existing
spec/policies/supervisor_policy_spec.rb,spec/system/supervisors/index_spec.rbandspec/system/volunteers/index_spec.rbpassing. The volunteer counts shown on/supervisorsmust not change. - Prosopite (N+1 detection) is already on in specs, so it will flag regressions.
How to verify locally
Seed data is small, so the slowness won't show up. Add a few thousand contacts in a console: FactoryBot.create_list(:case_contact, 3000, creator: Volunteer.first) in RAILS_ENV=development. Then compare the query count and time in the dev log before and after, for /supervisors and /volunteers as [email protected].
Difficulty: intermediate. It's mostly in two files (supervisor_policy.rb, user.rb), plus the views that read the counts (app/views/supervisors/index.html.erb).
- 主要语言
- Ruby
- 星标
- 382
- 派生
- 547
- 平均合并
- 2 天 22 小时
- 30 天内合并 PR
- 46
环境准备
在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。
- 提供 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
rubyforgood/casa 的其他 Issue
-
Remove leftover Cloud66 custom_web process from Procfile可能已有人在做 @ShahadatTest 今天认领。 未关闭Difficulty: Easy Good First Issue
难度 1/5 1 小时以内 新手友好度 88/100
rubyforgood/casa#7330 · 1 条评论 ·
维护者通常 1 天内回复
-
dependencies Difficulty: Easy Good First Issue
难度 1/5 1 小时以内 新手友好度 82/100
rubyforgood/casa#7325 ·
维护者通常 1 天内回复
-
Difficulty: Easy Good First Issue Help Wanted javascript
难度 2/5 1-3 小时 新手友好度 72/100
rubyforgood/casa#7311 ·
维护者通常 1 天内回复
-
Difficulty: Easy Good First Issue Help Wanted javascript
难度 2/5 1-3 小时 新手友好度 78/100
rubyforgood/casa#7310 ·
维护者通常 1 天内回复
-
Difficulty: Easy Good First Issue Help Wanted javascript
难度 2/5 1-3 小时 新手友好度 78/100
rubyforgood/casa#7309 ·
维护者通常 1 天内回复
相似的 Issue
-
难度 1/5 1 小时以内 新手友好度 82/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
yegor256/intercepted#128 ·
-
documentation good first issue
难度 1/5 1 小时以内 新手友好度 85/100
ysb3996-blip/oops#51 ·
维护者通常 1 天内回复
-
good first issue
难度 1/5 1 小时以内 新手友好度 72/100
维护者通常 1 天内回复
-
area:core-lib P2 size:S
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复