5

We have a certain content type in Drupal 8 that has a small grid of data on it that is populated from an API call when the node view is being built.

In that call, I am checking for cache and setting cache instead of talk to the API every request:

if ($cache = $this->cache->get($cache_key)) {
  return $cache->data;
}

// $content = request...

$this->cache->set($cache_key, $content, REQUEST_TIME + 3600, ['mymodule']);

Where $cache_key is just mymodule:remote_id:subscription_id. My default cache bin is handled via Memcache.

The Drupal page cache time is set to 30 minutes, and Varnish sits in front of it for anonymous traffic.

I am noticing that even though my custom cache data is set for an hour timer, and the Drupal cache is set for 30 minutes, users are able to see data from 3 days ago but I am not sure how. As soon as I go view the site (authenticated) and refresh, the data updates.

I tried backtracking this but nothing jumped out as missing, perhaps other than some cache tags I might need to add. Even still, the render object is what is being shown from cache, which the data is a part of before it is cached, not the cached data item itself.

System cron is running every hour. Shouldn't it purge invalidated cache as part of system_cron?

Edit: I switched my local from Memcache back to the default cache (MySQL) and noticed render cache items all have an expiration of -1.

At what point are entity render cache items invalidated? I feel like that might be my issue, but not sure how to address it.

7
  • "The Drupal page cache time is set to 30 minutes, and Varnish sits in front of it for anonymous traffic." Yes, this is how you are supposed to set up the cache for anonymous traffic, only that the Internal Page Cache doesn't respect the page cache time. Do you have this module still enabled?
    – 4uk4
    Jul 9, 2018 at 19:18
  • Yes, it is enabled, and also says: Required by: Acquia Purge (disabled), Lightning. I just uninstalled it.
    – Kevin
    Jul 9, 2018 at 19:21
  • I assume I do not need that module?
    – Kevin
    Jul 9, 2018 at 19:28
  • No, there is no point in caching pages a second time if you have Varnish sitting in front.
    – 4uk4
    Jul 9, 2018 at 19:32
  • 1
    Other than this specific issue for anonymous traffic there is more you can do. Now you need to set a cache max-age on the whole entity. To make the entity cacheable for a longer time you could think about a service for the API call to use it in a lazy-builder and put a placeholder in the entity.
    – 4uk4
    Jul 10, 2018 at 6:58

1 Answer 1

0

the max-age (maximum age) ... defaults to "permanently (forever) cacheable"

...

Cache contexts, tags and max-age must always be set, because they affect the cacheability of the entire response. Therefore they "bubble": parents automatically receive them.

Cache keys must only be set if the render array should be cached.

from https://www.drupal.org/docs/8/api/render-api/cacheability-of-render-arrays

Render arrays are cached indefinitely by default and setting the page cache expiration time doesn't change the cacheability metadata of render arrays in general. As on the linked page above, ideally you do something like:

// Merges the cache contexts, cache tags and max-age of the config object 
// and user entity that the render array depend on.
$renderer->addCacheableDependency($build, $config);
$renderer->addCacheableDependency($build, \Drupal\user\Entity\User::load($current_user->id())); 

But this doesn't work here because the data lives outside of Drupal - or more specifically, if you add anything that doesn't implement Drupal\Core\Cache\CacheableDependencyInterface as a dependency, the render array is marked as non-cacheable and it bubbles up: see Drupal\Core\Cache\RefinableCacheableDependencyTrait::addCacheableDependency().

So in this case I think you just have to set the max-age yourself.

1
  • I see. I set max-age to five minutes, and see that reflected in the cache table now. I will see how it turns out.
    – Kevin
    Jul 10, 2018 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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