Commit 5c52cfff authored by markpavlitski's avatar markpavlitski Committed by Jeremy

Issue #1634506 by markpavlitski: properly flush temporary items.

parent 1279c663
......@@ -97,6 +97,12 @@ class MemCacheDrupal implements DrupalCacheInterface {
// Cache item expired, return FALSE.
$cache = FALSE;
}
// Temporary items created before the cache was last flushed by
// cache_clear_all(NULL, $bin) are invalid.
elseif (!empty($cache->temporary) && $cache->created + $this->cache_lifetime <= $this->cache_temporary_flush) {
// CACHE_TEMPORARY item expired, return FALSE.
$cache = FALSE;
}
// Finally, check for wildcard clears against this cid.
else {
if (!$this->wildcard_valid($cid, $cache)) {
......@@ -147,15 +153,19 @@ class MemCacheDrupal implements DrupalCacheInterface {
// Convert CACHE_TEMPORARY (-1) into something that will live in memcache
// until the next flush.
$cache->expire = REQUEST_TIME + 2591999;
// This is a temporary cache item.
$cache->temporary = TRUE;
}
// Expire time is in seconds if less than 30 days, otherwise is a timestamp.
else if ($expire != CACHE_PERMANENT && $expire < 2592000) {
// Expire is expressed in seconds, convert to the proper future timestamp
// as expected in dmemcache_get().
$cache->expire = REQUEST_TIME + $expire;
$cache->temporary = FALSE;
}
else {
$cache->expire = $expire;
$cache->temporary = FALSE;
}
// Manually track the expire time in $cache->expire. When the object
......@@ -212,10 +222,16 @@ class MemCacheDrupal implements DrupalCacheInterface {
}
if (empty($cid) || $wildcard === TRUE) {
// system_cron() flushes all cache bins returned by hook_flush_caches()
// with cache_clear_all(NULL, $bin); This is for garbage collection with
// the database cache, but serves no purpose with memcache. So return
// early here.
// with cache_clear_all(NULL, $bin); The expected behaviour in this case
// is to perform garbage collection on expired cache items (which is
// irrelevant to memcache) but also to remove all CACHE_TEMPORARY items.
// @see https://api.drupal.org/api/drupal/includes!cache.inc/function/cache_clear_all/7
if (!isset($cid)) {
// Update the timestamp of the last CACHE_TEMPORARY clear. All
// temporary cache items created before this will be invalidated.
$this->cache_temporary_flush = time();
$this->variable_set("cache_temporary_flush_$this->bin", $this->cache_temporary_flush);
// Return early here as we do not want to register a wildcard flush.
return;
}
elseif ($cid == '*') {
......@@ -421,6 +437,7 @@ class MemCacheDrupal implements DrupalCacheInterface {
$this->cache_lifetime = variable_get('cache_lifetime', 0);
$this->cache_flush = variable_get('cache_flush_' . $this->bin);
$this->cache_content_flush = variable_get('cache_content_flush_' . $this->bin, 0);
$this->cache_temporary_flush = variable_get('cache_temporary_flush_' . $this->bin, 0);
$this->flushed = min($this->cache_flush, REQUEST_TIME - $this->cache_lifetime);
}
......
......@@ -393,6 +393,30 @@ class MemCacheClearCase extends MemcacheTestCase {
$this->assertCacheRemoved(t('Foofoo cache invalidated.'), 'foofoo');
}
/**
* Test CACHE_TEMPORARY and CACHE_PERMANENT behaviour.
*/
function testClearTemporaryPermanent() {
cache_set('test_cid_clear_temporary', $this->default_value, $this->default_bin, CACHE_TEMPORARY);
cache_set('test_cid_clear_permanent', $this->default_value, $this->default_bin, CACHE_PERMANENT);
cache_set('test_cid_clear_future', $this->default_value, $this->default_bin, time() + 3600);
$this->assertTrue($this->checkCacheExists('test_cid_clear_temporary', $this->default_value)
&& $this->checkCacheExists('test_cid_clear_permanent', $this->default_value)
&& $this->checkCacheExists('test_cid_clear_future', $this->default_value),
t('Three cache items were created for checking cache expiry.'));
// This should clear only expirable items (CACHE_TEMPORARY).
cache_clear_all(NULL, $this->default_bin, TRUE);
$this->assertFalse($this->checkCacheExists('test_cid_clear_temporary', $this->default_value),
t('Temporary cache item was removed after clearing cid NULL.'));
$this->assertTrue($this->checkCacheExists('test_cid_clear_permanent', $this->default_value),
t('Permanent cache item was not removed after clearing cid NULL.'));
$this->assertTrue($this->checkCacheExists('test_cid_clear_future', $this->default_value),
t('Future cache item was not removed after clearing cid NULL.'));
}
/**
* Test clearing using a cid.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment