Supervisors and volunteers pages load every case contact in the org (13s requests, memory spikes)
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 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時間
- マージ済み PR(30日)
- 46
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
rubyforgood/casa のほかの issue
-
Remove leftover Cloud66 custom_web process from Procfile対応中かも @ShahadatTest が 1 日前に担当しました。 オープンDifficulty: Easy Good First Issue
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
rubyforgood/casa#7330 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Remove the bin/bundle binstub (Heroku warns it can break Bundler on deploy)対応中かも @KoushikSagarr が 1 日前に担当しました。 オープンdependencies Difficulty: Easy Good First Issue
難易度 1/5 1時間未満 初心者へのやさしさ 82/100
rubyforgood/casa#7325 · コメント 1 件 ·
メンテナーはふだん 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 日以内に返信
rubyforgood/casa の issue をすべて見る
似ている issue
-
area/web interface
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
rubys/roundhouse#1757 ·
-
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
akitaonrails/ai-book-2026#12 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
openfoodfoundation/openfoodnetwork#14970 ·
メンテナーはふだん 1 日以内に返信
-
JWT::EncodedToken raises TypeError for a non-object header対応中かも @anakinj が今日担当しました。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
jwt/ruby-jwt#780 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信