3

In my custom module, I define a custom block that performs an expensive operation:

/**
 * {@inheritdoc}
 */
public function build() {
  $data = get_expensive_data();
  $agent_number = get_agent_number_from_context();
  return [
    '#theme' => 'my_custom_module',
    '#cache' => [
      'keys' => ['my_block', 'full_version', $agent_number],
      'tags' => ['my_custom_module'],
      'max-age' => 86400,
    ],
  ];
}

The caching works except when another user views the block or a user with a different role view the page; it creates a new cache item. Is it possible to have cache only one time for multiple users/roles?

Edit

I tried the following (ended up using route context just to not add another variable to my problem):

/**
 * {@inheritdoc}
 */
public function build() {
  $data = get_expensive_data();
  return [
    '#theme' => 'my_custom_module',
    '#data' => $data,
    '#cache' => [
      'contexts' => ['route'],
      'tags' => ['my_module'],
      'max-age' => 86400,
    ],
  ];
}

Noticed when I had the block using Layout Builder via Page Manager, no item got added to the cache_render table (that might be a separate issue). When I added the block on default Drupal Block Layout I noticed that it still created a new cache record for every user. For example:

User 1 navigated to: /my-account/A123 and the following record got added to the cache_render table:

cid

entity_view:block:mycustomblock:[languages:language_interface]=en:[route]=entity.node.canonical7ccb4f15749b8c9e759f0016bfc863bd5e6bef88ea0a9dfe7b1cbe2687d30b32:[theme]=my_theme:[url.site]=http://mysite.test:[user]=1

tags

block_view config:block.block.mycustomblock config:user.role.administrator config:user.role.authenticated my_module rendered user:1

User 72 navigated to: /my-account/A123 and the following record got added to the cache_render table:

cid

entity_view:block:mycustomblock:[languages:language_interface]=en:[route]=entity.node.canonical7ccb4f15749b8c9e759f0016bfc863bd5e6bef88ea0a9dfe7b1cbe2687d30b32:[theme]=my_theme:[url.site]=http://mysite.test:[user]=79

tags

block_view config:block.block.mycustomblock config:user.role.agent config:user.role.authenticated my_module rendered user:79

With using contexts, I am still seeing it create a new record for every user.

Edit 3

I think my test form Edit 2 is invalid because I was trying to make the block work outside of page manager but I needed the context from page manager so it was using the logged-in users. Long story short, I need to figure out why context caching isn't working (although key caching is working) when using Page Manager or Layout Manager.

2
  • In case you didn't know, max-age doesn't work for anonymous users (anonymous user role). See Limitations of max-age
    – No Sssweat
    Apr 23 '20 at 22:07
  • @NoSssweat I did not know that. Thanks for sharing.
    – albertski
    Apr 24 '20 at 13:08
5

Caching is shared with multiple users or roles by default, unless you add a cache context like user or user.roles.

Otherwise it's hard to tell what the code in the question wants to achieve.

  1. If it wants to set block cache keys, then you can't do it from here and you don't need to. They're set automatically. get_agent_number_from_context() should probably be a custom cache_context.agent_number which you then could add to the block build array to vary the cached block by this variable:

    /**
     * {@inheritdoc}
     */
    public function build() {
      $data = get_expensive_data();
      return [
        '#theme' => 'my_custom_module',
        '#data' => $data,
        '#cache' => [
          'contexts' => ['agent_number'],
          'max-age' => 86400,
        ],
      ];
    }
    

    How to create a custom cache context: https://www.drupal.org/docs/8/api/cache-api/cache-contexts#recognize-discover-create

  2. If it wants to cache the expensive data on its own (which makes sense if you want to reuse the rendered result in other places not necessarily blocks), then you need to execute get_expensive_data() in a #pre_render callback to avoid that it gets executed in case of a cache hit. See https://dev.acquia.com/blog/drupal-8-performance-render-caching

Edit 1: The cids you have added to the question contain a cache context for the user. I can't tell by the code shown so far how it ends up in your block. But there is also a cache tag of the user, so there has to be some code retrieving and rendering the current user.

Edit 2: Assuming the theme is the same there is also a default user.permissions cache context for all render caching which probably kicks in now that user is removed. See https://www.drupal.org/project/drupal/issues/2493033

8
  • Thanks. That makes perfect sense. I tried to create a custom cache context but wasn't able to view the agent number context. It might be because of page manager. drupal.stackexchange.com/questions/293098/…
    – albertski
    Apr 23 '20 at 22:59
  • For some reason I am not seeing the cache data get stored when logged in with multiple roles when using 'contexts' => ['agent_number'],. I even tried 'contexts' => ['user'],. Is there a special way to enable this to work for authenticated users?
    – albertski
    Apr 24 '20 at 16:45
  • Also, would these still be added to the cache_render table? I am not seeing anything in the cache_dynamic_page_cache table but I'm assuming that would be only for full pages and not blocks.
    – albertski
    Apr 24 '20 at 17:11
  • A block is cached by default, even without an cache metadata like tags or contexts. Blocks become part of pages unless they are placeholdered (but then you see the placeolder instead). If you don't see anything in those cache tables my guess would be that you have disabled caching in your dev environment.
    – 4k4
    Apr 24 '20 at 17:37
  • Actually, when I had the block on the page via Page Manager/Layout Builder the record didn't get added to cache_render. Weird that if I used my original method keys it did add it. I added an Edit section to my question of what I tried. You will notice that I am seeing the same issue of a separate cache item get added for each user.
    – albertski
    Apr 24 '20 at 19:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.