diff --git a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php index 796573ced34..753e6a3e27e 100644 --- a/core/lib/Drupal/Core/Cache/CacheBackendInterface.php +++ b/core/lib/Drupal/Core/Cache/CacheBackendInterface.php @@ -68,6 +68,12 @@ interface CacheBackendInterface { /** * Stores data in the persistent cache. * + * Core cache implementations set the created time on cache item with + * microtime(TRUE) rather than REQUEST_TIME_FLOAT, because the created time + * of cache items should match when they are created, not when the request + * started. Apart from being more accurate, this increases the chance an + * item will legitimately be considered valid. + * * @param string $cid * The cache ID of the data to store. * @param mixed $data diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php index 3f15f43358f..09e7e827ee3 100644 --- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php @@ -180,7 +180,7 @@ class DatabaseBackend implements CacheBackendInterface { $checksum = $this->checksumTags($flat_tags); $fields = array( 'serialized' => 0, - 'created' => REQUEST_TIME, + 'created' => round(microtime(TRUE), 3), 'expire' => $expire, 'tags' => implode(' ', $flat_tags), 'checksum_invalidations' => $checksum['invalidations'], @@ -575,8 +575,10 @@ class DatabaseBackend implements CacheBackendInterface { 'default' => 0, ), 'created' => array( - 'description' => 'A Unix timestamp indicating when the cache entry was created.', - 'type' => 'int', + 'description' => 'A timestamp with millisecond precision indicating when the cache entry was created.', + 'type' => 'numeric', + 'precision' => 14, + 'scale' => 3, 'not null' => TRUE, 'default' => 0, ), diff --git a/core/lib/Drupal/Core/Cache/PhpBackend.php b/core/lib/Drupal/Core/Cache/PhpBackend.php index 81f5876d0c8..6c7fdd238f7 100644 --- a/core/lib/Drupal/Core/Cache/PhpBackend.php +++ b/core/lib/Drupal/Core/Cache/PhpBackend.php @@ -121,7 +121,7 @@ class PhpBackend implements CacheBackendInterface { $item = (object) array( 'cid' => $cid, 'data' => $data, - 'created' => REQUEST_TIME, + 'created' => round(microtime(TRUE), 3), 'expire' => $expire, ); $item->tags = $this->flattenTags($tags); diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php index 0a9108cbe10..5df23c985b6 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericCacheBackendUnitTestBase.php @@ -142,7 +142,7 @@ abstract class GenericCacheBackendUnitTestBase extends DrupalUnitTestBase { $this->assert(is_object($cached), "Backend returned an object for cache id test1."); $this->assertIdentical($with_backslash, $cached->data); $this->assertTrue($cached->valid, 'Item is marked as valid.'); - $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertTrue($cached->created >= REQUEST_TIME && $cached->created < microtime(TRUE), 'Created time is correct.'); $this->assertEqual($cached->expire, Cache::PERMANENT, 'Expire time is correct.'); $this->assertIdentical(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2."); @@ -151,7 +151,7 @@ abstract class GenericCacheBackendUnitTestBase extends DrupalUnitTestBase { $this->assert(is_object($cached), "Backend returned an object for cache id test2."); $this->assertIdentical(array('value' => 3), $cached->data); $this->assertTrue($cached->valid, 'Item is marked as valid.'); - $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertTrue($cached->created >= REQUEST_TIME && $cached->created < microtime(TRUE), 'Created time is correct.'); $this->assertEqual($cached->expire, REQUEST_TIME + 3, 'Expire time is correct.'); $backend->set('test3', 'foobar', REQUEST_TIME - 3); @@ -159,7 +159,7 @@ abstract class GenericCacheBackendUnitTestBase extends DrupalUnitTestBase { $cached = $backend->get('test3', TRUE); $this->assert(is_object($cached), 'Backend returned an object for cache id test3.'); $this->assertFalse($cached->valid, 'Item is marked as valid.'); - $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertTrue($cached->created >= REQUEST_TIME && $cached->created < microtime(TRUE), 'Created time is correct.'); $this->assertEqual($cached->expire, REQUEST_TIME - 3, 'Expire time is correct.'); $this->assertIdentical(FALSE, $backend->get('test4'), "Backend does not contain data for cache id test4."); @@ -169,7 +169,7 @@ abstract class GenericCacheBackendUnitTestBase extends DrupalUnitTestBase { $this->assert(is_object($cached), "Backend returned an object for cache id test4."); $this->assertIdentical($with_eof, $cached->data); $this->assertTrue($cached->valid, 'Item is marked as valid.'); - $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertTrue($cached->created >= REQUEST_TIME && $cached->created < microtime(TRUE), 'Created time is correct.'); $this->assertEqual($cached->expire, Cache::PERMANENT, 'Expire time is correct.'); $this->assertIdentical(FALSE, $backend->get('test5'), "Backend does not contain data for cache id test5."); @@ -179,7 +179,7 @@ abstract class GenericCacheBackendUnitTestBase extends DrupalUnitTestBase { $this->assert(is_object($cached), "Backend returned an object for cache id test5."); $this->assertIdentical($with_eof_and_semicolon, $cached->data); $this->assertTrue($cached->valid, 'Item is marked as valid.'); - $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertTrue($cached->created >= REQUEST_TIME && $cached->created < microtime(TRUE), 'Created time is correct.'); $this->assertEqual($cached->expire, Cache::PERMANENT, 'Expire time is correct.'); $with_variable = array('foo' => '$bar'); @@ -274,7 +274,7 @@ abstract class GenericCacheBackendUnitTestBase extends DrupalUnitTestBase { $this->assert(isset($ret['test7']), "Existing cache id test7 is set."); // Test return - ensure that objects has expected properties. $this->assertTrue($ret['test2']->valid, 'Item is marked as valid.'); - $this->assertEqual($ret['test2']->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertTrue($ret['test2']->created >= REQUEST_TIME && $ret['test2']->created < microtime(TRUE), 'Created time is correct.'); $this->assertEqual($ret['test2']->expire, Cache::PERMANENT, 'Expire time is correct.'); // Test return - ensure it does not contain nonexistent cache ids. $this->assertFalse(isset($ret['test19']), "Nonexistent cache id test19 is not set.");