Share D10 dynamic cache among users with different roles

Created on 22 April 2024, 9 months ago

Problem/Motivation

I'm trying to setup Drupal's dynamic page cache on my custom module and I'm ecountering some issues with it. One of the issues is the one I'm going to reproduce here. I have the impression that Drupal's dynamic page cache doesn't share among users if they don't have the same role.

Steps to reproduce

  1. Edit the file "drupal/sites/development.services.yml" and comment the following lines :
    # services:
    #   cache.backend.null:
    #     class: Drupal\Core\Cache\NullBackendFactory
    
  2. Edit the file "drupal/sites/default/settings.local.php" and comment every line containing the string "cache.backend.null". (Normally, there is 3 lines.)
  3. Create a folder in drupal/web/modules/custom for a test module. For example "issue".
  4. Create a file in the previously created folder called ".info.yml". For example, issue.info.yml with the belows content :
    name: Cache Issue reproduction
    type: module
    description: Module to reproduce Zilloww's cache issue.
    package: Custom
    core_version_requirement: ^10
    
  5. Create the file "issue.routing.yml" with the following content :
    issue.index:
      path: '/issue'
      defaults:
        _controller: '\Drupal\issue\Controller\IssueController::index'
        _title: 'Issue'
      requirements:
        _permission: 'access content'
    
  6. Create a file called "issue.module" with the following content :
    function issue_theme() {
        return [
            'issue' => [
                'variables' => ['variables' => NULL]
            ]
        ];
    }
    
  7. Create a folder called "src". In this folder, create a folder "Controller". In the folder "src/Controller", create the file "IssueController.php" with the following content :
    <?php
    
    namespace Drupal\issue\Controller;
    
    use Drupal\Core\Controller\ControllerBase;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    
    class IssueController extends ControllerBase
    {
        public function index() {
            $ids = \Drupal::entityQuery('node')
                ->accessCheck(FALSE)
                ->condition('type', 'article')
                ->execute();
    
            $variables['articles'] = \Drupal\node\Entity\Node::loadMultiple($ids);
    
            return [
                '#theme' => 'issue',
                '#variables' => $variables,
                '#cache' => [
                    'contexts' => [],
                    'max-age' => \Drupal\Core\Cache\Cache::PERMANENT,
                    'tags' => ['node_list:article']
                ]
            ];
        }
    }
    
  8. Create the folder "issue/templates" and create the file "issue.html.twig" in it with the following content :
    <div style="padding:50px;">
        {% if variables.articles|length > 0 %}
            <h1>Articles</h1>
    
            <ul>
                {% for article in variables.articles %}
                    <li>{{ article.label }}</li>
                {% endfor %}
            </ul>
        {% else %}
            <h1>No article found.</h1>
        {% endif %}
    </div>
    
  9. Execute the following command in your terminal : drush en issue to activate the test module
  10. Create a role called "A" and another role called "B".
  11. Create a user and put it in the role "A" .
  12. Create a second user and put it in the role "B" .
  13. Navigate to the url "/issue" with the user X.
  14. Open your browser's developer console and find the page response in the network tab. Take a look at the header "X-Drupal-Dynamic-Cache". If it's the first time that you load the page, it has to be set to "MISS".
  15. Now, create a new article on your website and refresh the page with the user X. Normally, the cache has to miss another time because the "node_list:article" cache tag has been invalidated.
  16. Refresh another time the page with the user X. Now, the header "X-Drupal-Dynamic-Cache" has to be set to "HIT".
  17. Now, go to the page with the user Y. The expected behaviour is to get a HIT from the cache since the user X already built it.

Proposed resolution

I gave my entire setup and steps to reproduce my issue in the section "Steps to reproduce". Let me know if you can reproduce the issue and know why is this happening.
, If the user X and the user Y are both in the role A, the cache will be shared amongst these two users.

💬 Support request
Status

Active

Version

10.3

Component
Cache 

Last updated about 14 hours ago

Created by

🇨🇭Switzerland zilloww

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @zilloww
  • 🇨🇭Switzerland zilloww

    @prachimudholkar,

    Thank you for your response. I believe it may have been unintentional, but you deleted the content of my post. Could you please refrain from doing so? I haven't found a solution for my issue on this Stack Exchange, but it might be beneficial for others.

    On a related note, I discovered what's happening! In the file "drupal/web/core/core.services.yml," there's a line that sets the "required_cache_contexts." This configuration specifies the default cache contexts for every cached element on the website, this configurations sets the context "user.permissions" as a default cache context which likely explains a lot because permissions are assigned by roles.

    Since every cache is constructed with the "user.permissions" context, it seems normal for User Y to experience a CACHE MISS when User X receives a CACHE HIT. This happens because the page cache misses due to differing permissions between the two users. However, the page cache has placeholders (including one pointing to the cache of my list), which means the list's cache HITS. Therefore, the page is rebuilt for each user from a different group, but not the list, which is a positive outcome.

    This appears to be just typical behavior of the Drupal caching system. If anyone has a different perspective or explanation, I am open to suggestions.

  • Status changed to Postponed: needs info 1 day ago
  • 🇳🇿New Zealand quietone

    The Drupal Core issue queue is not the ideal place for support requests. The 'support request' option is there for filing support issues for contributed modules and themes. There are several support options listed on our support page (Community > Support at the top of Drupal.org) and there is Drupal Slack . You may get better replies in one of those places.

    Was this answered by the link provided in #2?

Production build 0.71.5 2024