Skip to content

Instantly share code, notes, and snippets.

@JanTvrdik
Last active December 13, 2016 21:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JanTvrdik/f76d98b818abdde26cb4 to your computer and use it in GitHub Desktop.
Save JanTvrdik/f76d98b818abdde26cb4 to your computer and use it in GitHub Desktop.
General purpose thread-safe cache function
<?php
/**
* @param string $file
* @param callable $tryLoad (string $file, mixed & $data): bool
* @param callable $isExpired (string $file): bool
* @param callable $fallback (string $file): string
* @return mixed
*/
function loadCacheFile($file, $tryLoad, $isExpired, $fallback)
{
if (!$isExpired($file) && $tryLoad($file, $data)) {
return $data;
}
if (!is_dir(dirname($file))) {
@mkdir(dirname($file)); // @ - directory may already exist
}
$handle = fopen("$file.lock", 'c+');
if (!$handle || !flock($handle, LOCK_EX)) {
throw new \RuntimeException("Unable to acquire exclusive lock '$file.lock'.");
}
if (!is_file($file) || $isExpired($file)) {
$data = $fallback($file);
if (file_put_contents("$file.tmp", $data) !== strlen($data) || !rename("$file.tmp", $file)) {
@unlink("$file.tmp"); // @ - file may not exist
throw new \RuntimeException("Unable to create '$file'.");
}
}
if (!$tryLoad($file, $data)) {
throw new \RuntimeException("Unable to load '$file'.");
}
flock($handle, LOCK_UN);
return $data;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment