Score:2

How can I test Max-age on cache?

iq flag

I have a Controller using cache tags. I have just been asked a change that requires a Max-age also (show next event starting from current time); I explained that the only way to have this is with some delay, and we agreed for a max-age of 300.

To test the modification on my development machine, I set a shorter max-age of 60,

        return [
            '#theme' => 'mytheme',
            '#my_param' => $value,
             ...
            '#cache' => [ 
                'tags' => $cache_tags,
                'max-age' => 60,
            ],
        ];

I loaded the page just after a drush cr, and in the header I got a clear X-Drupal-Cache: MISS. I loaded it again, and I got a HIT. Then I waited for a minute... and I got a HIT again.

Should I be looking for something else? I noticed a X-Drupal-Dynamic-Cache header also, but it is always set to MISS.

EDIT: From the comments I understood that I cannot set a max-age on a page with anonymous access, so the question changes: is there any other workaround, apart from disabling cache on this page, that would have a big impact on performance?

unusedspoon avatar
aq flag
X-Drupal-Cache is for the anonymous user caching of the whole page. It's well documented that setting a max-age has no effect on this caching unfortunately. So max-age will only affect X-Drupal-Dynamic-Cache. This only becomes active if you are logged in (or you disable the anonymous caching). Also if you are logged in with an admin account things like the admin toolbar will always cause a MISS on X-Drupal-Dynamic-Cache. So best to try with normal user logged in account
Jaypan avatar
de flag
Usually it's better to invalidate a cache after a change has been made, rather than setting a max age, as max-age adds to performance hits. That's not an absolute rule, but you didn't tell us your use case. Is there a specific reason to use max-age rather than invalidating a cache tag?
id flag
max-age does not bubble https://www.drupal.org/project/drupal/issues/2352009
Francesco Marchetti-Stasi avatar
iq flag
@unusedspoon, the page in question is a public page, so yes, it was accessed by the the anonymous user. Now that you mention it, I remember reading that max-age has no effect on this caching; I didn't search the documentation because, well, I often find it difficult to look things up in Drupal documentation, especially when I don't know exactly what I'm looking for...
Francesco Marchetti-Stasi avatar
iq flag
@Jaypan, I described it quickly between parentheses: I have to show the next event starting from current time, so it changes even if no content is changed. Suppose for example that there is an event starting at 11:00 and one at 14:30: at 10:59 I have to show the first, at 11:01 I should show the second. As I said, I negotiated a delay of five minutes, so the worst case is that the page is updated with a five minutes delay, i.e., the page would show the event at 11:00 until 11:05, and then the one at 14:30 would appear.
Francesco Marchetti-Stasi avatar
iq flag
@cilefen, thank you. That's quite a lot to read, but if I understand correctly the summary is that there is no way to manage this use case, correct? :(
id flag
I think there is a patch for Core that works.
Francesco Marchetti-Stasi avatar
iq flag
Thank you @cilefen, I'll keep an eye on the issue and eventually migrate to the more elegant solution based on max-age; in the meantime, I will keep the system cron based solution suggeste by 4uk4.
Score:4
cn flag

To extend on the comments. At this moment the only caching method implemented for anonymous traffic is cache tags. Context or max-age don't work. Cache tags are great for database content, this is the use case of Drupal out-of-the-box. But you can use cache tags for a time-based invalidation as well. In a cron job:

mymodule.module

use Drupal\Core\Cache\Cache;

/**
 * Implements hook_cron().
 */
function mymodule_cron() {
  $cache_tags = ['foo'];
  if (date('H') == 12 ) {
    Cache::invalidateTags($cache_tags);
  }
}

This invalidates the controller output every 24h at noon. Make sure to trigger cron at least every hour.

To achieve the max-age of 300, trigger cron every 5 min, or when events usually start in your schedule. Go to /admin/config/system/cron, get the link with the long hash code, and wget it in the cron table of your web host.

Then run the cron hook without condition:

function mymodule_cron() {
  $cache_tags = ['foo'];
  Cache::invalidateTags($cache_tags);
}

Don't forget to configure "Browser and proxy cache maximum age" in the Performance configuration page accordingly.

Francesco Marchetti-Stasi avatar
iq flag
Thank you @4uk4, I guess this is my only possibility. I already have a couple of routes configured with `_access_system_cron` and invoked from the host cron, so I will implement this solution.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.