Skip to content

Instantly share code, notes, and snippets.

@gschoppe
Last active August 29, 2015 14:21
Show Gist options
  • Save gschoppe/e5871149c7a8f9fb94d2 to your computer and use it in GitHub Desktop.
Save gschoppe/e5871149c7a8f9fb94d2 to your computer and use it in GitHub Desktop.
PHP Minimal Filesystem Function Cache
<?php
// PHP Minimal Filesystem Function Cache
// by Greg Schoppe (http://gschoppe.com)
// copyright 2015 Greg Schoppe, GPL, BSD, and MIT licensed
// takes a function name as a string, and an array of the arguments to be passed to that function
// caches and returns the results of that function call (or the cached copy, if less than $TTL seconds old)
// Useful for rate-limiting cURL requests, or other high resource or rate limited functions
// WARNING: DO NOT USE WITH ANONYMOUS FUNCTIONS (AKA: CLOSURES), ANY FUNCTION THAT PRODUCES SIDE EFFECTS,
// OR WITH ANY FUNCTION THAT DOES NOT RETURN A SERIALIZABLE VALUE
function callFunctionWithCache($functionName, $arguments = array(), $TTL=3600, $purgeCache=false) {
$cacheFolder = "cache/";
$manageCache = true; // set to false if you intend to manage the cache folder with a cron job
$cacheFileCap = 1000; // max number of files to cache
$cacheMaxSize = pow(1024, 2)*32; // max total size of cache files in bytes (e.g. pow(1024, 2)*32 = 32Mb)
$hysteresis = .8; // when cache is cleaned, it will be culled back to this percent of the max, to prevent cache management from ocurring every time the script is run
$cacheFile = $TTL."-".$cacheFolder.md5(serialize($functionName))."-".md5(serialize($arguments)).".cache";
// check cache
if(file_exists($cacheFile) && ((time()-filemtime($cacheFile)) < $TTL)) {
// get cached copy
$response = json_decode(file_get_contents($cacheFile));
} else {
// do function call
$response = call_user_func_array($functionName, $arguments);
// store to cache
$cache = json_encode($response);
// only store if string is smaller than max cache size
if(mb_strlen($cache, '8bit') < $cacheMaxSize) {
file_put_contents($cacheFile, json_encode($response));
}
// clean up cache
if($manageCache) {
$filecount = 0;
$files = glob($cacheFolder . "*.cache");
if ($files) $filecount = count($files);
$cacheSize = array_reduce($files, function($a, $b) {
return($a + filesize($b));
}, 0);
if( ($filecount > $cacheFileCap) || ($cacheSize > $cacheMaxSize) ) {
$cullCount = $filecount-($cacheFileCap*$hysteresis);
$cullSize = $cacheSize-($cacheMaxSize*$hysteresis);
usort($files, function($a, $b) {
return filemtime($a) < filemtime($b);
});
$doCull = true;
foreach($files as $file) {
if($cullCount<=0 && $cullSize <=0)
$doCull = false;
$fileParts = explode('/', $file);
$fileName = array_pop($fileParts);
$fileNameParts = explode('-', $fileName);
$fileTTL = intval(array_pop($fileNameParts));
if((time()-filemtime($file)) > $fileTTL || $doCull) {
$filesize = filesize($file);
if(is_file($file))
unlink($file);
$cullSize -= $filesize;
$cullCount--;
}
}
}
}
}
// empty cache if requested
if($purgeCache) {
$files = glob($cacheFolder . "*.cache");
if ($files) {
foreach($files as $file) {
if(is_file($file))
unlink($file);
}
}
}
// return content
return $response;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment