Problem/Motivation

Thank you for Masquerade Role! Our support staff use it to see the site with a role of the people they help.

The module replaces the current_user service with MasqueradeAccountProxy. Its getRoles() and hasPermission() ask RoleManager::isActive() first, which reads the user's "active" flag through RoleManager::getData() from user.data: one database query on every call, without a static cache. Drupal calls these two methods very often while it builds a page: the user.roles and user.permissions cache contexts of every cached element, every entity access check, every node grant check.

On our site (Drupal 11.4, msqrole 1.0.21) this made 500 to 800 of these queries for an ordinary page of a logged-in user, and more than 5,000 on a page whose render cache was cold. Even a page served from the dynamic page cache still made more than 200, because the cache contexts of its placeholders are resolved on every request. It does not matter whether the user masquerades: the flag is read either way.

Steps to reproduce

  1. Install the module and log in as any user (no masquerading needed).
  2. Log the database queries of a page view, for example with Database::startLog() or the Webprofiler module.
  3. Most of the queries read the table users_data with module = 'msqrole' and name = 'active' for the same user.

Proposed resolution

  • RoleManager::getData() reads all msqrole data of a user with one query and keeps it for the rest of the request (keyed by user ID).
  • setData() and removeData() drop what is kept for that user, so a change made in the same request is read fresh.
  • A call with a NULL user ID keeps its current behaviour.

With this change, a page of a logged-in user on our site made 10 instead of about 220 database queries (dynamic page cache hit), and the pages became about twice as fast (median of 7 interleaved runs, local Docker setup):

Page Before After
Front page 249 ms 121 ms
FAQ page 163 ms 82 ms
Article listing 281 ms 141 ms
Content page 319 ms 111 ms
Personal dashboard 241 ms 147 ms

Remaining tasks

Review the MR.

User interface changes

None.

API changes

None.

Data model changes

None.

Text generated with AI

Issue fork msqrole-3630504

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

daniel.pernold created an issue. See original summary.

daniel.pernold’s picture

Status: Active » Needs review
randalv’s picture

Status: Needs review » Fixed

This definitely should have been improved long ago, good find and thanks for providing a sensible fix!

I'll merge and push a new tag.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

daniel.pernold’s picture

Thank you so much, randalv, for the quick review, the kind words and for releasing the fix in 1.0.22 right away! We'll switch to the new release.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.