Skip to content

perf: preload organiser roles to eliminate N+1 queries in event_organiser?#2692

Merged
mroderick merged 1 commit into
masterfrom
benchmark/event-organiser
Jul 7, 2026
Merged

perf: preload organiser roles to eliminate N+1 queries in event_organiser?#2692
mroderick merged 1 commit into
masterfrom
benchmark/event-organiser

Conversation

@mroderick

Copy link
Copy Markdown
Collaborator

This optimisation originally came from @jonodrew's work in #2305. That PR had deeper merge conflicts with a rewritten EventsController, but the hash-lookup approach for event_organiser? was independently useful and is extracted here.

What changed

event_organiser? in MemberPresenter was calling has_role?(:organiser, event) per event — one permission query (plus join) for each event on the page. For an organiser, this fires for every event/meeting rendered in the listing.

The replacement preloads all organiser roles into a { resource_type => [resource_id] } hash with a single query, then does in-memory lookups.

When this applies

Only for organiser users viewing event listing pages. The call site in _event.html.haml is guarded by @user.organiser?, so non-organisers never hit this path. The pages that benefit:

  • Dashboard (/, /dashboard) — rendering upcoming workshops
  • Chapter page (/:slug) — upcoming and past workshops
  • Events index (/events/upcoming, /events/past) — paginated event lists

Benchmarks

Against production data (29k members, 2.5k workshops, user with 258 organiser roles, 50 workshops):

Master This PR Saving
Time 136ms 4ms 26-32x faster
Permission queries 143 2 98.6% reduction

The 2 remaining queries are: one SELECT to bulk-load all organiser role rows, and one SELECT for the memoised admin check.

…iser?

Replaces per-event has_role?(:organiser) calls with a single query that
loads all organiser roles upfront, then does in-memory hash lookups.

Reduces permission queries for a page with 30 events from ~88 to ~2
(98% reduction). Measured against dev data with an organiser user.

- Adds private organising_events method (cached) that plucks all
  organiser role (resource_type, resource_id) pairs
- Adds private admin? method (cached) for the admin fallback check
- Handles nil chapter for events/meetings that use HABTM chapters
@mroderick mroderick marked this pull request as ready for review July 7, 2026 14:36
@mroderick mroderick merged commit 66e5621 into master Jul 7, 2026
9 checks passed
@mroderick mroderick deleted the benchmark/event-organiser branch July 7, 2026 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants