Eager-load host and chapter-organiser chains for event listings - #2909
Merged
Merged
Conversation
/events/upcoming issued ~31 queries per render (production median 467ms). Three per-card query sources, all association hops the existing eager loads didn't cover: - WorkshopPresenter#venue -> model.host -> workshop_host.sponsor: the belongs_to sponsor behind the has_one :host through-chain now loads with the workshop (13 single-sponsor queries on the production page). - WorkshopPresenter#organisers falls back to the chapter's organiser permission members; that hop now loads with the chapter, and chapter_organisers reads the loaded collections instead of find_by (which would bypass the association cache). - latest_model_updated ran its 4 MAX queries twice (once for fresh_when's Last-Modified, once for the etag); compute it once. Against codebar_production_dump: 26 queries -> 9, warm render ~115ms. Fixes #2888
mroderick
marked this pull request as ready for review
September 19, 2026 13:18
olleolleolle
approved these changes
Sep 19, 2026
olleolleolle
enabled auto-merge
September 19, 2026 20:00
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GET /events/upcomingrendered ~31 queries per request (production median 467ms). Three per-card query sources, all association hops the existing eager loads didn't cover:WorkshopPresenter#venue→model.host→workshop_host.sponsor— the sponsor behind thehas_one :hostthrough-chain loaded one query per hosted workshop (13 on the measured page)WorkshopPresenter#organisersfalls back to the chapter's organiser members when a workshop has none;chapter.permissions.find_by(name: 'organiser')loaded one query per such cardlatest_model_updatedran its four MAX queries twice —fresh_whenreceived it as both the Last-Modified value and the etagChanges
workshop_host: :sponsorandchapter: { permissions: :members }chapter_organisersreads the loaded collections instead offind_by, which builds a new relation and bypasses the association cachelatest_model_updatedis computed once inupcomingandpastMeasured
Against
codebar_production_dump(fragment cache warm): 26 queries → 9, warm render ~115ms either way. Reproduced the production shape: the 13 single-sponsor queries and the double MAX queries are gone.Review notes
chapter_organisersbehaviour is unchanged for empty results (nil →[]in both shapes)./events/pastsharesload_eventsbut has no query-count guard of its own.Verify
Query count drops in production (Scout APM:
/events/upcoming); median duration drops with it; ETag behaviour unchanged.Fixes #2888