CachedBagOStuff: cache backend misses
authorBryan Davis <bd808@wikimedia.org>
Tue, 23 Feb 2016 01:45:20 +0000 (18:45 -0700)
committerBryan Davis <bd808@wikimedia.org>
Tue, 23 Feb 2016 01:45:20 +0000 (18:45 -0700)
Cache misses from the backend cache the same as hits.

Bug: T127772
Change-Id: If2fe1920411b24862acea888c627db13717da8bd

includes/libs/objectcache/CachedBagOStuff.php
includes/libs/objectcache/HashBagOStuff.php
tests/phpunit/includes/libs/objectcache/CachedBagOStuffTest.php

index 798357d..3d5d383 100644 (file)
@@ -50,11 +50,9 @@ class CachedBagOStuff extends HashBagOStuff {
 
        protected function doGet( $key, $flags = 0 ) {
                $ret = parent::doGet( $key, $flags );
-               if ( $ret === false ) {
+               if ( $ret === false && !$this->hasKey( $key ) ) {
                        $ret = $this->backend->doGet( $key, $flags );
-                       if ( $ret !== false ) {
-                               $this->set( $key, $ret, 0, self::WRITE_CACHE_ONLY );
-                       }
+                       $this->set( $key, $ret, 0, self::WRITE_CACHE_ONLY );
                }
                return $ret;
        }
index 6e7fb0c..e03cec6 100644 (file)
@@ -60,8 +60,19 @@ class HashBagOStuff extends BagOStuff {
                return true;
        }
 
+       /**
+        * Does this bag have a non-null value for the given key?
+        *
+        * @param string $key
+        * @return bool
+        * @since 1.27
+        */
+       protected function hasKey( $key ) {
+               return isset( $this->bag[$key] );
+       }
+
        protected function doGet( $key, $flags = 0 ) {
-               if ( !isset( $this->bag[$key] ) ) {
+               if ( !$this->hasKey( $key ) ) {
                        return false;
                }
 
index 3b19c9a..7fe8055 100644 (file)
@@ -49,4 +49,22 @@ class CachedBagOStuffTest extends PHPUnit_Framework_TestCase {
                $cache->delete( 'foo', CachedBagOStuff::WRITE_CACHE_ONLY );
                $this->assertEquals( 'old', $cache->get( 'foo' ) ); // Reloaded from backend
        }
+
+       public function testCacheBackendMisses() {
+               $backend = new HashBagOStuff;
+               $cache = new CachedBagOStuff( $backend );
+
+               // First hit primes the cache with miss from the backend
+               $this->assertEquals( false, $cache->get( 'foo' ) );
+
+               // Change the value in the backend
+               $backend->set( 'foo', true );
+
+               // Second hit returns the cached miss
+               $this->assertEquals( false, $cache->get( 'foo' ) );
+
+               // But a fresh value is read from the backend
+               $backend->set( 'bar', true );
+               $this->assertEquals( true, $cache->get( 'bar' ) );
+       }
 }