diff --git a/src/Spiritix/LadaCache/Cache.php b/src/Spiritix/LadaCache/Cache.php index aac49f0..8afed52 100644 --- a/src/Spiritix/LadaCache/Cache.php +++ b/src/Spiritix/LadaCache/Cache.php @@ -91,6 +91,23 @@ public function set($key, array $tags, $data) } } + /** + * Store given key in tags. + * + * Ensure key exists in the given tags. + * Redis sets are unique, so the same value will not be added twice. + * + * @param string $key + * @param array $tags + */ + public function setCacheTagsForKey($key, array $tags) + { + $key = $this->redis->prefix($key); + foreach ($tags as $tag) { + $this->redis->sadd($this->redis->prefix($tag), $key); + } + } + /** * Returns value of a cached key. * diff --git a/src/Spiritix/LadaCache/QueryHandler.php b/src/Spiritix/LadaCache/QueryHandler.php index f6a5ee8..8908d26 100644 --- a/src/Spiritix/LadaCache/QueryHandler.php +++ b/src/Spiritix/LadaCache/QueryHandler.php @@ -154,10 +154,13 @@ public function cacheQuery($queryClosure) $action = ($result === null) ? 'Miss' : 'Hit'; - // If not, execute the query closure and cache the result if ($result === null) { + // Cache miss, execute the query closure and cache the result $result = $queryClosure(); $this->cache->set($key, $tags, $result); + } else { + // Cache hit, validate cache tags on key + $this->cache->setCacheTagsForKey($key, $tags); } $this->destructCollector($reflector, $tags, $key, $action); diff --git a/tests/InvalidatorTest.php b/tests/InvalidatorTest.php index b765fdf..b1ad728 100644 --- a/tests/InvalidatorTest.php +++ b/tests/InvalidatorTest.php @@ -91,4 +91,24 @@ public function testCacheStateWhenInvalideIsCalledInDistributedSystem(): void $this->assertTrue($this->cache->has('key3')); $this->assertTrue($this->cache->has('tag2')); } + + public function testCacheHitsValidateKeyInTags(): void + { + $this->cache->set('key1', ['tag2'], 'data'); // <-- Bug, simulate 'tag1' missing from key1 + $this->cache->set('key2', ['tag1', 'tag2'], 'data'); + + // Simulate cache hit on Key1 + // Start -------------------------------------------------------------------------------- + $data = $this->cache->get('key1'); + $this->assertSame('data', $data); + $this->cache->setCacheTagsForKey('key1', ['tag1', 'tag2']); // <-- Validate tags for key + // End ---------------------------------------------------------------------------------- + + // Invalidate cache. + $this->invalidator->invalidate(['tag1']); + + // Check cache is invalidated: + $this->assertFalse($this->cache->has('key1')); + $this->assertFalse($this->cache->has('key2')); + } }