Made WANObjectCache::getCheckKey() automatically init the key
authorAaron Schulz <aschulz@wikimedia.org>
Fri, 22 May 2015 05:46:25 +0000 (22:46 -0700)
committerOri.livneh <ori@wikimedia.org>
Thu, 2 Jul 2015 07:13:22 +0000 (07:13 +0000)
* This still allows If-Modified-Since logic but does not
  need to broadcast initialization values just because a
  key fell out of cache. The value can differ between DCs
  anyway via skew, this just lets them drift more. Actual
  purge events are still broadcasted, which is what matters.
* The User class has now been simplified given this change.
* Added more general comments to getCheckKeyTime().

Change-Id: Ic1f4bbb1947e0d1dd47499c9e9dc86991c30580c

includes/User.php
includes/libs/objectcache/WANObjectCache.php
tests/phpunit/includes/objectcache/WANObjectCacheTest.php

index 46d53b8..63c0d37 100644 (file)
@@ -2326,6 +2326,10 @@ class User implements IDBAccessObject {
 
        /**
         * Get the user touched timestamp
+        *
+        * Use this value only to validate caches via inequalities
+        * such as in the case of HTTP If-Modified-Since response logic
+        *
         * @return string TS_MW Timestamp
         */
        public function getTouched() {
@@ -2334,14 +2338,9 @@ class User implements IDBAccessObject {
                if ( $this->mId ) {
                        if ( $this->mQuickTouched === null ) {
                                $key = wfMemcKey( 'user-quicktouched', 'id', $this->mId );
+                               $cache = ObjectCache::getMainWANInstance();
 
-                               $timestamp = ObjectCache::getMainWANInstance()->getCheckKeyTime( $key );
-                               if ( $timestamp ) {
-                                       $this->mQuickTouched = wfTimestamp( TS_MW, (int)$timestamp );
-                               } else {
-                                       # Set the timestamp to get HTTP 304 cache hits
-                                       $this->touch();
-                               }
+                               $this->mQuickTouched = wfTimestamp( TS_MW, $cache->getCheckKeyTime( $key ) );
                        }
 
                        return max( $this->mTouched, $this->mQuickTouched );
index 5d9557a..c32efb9 100644 (file)
@@ -279,13 +279,32 @@ class WANObjectCache {
        /**
         * Fetch the value of a timestamp "check" key
         *
+        * The key will be *initialized* to the current time if not set,
+        * so only call this method if this behavior is actually desired
+        *
+        * The timestamp can be used to check whether a cached value is valid.
+        * Callers should not assume that this returns the same timestamp in
+        * all datacenters due to relay delays.
+        *
+        * The level of staleness can roughly be estimated from this key, but
+        * if the key was evicted from cache, such calculations may show the
+        * time since expiry as ~0 seconds.
+        *
         * Note that "check" keys won't collide with other regular keys
         *
         * @param string $key
-        * @return float|bool TS_UNIX timestamp of the key; false if not present
+        * @return float UNIX timestamp of the key
         */
        final public function getCheckKeyTime( $key ) {
-               return self::parsePurgeValue( $this->cache->get( self::TIME_KEY_PREFIX . $key ) );
+               $key = self::TIME_KEY_PREFIX . $key;
+
+               $time = self::parsePurgeValue( $this->cache->get( $key ) );
+               if ( $time === false ) {
+                       $time = microtime( true );
+                       $this->cache->add( $key, self::PURGE_VAL_PREFIX . $time, self::CHECK_KEY_TTL );
+               }
+
+               return $time;
        }
 
        /**
index 47a83b3..10f64be 100644 (file)
@@ -229,8 +229,10 @@ class WANObjectCacheTest extends MediaWikiTestCase {
        public function testTouchKeys() {
                $key = wfRandomString();
 
+               $priorTime = microtime( true );
+               usleep( 1 );
                $t0 = $this->cache->getCheckKeyTime( $key );
-               $this->assertFalse( $t0, 'Check key time is false' );
+               $this->assertGreaterThanOrEqual( $priorTime, $t0, 'Check key auto-created' );
 
                $priorTime = microtime( true );
                usleep( 1 );