Opening any person page on a large tree took 4-5s on an idle server. Root cause:
list_persons looped over every person calling privacy.person_visibility (which
issues TWO get_membership_role queries per call) AND _attach_primary_name (one
name query per person). On the reporter's 2,324-person tree that's ~7,000
serialized DB round-trips per page load — the person page fetches the full
person list to build its name-lookup map.
Fix:
- Resolve the viewer's membership role ONCE. Members see the whole tree (full),
so skip the per-person privacy engine entirely.
- Add _attach_primary_names: one batched names query (person_id IN (...),
ordered the same as the single-person query so it picks the same name) instead
of one per person.
- Apply the same batching to the non-member path, search_persons, the deleted-
persons list, and public_view_service.list_public_persons.
Member-path list_persons goes from ~3·N queries to ~3 total. Other tree-wide
list endpoints (events/relationships/media/citations) were already flat selects.
Adds a regression test that asserts list_persons issues a constant number of
queries (not proportional to person count). Suite: 103 passing.
Signed-off-by: Justin Paul <justin@jpaul.me>