From 356821e2a4548898f30bb8a86d494080aec3dca1 Mon Sep 17 00:00:00 2001 From: Romain Canon Date: Wed, 18 Sep 2024 08:41:28 +0200 Subject: [PATCH] misc: use `xxh128` hash for cache keys --- src/Cache/KeySanitizerCache.php | 47 +++++++++++-------- .../Cache/CacheClassDefinitionRepository.php | 4 +- .../CacheFunctionDefinitionRepository.php | 4 +- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/Cache/KeySanitizerCache.php b/src/Cache/KeySanitizerCache.php index 0d3785c6..0f78ca25 100644 --- a/src/Cache/KeySanitizerCache.php +++ b/src/Cache/KeySanitizerCache.php @@ -4,12 +4,12 @@ namespace CuyZ\Valinor\Cache; -use Closure; use CuyZ\Valinor\Utility\Package; use Psr\SimpleCache\CacheInterface; use Traversable; use function hash; +use function strstr; /** * @internal @@ -21,21 +21,28 @@ final class KeySanitizerCache implements WarmupCache { private static string $version; - /** @var Closure(string): string */ - private Closure $sanitize; - public function __construct( /** @var CacheInterface */ private CacheInterface $delegate - ) { - // Two things: - // 1. We append the current version of the package to the cache key in - // order to avoid collisions between entries from different versions - // of the library. - // 2. The key is hashed so that it does not contain illegal characters. - // @see https://www.php-fig.org/psr/psr-16/#12-definitions - // @infection-ignore-all - $this->sanitize = static fn (string $key) => $key . hash('sha1', self::$version ??= PHP_VERSION . '/' . Package::version()); + ) {} + + /** + * Two things: + * 1. We append the current version of the package to the cache key in order + * to avoid collisions between entries from different versions of the + * library. + * 2. The key is hashed so that it does not contain illegal characters. + * @see https://www.php-fig.org/psr/psr-16/#12-definitions + * + * @infection-ignore-all + */ + private function sanitize(string $key): string + { + self::$version ??= PHP_VERSION . '/' . Package::version(); + + $firstPart = strstr($key, "\0", before_needle: true); + + return $firstPart . hash('xxh128', $key . self::$version); } public function warmup(): void @@ -47,17 +54,17 @@ public function warmup(): void public function get($key, $default = null): mixed { - return $this->delegate->get(($this->sanitize)($key), $default); + return $this->delegate->get($this->sanitize($key), $default); } public function set($key, $value, $ttl = null): bool { - return $this->delegate->set(($this->sanitize)($key), $value, $ttl); + return $this->delegate->set($this->sanitize($key), $value, $ttl); } public function delete($key): bool { - return $this->delegate->delete(($this->sanitize)($key)); + return $this->delegate->delete($this->sanitize($key)); } public function clear(): bool @@ -67,7 +74,7 @@ public function clear(): bool public function has($key): bool { - return $this->delegate->has(($this->sanitize)($key)); + return $this->delegate->has($this->sanitize($key)); } /** @@ -76,7 +83,7 @@ public function has($key): bool public function getMultiple($keys, $default = null): Traversable { foreach ($keys as $key) { - yield $key => $this->delegate->get(($this->sanitize)($key), $default); + yield $key => $this->delegate->get($this->sanitize($key), $default); } } @@ -85,7 +92,7 @@ public function setMultiple($values, $ttl = null): bool $versionedValues = []; foreach ($values as $key => $value) { - $versionedValues[($this->sanitize)($key)] = $value; + $versionedValues[$this->sanitize($key)] = $value; } return $this->delegate->setMultiple($versionedValues, $ttl); @@ -96,7 +103,7 @@ public function deleteMultiple($keys): bool $transformedKeys = []; foreach ($keys as $key) { - $transformedKeys[] = ($this->sanitize)($key); + $transformedKeys[] = $this->sanitize($key); } return $this->delegate->deleteMultiple($transformedKeys); diff --git a/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php b/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php index c0992bad..89a720e4 100644 --- a/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php +++ b/src/Definition/Repository/Cache/CacheClassDefinitionRepository.php @@ -9,8 +9,6 @@ use CuyZ\Valinor\Type\ObjectType; use Psr\SimpleCache\CacheInterface; -use function hash; - /** @internal */ final class CacheClassDefinitionRepository implements ClassDefinitionRepository { @@ -23,7 +21,7 @@ public function __construct( public function for(ObjectType $type): ClassDefinition { // @infection-ignore-all - $key = 'class-definition' . hash('sha1', $type->toString()); + $key = "class-definition-\0" . $type->toString(); $entry = $this->cache->get($key); diff --git a/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php b/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php index b56b729b..265b8189 100644 --- a/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php +++ b/src/Definition/Repository/Cache/CacheFunctionDefinitionRepository.php @@ -9,8 +9,6 @@ use CuyZ\Valinor\Utility\Reflection\Reflection; use Psr\SimpleCache\CacheInterface; -use function hash; - /** @internal */ final class CacheFunctionDefinitionRepository implements FunctionDefinitionRepository { @@ -25,7 +23,7 @@ public function for(callable $function): FunctionDefinition $reflection = Reflection::function($function); // @infection-ignore-all - $key = 'function-definition-' . hash('sha1', $reflection->getFileName() . $reflection->getStartLine() . $reflection->getEndLine()); + $key = "function-definition-\0" . $reflection->getFileName() . ':' . $reflection->getStartLine() . '-' . $reflection->getEndLine(); $entry = $this->cache->get($key);