From: Aaron Schulz Date: Thu, 28 May 2015 17:04:19 +0000 (-0700) Subject: objectcache: Add WANObjectCache::resetCheckKey() method X-Git-Tag: 1.31.0-rc.0~10784^2 X-Git-Url: http://git.cyclocoop.org/data/Luca_Pacioli_%28Gemaelde%29.jpeg?a=commitdiff_plain;h=7d5f3efa2fae29db28881ec739e5e7011cf03a51;p=lhc%2Fweb%2Fwiklou.git objectcache: Add WANObjectCache::resetCheckKey() method Change-Id: I6f8b97c1f4511534e1ab2656f472adee491f9d9f --- diff --git a/includes/libs/objectcache/WANObjectCache.php b/includes/libs/objectcache/WANObjectCache.php index c32efb9776..e8837b330b 100644 --- a/includes/libs/objectcache/WANObjectCache.php +++ b/includes/libs/objectcache/WANObjectCache.php @@ -300,8 +300,10 @@ class WANObjectCache { $time = self::parsePurgeValue( $this->cache->get( $key ) ); if ( $time === false ) { - $time = microtime( true ); + // Casting assures identical floats for the next getCheckKeyTime() calls + $time = (string)microtime( true ); $this->cache->add( $key, self::PURGE_VAL_PREFIX . $time, self::CHECK_KEY_TTL ); + $time = (float)$time; } return $time; @@ -320,6 +322,13 @@ class WANObjectCache { * avoid race conditions where dependent keys get updated with a * stale value (e.g. from a DB slave). * + * This is typically useful for keys with static names or some cases + * dynamically generated names where a low number of combinations exist. + * When a few important keys get a large number of hits, a high cache + * time is usually desired as well as lockTSE logic. The resetCheckKey() + * method is less appropriate in such cases since the "time since expiry" + * cannot be inferred. + * * Note that "check" keys won't collide with other regular keys * * @see WANObjectCache::get() @@ -336,6 +345,39 @@ class WANObjectCache { return $this->relayPurge( $key, self::CHECK_KEY_TTL ) && $ok; } + /** + * Delete a "check" key from all clusters, invalidating keys that use it + * + * This is similar to touchCheckKey() in that keys using it via + * getWithSetCallback() will be invalidated. The differences are: + * a) The timestamp will be deleted from all caches and lazily + * re-initialized when accessed (rather than set everywhere) + * b) Thus, dependent keys will be known to be invalid, but not + * for how long (they are treated as "just" purged), which + * effects any lockTSE logic in getWithSetCallback() + * The advantage is that this does not place high TTL keys on every cache + * server, making it better for code that will cache many different keys + * and either does not use lockTSE or uses a low enough TTL anyway. + * + * This is typically useful for keys with dynamically generated names + * where a high number of combinations exist. + * + * Note that "check" keys won't collide with other regular keys + * + * @see WANObjectCache::touchCheckKey() + * @see WANObjectCache::get() + * + * @param string $key Cache key + * @return bool True if the item was purged or not found, false on failure + */ + final public function resetCheckKey( $key ) { + $key = self::TIME_KEY_PREFIX . $key; + // Update the local cluster immediately + $ok = $this->cache->delete( $key ); + // Publish the purge to all clusters + return $this->relayDelete( $key ) && $ok; + } + /** * Method to fetch/regenerate cache keys * @@ -545,6 +587,26 @@ class WANObjectCache { return $ok; } + /** + * Do the actual async bus delete of a key + * + * @param string $key Cache key + * @return bool Success + */ + protected function relayDelete( $key ) { + $event = $this->cache->modifySimpleRelayEvent( array( + 'cmd' => 'delete', + 'key' => $key, + ) ); + + $ok = $this->relayer->notify( "{$this->pool}:purge", $event ); + if ( !$ok ) { + $this->lastRelayError = self::ERR_RELAY; + } + + return $ok; + } + /** * Check if a key should be regenerated (using random probability) * diff --git a/tests/phpunit/includes/objectcache/WANObjectCacheTest.php b/tests/phpunit/includes/objectcache/WANObjectCacheTest.php index 10f64be716..9b4eca7e50 100644 --- a/tests/phpunit/includes/objectcache/WANObjectCacheTest.php +++ b/tests/phpunit/includes/objectcache/WANObjectCacheTest.php @@ -224,6 +224,7 @@ class WANObjectCacheTest extends MediaWikiTestCase { /** * @covers WANObjectCache::touchCheckKey() + * @covers WANObjectCache::resetCheckKey() * @covers WANObjectCache::getCheckKeyTime() */ public function testTouchKeys() { @@ -250,5 +251,13 @@ class WANObjectCacheTest extends MediaWikiTestCase { $t4 = $this->cache->getCheckKeyTime( $key ); $this->assertEquals( $t3, $t4, 'Check key time did not change' ); + + usleep( 1 ); + $this->cache->resetCheckKey( $key ); + $t5 = $this->cache->getCheckKeyTime( $key ); + $this->assertGreaterThan( $t4, $t5, 'Check key time increased' ); + + $t6 = $this->cache->getCheckKeyTime( $key ); + $this->assertEquals( $t5, $t6, 'Check key time did not change' ); } }