Supervisors and volunteers pages load every case contact in the org (13s requests, memory spikes)

Chiusa
#7,279 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
58/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
rails, ruby

Direzione di ricerca

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.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

📈 Performance Improvement Help Wanted

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 @supervisors for the supervisor filter dropdown and its ids. It never touches contacts.
  • /supervisors calls Supervisor#no_attempt_for_two_weeks (app/models/user.rb). That method calls volunteer.case_contacts.none? and volunteer.case_contacts.maximum(:created_at), which run fresh SQL anyway. The trace shows ~120 of each on top of the preload. It also runs SELECT * FROM case_assignments WHERE volunteer_id = ? 161 times, an N+1.

Suggested fix

  • Remove :case_contacts (and probably all the includes) from SupervisorPolicy::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_weeks as one query per supervisor, or one grouped query for all supervisors. For example, count active volunteers with an active case assignment and no case_contacts created in the last 14 days. Use NOT EXISTS or MAX(created_at) grouped by creator_id, not Ruby loops.
  • Fix the case_assignments N+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.rb and spec/system/volunteers/index_spec.rb passing. The volunteer counts shown on /supervisors must 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).

Lingua principale
Ruby
Stelle
382
Fork
547
Merge medio
2g 22h
PR unite (30g)
46

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di rubyforgood/casa

Tutte le issue di rubyforgood/casa

Issue simili

Altre issue su Ruby

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.