Allow for dynamic TTLs in getWithSetCallback()
authorAaron Schulz <aschulz@wikimedia.org>
Mon, 11 May 2015 17:03:55 +0000 (10:03 -0700)
committerAaron Schulz <aschulz@wikimedia.org>
Tue, 12 May 2015 20:04:53 +0000 (13:04 -0700)
* This gives it better parity with BagOStuff::set()
* Also updated some doc comments

Change-Id: Ib94b97715fae901bac1750656e3dc7501919d6d2

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

index 92bd0bd..21a09e6 100755 (executable)
@@ -300,10 +300,13 @@ class WANObjectCache {
        /**
         * Method to fetch/regenerate cache keys
         *
-        * On cache miss, the key will be set to the callback result.
+        * On cache miss, the key will be set to the callback result,
+        * unless the callback returns false. The arguments supplied are:
+        *     (current value or false, &$ttl)
         * The callback function returns the new value given the current
-        * value (false if not present). If false is returned, then nothing
-        * will be saved to cache.
+        * value (false if not present). Preemptive re-caching and $checkKeys
+        * can result in a non-false current value. The TTL of the new value
+        * can be set dynamically by altering $ttl in the callback (by reference).
         *
         * Usually, callbacks ignore the current value, but it can be used
         * to maintain "most recent X" values that come from time or sequence
@@ -326,7 +329,7 @@ class WANObjectCache {
         * @code
         *     $key = wfMemcKey( 'cat-recent-actions', $catId );
         *     // Function that derives the new key value given the old value
-        *     $callback = function( $cValue ) { ... };
+        *     $callback = function( $cValue, &$ttl ) { ... };
         *     // Get the key value from cache or from source on cache miss;
         *     // try to only let one cluster thread manage doing cache updates
         *     $opts = array( 'lockTSE' => 5, 'lowTTL' => 10 );
@@ -419,7 +422,7 @@ class WANObjectCache {
                }
 
                // Generate the new value from the callback...
-               $value = call_user_func( $callback, $cValue );
+               $value = call_user_func_array( $callback, array( $cValue, &$ttl ) );
                // When delete() is called, writes are write-holed by the tombstone,
                // so use a special stash key to pass the new value around threads.
                if ( $value !== false && ( $isHot || $isTombstone ) ) {
index 3161d18..3e284c8 100644 (file)
@@ -86,13 +86,22 @@ class WANObjectCacheTest extends MediaWikiTestCase {
                $cKey2 = wfRandomString();
 
                $wasSet = 0;
-               $func = function() use ( &$wasSet, $value ) { ++$wasSet; return $value; };
+               $func = function( $old, &$ttl ) use ( &$wasSet, $value ) {
+                       ++$wasSet;
+                       $ttl = 20; // override with another value
+                       return $value;
+               };
 
                $wasSet = 0;
                $v = $cache->getWithSetCallback( $key, $func, 30, array(), array( 'lockTSE' => 5 ) );
                $this->assertEquals( $v, $value );
                $this->assertEquals( 1, $wasSet, "Value regenerated" );
 
+               $curTTL = null;
+               $v = $cache->get( $key, $curTTL );
+               $this->assertLessThanOrEqual( 20, $curTTL, 'Current TTL between 19-20 (overriden)' );
+               $this->assertGreaterThanOrEqual( 19, $curTTL, 'Current TTL between 19-20 (overriden)' );
+
                $wasSet = 0;
                $v = $cache->getWithSetCallback( $key, $func, 30, array(), array( 'lockTSE' => 5 ) );
                $this->assertEquals( $v, $value );