5

I'm trying to figure out how Drupal's cron effects the page cache of my site. It would be nice to store as many pages in the cache table as possible so that when requests are made they are being served from the page cache!

However I am getting conflicting answers on the effect of Drupal's cron job on the cache!

This link says that "each cron run clears the cache for all pages":

http://tomroelandts.com/articles/how-to-ensure-that-visitors-always-see-cached-pages-in-drupal-7

as well as -> drupal.org/node/1576686

But this guy, says it only clears caches that can be expired:

https://www.drupal.org/node/1691116#comment-6352756

Would love to get a definitive answer on this!

6

System module's system_cron() clears expirable entries from cache tables. An expirable cache entry is one that is beyond its "can expire" date, or it's an entry that was initially saved with the CACHE_TEMPORARY flag.

Assuming you're using the default database cache, you can see which entries are expirable by looking in a cache table. The "expire" column contains the timestamp at which an entry becomes expirable. If the value is "-1", it's CACHE_TEMPORARY and always expirable.

As far as Drupal's default database page cache goes, the "expire" column won't tell you much, since the minimum cache lifetime is not applied to the expire value. Instead, Drupal keeps track of the last time the entire cache was flushed, and will not flush the page cache again until at least "minimum cache lifetime" seconds have passed.

  • Thanks, this is really helpful! 1.) Is there a way to turn this off without turning off cron? Specifically the expiration of the page cache tables? Is that bad practice? 2.) So if the minimum cache lifetime is set to 0 and by default the the column is CACHE_TEMPORARY the page cache will clear every cron. – Nick Dynan Feb 15 '15 at 21:16
  • 2
    There are a couple options I could recommend: (a) Use Elysia Cron module instead of regular Drupal cron, which would let you run system_cron() on a separate schedule from other cron functions; or (b) set a minimum cache lifetime and use Expire module to selectively clear some entries prematurely when certain events fire. – Les Lim Feb 15 '15 at 21:25
  • Awesome. A question per each answer: a.) Would it be detrimental to make system cron long, for example 1 week. Are there other functions that could get screwy doing this? b.) I am using Expire atm and it's well and good. It's my understanding if I set a min cache lifetime, even Expire can't clear the page cache, is that correct? Or at least the cache won't invalidate until the mcl is reached. I am clearing from a CDN when I save a story with some post-save hooks, I need to be able to clear the pages caches so the CDN gets the right version! – Nick Dynan Feb 15 '15 at 21:42
  • 1
    (a) I'd still run system_cron() daily, since it does some other cleanup tasks. Besides, a week-long cache really isn't much more performant than a day-long cache. You're still going to get a pretty good hit rate on that cache whether it's a day or a week. (b) Expire module absolutely can clear cache entries before Minimum Cache Lifetime is reached. The settings can be finicky, though, and it gets more complicated as you add other cache layers like Varnish or CDN. – Les Lim Feb 15 '15 at 21:53
  • Yes I'm finding that, Expires has an internal and external setting. I have it set to external for a CDN, but need the internal to clear out the MCL. I kinda hacked the Expire module, not the right way to do it. But it can overwrite the MCL & Externally Purge. Call the executeInternalExpiration function inside the external one.... elseif ($status == EXPIRE_STATUS_ENABLED_EXTERNAL) { self::executeInternalExpiration($urls, $wildcards); self::executeExternalExpiration($urls, $wildcards, $object_type, $object); } – Nick Dynan Feb 17 '15 at 7:56
5

The page cache is cleared on cron every time if the minimum cache lifetime is set at the default of none. If the minimum cache lifetime is set, cron deletes all cache entries no more than once per the minimum cache lifetime setting.

Inside of drupal_page_set_cache() you can see that 'expire' => CACHE_TEMPORARY,.

With the core database cache, it ignores the minimum cache lifetime on clears. When you look at the code in DrupalDatabaseCache::clear; there is zero code in there that has to do with when the cache was created; thus the minimum cache lifetime is not enforced. Inside of system_cron one of the caches that gets cleared is cache_page.

If you wish to change this you can change how often system_cron runs; elysia cron is a good way to do this. But be aware that any node save from the GUI will also clear the page cache as well; see node_form_submit, at the bottom it will clear the page cache. Same is true for any comments saved, see comment_form_submit().

The best solution is to change how the page cache works. Have it respect the minimum cache lifetime. There are 2 modules that enforce this:
https://www.drupal.org/project/apdqc Asynchronous Prefetch Database Query Cache
https://www.drupal.org/project/adbc Alternative Database Cache
ADBC was created to make the minimum cache lifetime more useable & is database agnostic. APDQC has all of ADBC in it but it also gets rid of deadlock and metadata lock issues when using MySQL as well as speeding up cache get and set calls; only works with MySQL. If you're using MySQL I would recommend using APDQC; if you're using a different database then ADBC is the way to go.

Once the minimum is enforced you do need a way to update that cached page if it was actually updated. The Cache Expiration module can do this for you.

D7 issue: https://www.drupal.org/node/891600

  • 1
    DrupalDatabaseCashe::clear does respect cache_lifetime, though. It just applies per cache bin, not per cache entry. So calls to cache_clear_all() like in system_cron() or node_form_submit() are not guaranteed to clear the page cache if cache_lifetime > 0. – Les Lim Feb 16 '15 at 17:37
  • 1
    By default every item inside of the cache_page bin is CACHE_TEMPORARY. Same is true for every item inside of cache_blocks; see _block_render_blocks(). – mikeytown2 Feb 16 '15 at 18:25
  • 1
    That's true, per cache entry. What I'm saying is that DrupalDatabaseCache::clear doesn't actually perform any db_delete operations on the bin unless cache_lifetime seconds have passed since the last time the bin was cleared. – Les Lim Feb 16 '15 at 20:00

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.