Skip to content

perf: fix N+1 queries in notification jobs and discussion update serialization#96

Open
imorland wants to merge 1 commit into2.xfrom
im/fix-n1-queries
Open

perf: fix N+1 queries in notification jobs and discussion update serialization#96
imorland wants to merge 1 commit into2.xfrom
im/fix-n1-queries

Conversation

@imorland
Copy link
Copy Markdown
Member

Summary

  • Notification jobs: stateFor($user) was called inside reject() callbacks in all three notification job classes — once per user per tag (N×T queries). Replaced with a single TagState::whereIn() pre-load via a new preloadTagStates() helper on NotificationJob, reducing to 1 query regardless of user/tag count.
  • Discussion Update endpoint: flarum/tags eager-loads tag state via withStateFor() for Index, Show, and Create on DiscussionResource — but not Update. The subscription field getter was falling back to stateFor() per tag on discussion edit responses. Added eagerLoadWhere('tags', withStateFor(...)) for the Update endpoint to close this gap.

Confirmed via Clockwork

PATCH /api/discussions/{id} with 3 tags: 0 tag_user state queries (was 3×, one per tag). Notification job fix is correct by inspection — async queue jobs are not captured in HTTP Clockwork entries.

What remains unfixed (by design)

whereVisibleTo($user) and isVisibleTo($user) in reject() remain as per-user queries — these cannot be batched without framework changes.

…alization

In all three notification jobs, `stateFor($user)` was called inside
`reject()` callbacks — once per user per tag, resulting in N×T queries.
Replace with a single `TagState::whereIn()` pre-load keyed by user ID,
via a new `preloadTagStates()` helper on `NotificationJob`.

Also adds an `eagerLoadWhere` for the `tags` relation on the
`DiscussionResource` `Update` endpoint, closing a gap left by
`flarum/tags` which only covers `Index`, `Show`, and `Create`. Without
this, the `subscription` field getter fell back to `stateFor()` per tag
on discussion edit responses.

Confirmed via Clockwork: PATCH /api/discussions/{id} with 3 tags now
runs 0 tag_user state queries (was 3×) against the Update endpoint.
@imorland imorland requested a review from a team as a code owner March 14, 2026 10:07
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.

1 participant