Skip to content

fix(member): route group checks through the request-scoped membership cache - #654

Open
romanetar wants to merge 2 commits into
mainfrom
fix/member-group-checks-use-membership-cache
Open

romanetar wants to merge 2 commits into
mainfrom
fix/member-group-checks-use-membership-cache

Conversation

@romanetar

@romanetar romanetar commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

ref: https://app.clickup.com/t/86bcjg9a2

Summary

  • isAdmin(), isSummitAdmin(), isRegistrationAdmin(), isTester(), isTrackChairAdmin() and isOnGroup() now resolve membership through belongsToGroup(), which answers from the request-scoped $groupMembershipCache after the first lookup per group code. Before, each call ran one Group_Members query through getGroupByCode(), the most executed statement on prod-12 (16.1M executions since the 2026-10-13 restart, about 117 per second).
  • getGroupByCode() consults and fills the same cache, so a known negative answer costs no query. It still queries when it needs the Group entity.
  • belongsToGroup() no longer caches the answer when the membership query fails. It logs a warning and returns false (fail closed), and the next check retries instead of treating the member as "not on the group" for the rest of the request.

Notes:

  • Results are unchanged: getGroupByCode() has no caller outside Member.php and every internal caller only null-checks it.
  • The cache is already reset by setGroups(), clearGroups(), add2Group() and removeFromGroup().
  • A Member instance kept in the identity map across jobs of a long-lived worker can still serve a stale membership. That exposure already exists for belongsToGroup() and is not changed here.

Test plan

  • tests/Unit/Models/MemberGroupMembershipFailureTest.php: a failed query is not cached, a successful one still is (no DB needed; fails against the previous belongsToGroup())
  • CI: tests/Unit/Models/MemberGroupMembershipCacheTest.php (needs the DB) asserts that N isAdmin() calls on the same instance run 2 membership queries, isOnGroup() 3, an admin short-circuits without a second lookup, and getGroupByCode() answers a known negative from the cache
  • CI: existing authorization tests pass unchanged
  • prod-12 after deploy: digest d11fcd04929d executions drop by at least 90% (from about 117 per second)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Improvements
    • Repeated group-membership checks now reuse cached results, reducing unnecessary lookups.
    • Group codes are trimmed before lookup, and temporary lookup failures won’t be cached as membership results.

… cache

isAdmin, isSummitAdmin, isRegistrationAdmin, isTester, isTrackChairAdmin and
isOnGroup ran one Group_Members query per call through getGroupByCode(), the
most executed statement on prod-12. They now resolve membership through
belongsToGroup(), which answers from $groupMembershipCache after the first
lookup per group code.

getGroupByCode() consults and fills the same cache so a known negative answer
costs no query. belongsToGroup() no longer caches the result when the query
fails, so a transient error cannot stick as "not a member" for the request.
@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cdf18f33-f30d-4ad8-bc3a-8948be50ec2c
📥 Commits

Reviewing files that changed from the base of the PR and between 0eac852 and d7e9b99.

📒 Files selected for processing: 3
  • app/Models/Foundation/Main/Member.php
  • tests/Unit/Models/MemberGroupMembershipCacheTest.php
  • tests/Unit/Models/MemberGroupMembershipFailureTest.php

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

Member group checks now use cached local membership results. Group-code lookups trim codes and cache positive and negative results. Failed membership queries are logged and not cached. Unit tests cover query counts, membership results, and retry behavior after a failed query.

Changes: Member group membership

Layer / File(s) Summary
Cache lookup and failure handling
app/Models/Foundation/Main/Member.php, tests/Unit/Models/MemberGroupMembershipFailureTest.php
getGroupByCode() trims codes and caches positive and negative lookups. Failed belongsToGroup() queries are logged and not cached. Tests verify failed queries can be retried and successful negative results are cached.
Group checks and query-count coverage
app/Models/Foundation/Main/Member.php, tests/Unit/Models/MemberGroupMembershipCacheTest.php
Admin and group-membership methods use belongsToGroup() for local checks. Tests verify membership results and query counts for repeated checks.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~15 minutes

Change: Bug fix

Merge Risk: 🔵 Low · up to d7e9b

Group checks now use a request-scoped cache. A Member instance reused after a group removal but before a flush can report stale membership. No current flow was found that does this, so the risk is bounded. Owners should be aware of it, and the cache should be invalidated when removals are made.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title "fix(member): route group checks through the request-scoped membership cache" matches the main change. The raw summary shows that Member.php routes isAdmin, isSummitAdmin, isRegistrationAdmi…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "fix(member): route group checks through the request-scoped membership cache" matches the main change. The raw summary shows that Member.php routes isAdmin, isSummitAdmin, isRegistrationAdmin, isTester, isTrackChairAdmin, and isOnGroup through belongsToGroup(), which uses the cache. It also shows getGroupByCode() using the same cache, plus the failure handling that avoids caching a failed lookup. The title is specific and scoped to the primary change. It omits the failure-handling detail, which is acceptable for a short title.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

📘 OpenAPI / Swagger preview

➡️ https://OpenStackweb.github.io/summit-api/openapi/pr-654/

This page is automatically updated on each push to this PR.

@github-actions

Copy link
Copy Markdown

📘 OpenAPI / Swagger preview

➡️ https://OpenStackweb.github.io/summit-api/openapi/pr-654/

This page is automatically updated on each push to this PR.

This branch has not been deployed

No deployments
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