Last active
August 29, 2015 14:10
-
-
Save lavoiesl/9cdc5893a71c53e16b47 to your computer and use it in GitHub Desktop.
Get a value from a Doctrine Cache or compute it using a callback, including stampede protection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Get a value from the cache or compute it using a callback | |
* Includes cache stampede protection | |
* @link http://en.wikipedia.org/wiki/Cache_stampede | |
* @link http://blog.lavoie.sl/2014/12/preventing-cache-stampede-using-doctrine-cache.html | |
* @global cache Doctrine\Common\Cache\Cache | |
* | |
* @param string $key Cache key | |
* @param Closure $callback Computing function | |
* @param float $ttl Seconds | |
* @param float $stampedeTtl Seconds before cache stampede expires | |
* Should be about 2-3 times the estimated time to build the cache | |
* @return mixed | |
*/ | |
function cacheGetDefault($key, Closure $callback, $ttl = 0, $stampedeTtl = null) | |
{ | |
global $cache; | |
$data = $cache->fetch($key); | |
if (false !== $data) { | |
return $data; | |
} | |
if (null !== $stampede) { | |
$stampede = max((double) $stampede, 0.001); // prevention for infinite ttl | |
// data is being computed, wait | |
while ('__STAMPEDE__' === $data) { | |
// wait 1/20th of the stampede TTL, to give the CPU a chance | |
sleep($stampede / 20); | |
$data = $cache->fetch($key); | |
} | |
} | |
if ($data === false) { | |
if (null !== $stampedeTtl) { | |
// acquire lock | |
$cache->save($key, '__STAMPEDE__', $stampedeTtl); | |
} | |
// compute the actual data | |
$data = $callback(); | |
} | |
$cache->save($key, $data, $ttl); | |
return $data; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$cacheTtl = 3600; // an hour | |
$stampedeTtl = 5; // seconds before releasing lock | |
cacheGetDefault('recent_tweets', function() { | |
return file_get_contents('https://api.twitter.com/1.1/search/tweets.json?q=@lavoiesl'); | |
}, $cacheTtl, $stampedeTtl); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment