Adding cache tag during hook_toolbar_alter breaks render caching

Created on 24 September 2024, about 2 months ago

Problem/Motivation

I noticed that after installing this module, toolbar render caching wasn't working for for logged in users.

Steps to reproduce

1. Use a site with caching enable, with a database cache backend for easy debugging.
2. Log in as an admin and hit an admin page such as /admin/content
3. Do not have this module installed, verify that the toolbar is being cached in the render cache with:

SELECT cid FROM cache_render WHERE cid LIKE "%toolbar:%";

4. Enable this module and clear the cache, then make a request to /admin/content again.
5. Run the same query as above, the toolbar is now not being cached.

Proposed resolution

By adding a cache tag during hook_toolbar_alter(), this is done during a #prerender in docroot/core/lib/Drupal/Core/Render/Renderer.php:

    // Make any final changes to the element before it is rendered. This means
    // that the $element or the children can be altered or corrected before the
    // element is rendered into the final text.
    if (isset($elements['#pre_render'])) {
      foreach ($elements['#pre_render'] as $callable) {
        $elements = $this->doCallback('#pre_render', $callable, [$elements]);
      }
    }

Adding a cache tag breaks a check later in Renderer to confirm the cache keys haven't changed, it seems to nuke the 'keys' part of the #cache element:

    // Cache the processed element if both $pre_bubbling_elements and $elements
    // have the metadata necessary to generate a cache ID.
    if (isset($pre_bubbling_elements['#cache']['keys']) && isset($elements['#cache']['keys'])) {
      if ($pre_bubbling_elements['#cache']['keys'] !== $elements['#cache']['keys']) {
        throw new \LogicException('Cache keys may not be changed after initial setup. Use the contexts property instead to bubble additional metadata.');
      }
      $this->renderCache->set($elements, $pre_bubbling_elements);

If these 'keys' don't match then the element doesn't cache at all. I believe you have to add the cache tag in hook_page_top() so it's added before any #pre_render hooks are handled.

Patch to come.

🐛 Bug report
Status

Active

Version

1.0

Component

Code

Created by

🇦🇺Australia thomwilhelm Sydney

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

Merge Requests

Comments & Activities

Production build 0.71.5 2024