[Cache] add logs on early-recomputation and locking
This commit is contained in:
parent
755f41192f
commit
847a9bb86d
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Cache;
|
namespace Symfony\Component\Cache;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Contracts\Cache\CacheInterface;
|
use Symfony\Contracts\Cache\CacheInterface;
|
||||||
use Symfony\Contracts\Cache\ItemInterface;
|
use Symfony\Contracts\Cache\ItemInterface;
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ final class LockRegistry
|
|||||||
return $previousFiles;
|
return $previousFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata = null)
|
public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata = null, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
$key = self::$files ? crc32($item->getKey()) % \count(self::$files) : -1;
|
$key = self::$files ? crc32($item->getKey()) % \count(self::$files) : -1;
|
||||||
|
|
||||||
@ -87,6 +88,7 @@ final class LockRegistry
|
|||||||
try {
|
try {
|
||||||
// race to get the lock in non-blocking mode
|
// race to get the lock in non-blocking mode
|
||||||
if (flock($lock, LOCK_EX | LOCK_NB)) {
|
if (flock($lock, LOCK_EX | LOCK_NB)) {
|
||||||
|
$logger && $logger->info('Lock acquired, now computing item "{key}"', ['key' => $item->getKey()]);
|
||||||
self::$lockedFiles[$key] = true;
|
self::$lockedFiles[$key] = true;
|
||||||
|
|
||||||
$value = $callback($item, $save);
|
$value = $callback($item, $save);
|
||||||
@ -103,6 +105,7 @@ final class LockRegistry
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
// if we failed the race, retry locking in blocking mode to wait for the winner
|
// if we failed the race, retry locking in blocking mode to wait for the winner
|
||||||
|
$logger && $logger->info('Item "{key}" is locked, waiting for it to be released', ['key' => $item->getKey()]);
|
||||||
flock($lock, LOCK_SH);
|
flock($lock, LOCK_SH);
|
||||||
} finally {
|
} finally {
|
||||||
flock($lock, LOCK_UN);
|
flock($lock, LOCK_UN);
|
||||||
@ -114,6 +117,7 @@ final class LockRegistry
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$value = $pool->get($item->getKey(), $signalingCallback, 0);
|
$value = $pool->get($item->getKey(), $signalingCallback, 0);
|
||||||
|
$logger && $logger->info('Item "{key}" retrieved after lock was released', ['key' => $item->getKey()]);
|
||||||
$save = false;
|
$save = false;
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
@ -121,6 +125,7 @@ final class LockRegistry
|
|||||||
if ($signalingException !== $e) {
|
if ($signalingException !== $e) {
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
$logger && $logger->info('Item "{key}" not found while lock was released, now retrying', ['key' => $item->getKey()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Cache\Traits;
|
namespace Symfony\Component\Cache\Traits;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Component\Cache\Adapter\AdapterInterface;
|
use Symfony\Component\Cache\Adapter\AdapterInterface;
|
||||||
use Symfony\Component\Cache\CacheItem;
|
use Symfony\Component\Cache\CacheItem;
|
||||||
use Symfony\Component\Cache\Exception\InvalidArgumentException;
|
use Symfony\Component\Cache\Exception\InvalidArgumentException;
|
||||||
@ -40,7 +41,7 @@ trait ContractsTrait
|
|||||||
public function setCallbackWrapper(?callable $callbackWrapper): callable
|
public function setCallbackWrapper(?callable $callbackWrapper): callable
|
||||||
{
|
{
|
||||||
$previousWrapper = $this->callbackWrapper;
|
$previousWrapper = $this->callbackWrapper;
|
||||||
$this->callbackWrapper = $callbackWrapper ?? function (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata) {
|
$this->callbackWrapper = $callbackWrapper ?? function (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger) {
|
||||||
return $callback($item, $save);
|
return $callback($item, $save);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,13 +83,13 @@ trait ContractsTrait
|
|||||||
try {
|
try {
|
||||||
$value = $callbackWrapper($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) {
|
$value = $callbackWrapper($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) {
|
||||||
$setMetadata($item, $startTime, $metadata);
|
$setMetadata($item, $startTime, $metadata);
|
||||||
});
|
}, $this->logger ?? null);
|
||||||
$setMetadata($item, $startTime, $metadata);
|
$setMetadata($item, $startTime, $metadata);
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
} finally {
|
} finally {
|
||||||
$this->callbackWrapper = $callbackWrapper;
|
$this->callbackWrapper = $callbackWrapper;
|
||||||
}
|
}
|
||||||
}, $beta, $metadata);
|
}, $beta, $metadata, $this->logger ?? null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace Symfony\Contracts\Cache;
|
|||||||
|
|
||||||
use Psr\Cache\CacheItemPoolInterface;
|
use Psr\Cache\CacheItemPoolInterface;
|
||||||
use Psr\Cache\InvalidArgumentException;
|
use Psr\Cache\InvalidArgumentException;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes.
|
* An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes.
|
||||||
@ -37,7 +38,7 @@ trait CacheTrait
|
|||||||
return $this->deleteItem($key);
|
return $this->deleteItem($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null)
|
private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
if (0 > $beta = $beta ?? 1.0) {
|
if (0 > $beta = $beta ?? 1.0) {
|
||||||
throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', \get_class($this), $beta)) extends \InvalidArgumentException implements InvalidArgumentException {
|
throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', \get_class($this), $beta)) extends \InvalidArgumentException implements InvalidArgumentException {
|
||||||
@ -52,9 +53,13 @@ trait CacheTrait
|
|||||||
$expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false;
|
$expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false;
|
||||||
$ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false;
|
$ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false;
|
||||||
|
|
||||||
if ($recompute = $ctime && $expiry && $expiry <= microtime(true) - $ctime / 1000 * $beta * log(random_int(1, PHP_INT_MAX) / PHP_INT_MAX)) {
|
if ($recompute = $ctime && $expiry && $expiry <= ($now = microtime(true)) - $ctime / 1000 * $beta * log(random_int(1, PHP_INT_MAX) / PHP_INT_MAX)) {
|
||||||
// force applying defaultLifetime to expiry
|
// force applying defaultLifetime to expiry
|
||||||
$item->expiresAt(null);
|
$item->expiresAt(null);
|
||||||
|
$this->logger && $this->logger->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [
|
||||||
|
'key' => $key,
|
||||||
|
'delta' => sprintf('%.1f', $expiry - $now),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user