/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
Summary
GET /events/upcoming rendered ~31 queries per request (production median 467ms). Three per-card query sources, all association hops the existing eager loads didn't cover:
Changes
- The workshop eager load now covers workshop_host: :sponsor and chapter: { permissions: :members }
- chapter_organisers reads the loaded collections instead of find_by, which builds a new relation and bypasses the association cache
- latest_model_updated is computed once in upcoming and past
MeasuredAgainst 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
Verify
Query count drops in production (Scout APM: /events/upcoming); median duration drops with it; ETag behaviour unchanged.
Fixes #2888