Supervisors and volunteers pages load every case contact in the org (13s requests, memory spikes)
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 58/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Área
- backend, performance
Línea de trabajo
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.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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).
- Lenguaje dominante
- Ruby
- Estrellas
- 382
- Forks
- 547
- Merge medio
- 2 d 22 h
- PR fusionados (30 d)
- 46
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Incluye un Dockerfile o un archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de rubyforgood/casa
-
Remove leftover Cloud66 custom_web process from ProcfilePosiblemente ocupada @ShahadatTest la tomó hoy. AbiertoDifficulty: Easy Good First Issue
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
rubyforgood/casa#7330 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
dependencies Difficulty: Easy Good First Issue
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
rubyforgood/casa#7325 ·
Los mantenedores suelen responder en 1 día
-
Difficulty: Easy Good First Issue Help Wanted javascript
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
rubyforgood/casa#7311 ·
Los mantenedores suelen responder en 1 día
-
Difficulty: Easy Good First Issue Help Wanted javascript
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
rubyforgood/casa#7310 ·
Los mantenedores suelen responder en 1 día
-
Difficulty: Easy Good First Issue Help Wanted javascript
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
rubyforgood/casa#7309 ·
Los mantenedores suelen responder en 1 día
Todos los issues de rubyforgood/casa
Issues similares
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
zold-io/zold-ruby-sdk#85 ·
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 62/100
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100