Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

!!! FEATURE: Introduce flushByTags to taggable cache backends #2718

Merged
merged 5 commits into from
Mar 18, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Neos.Cache/Classes/Backend/ApcuBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,20 @@ public function flushByTag(string $tag): int
return count($identifiers);
}

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @api
*/
public function flushByTags(array $tags): int
{
$flushed = 0;
foreach ($tags as $tag) {
$flushed += $this->flushByTag($tag);
}
return $flushed;
}

/**
* Associates the identifier with the given tags
*
Expand Down
14 changes: 14 additions & 0 deletions Neos.Cache/Classes/Backend/FileBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,20 @@ public function flushByTag(string $tag): int
return count($identifiers);
}

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @api
*/
public function flushByTags(array $tags): int
{
$flushed = 0;
foreach ($tags as $tag) {
$flushed += $this->flushByTag($tag);
}
return $flushed;
}

/**
* Checks if the given cache entry files are still valid or if their
* lifetime has exceeded.
Expand Down
14 changes: 14 additions & 0 deletions Neos.Cache/Classes/Backend/MemcachedBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,20 @@ public function flushByTag(string $tag): int
return count($identifiers);
}

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @api
*/
public function flushByTags(array $tags): int
{
$flushed = 0;
foreach ($tags as $tag) {
$flushed += $this->flushByTag($tag);
}
return $flushed;
}

/**
* Associates the identifier with the given tags
*
Expand Down
12 changes: 12 additions & 0 deletions Neos.Cache/Classes/Backend/NullBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ public function flushByTag(string $tag): int
return 0;
}

/**
* Does nothing
*
* @param array<string> $tags ignored
* @return integer
* @api
*/
public function flushByTags(array $tags): int
{
return 0;
}

/**
* Does nothing
*
Expand Down
15 changes: 15 additions & 0 deletions Neos.Cache/Classes/Backend/PdoBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,21 @@ public function flushByTag(string $tag): int
return $flushed;
}

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @throws Exception
* @api
*/
public function flushByTags(array $tags): int
{
$flushed = 0;
foreach ($tags as $tag) {
$flushed += $this->flushByTag($tag);
}
return $flushed;
}

/**
* Finds and returns all cache entry identifiers which are tagged by the
* specified tag.
Expand Down
14 changes: 14 additions & 0 deletions Neos.Cache/Classes/Backend/RedisBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,20 @@ public function flushByTag(string $tag): int
return $this->redis->eval($script, [$this->getPrefixedIdentifier('tag:' . $tag), $this->getPrefixedIdentifier('entries'), $this->getPrefixedIdentifier('')], 2);
}

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @api
*/
public function flushByTags(array $tags): int
{
$flushed = 0;
foreach ($tags as $tag) {
$flushed += $this->flushByTag($tag);
}
return $flushed;
}

/**
* Finds and returns all cache entry identifiers which are tagged by the
* specified tag.
Expand Down
9 changes: 9 additions & 0 deletions Neos.Cache/Classes/Backend/TaggableBackendInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ interface TaggableBackendInterface extends BackendInterface
*/
public function flushByTag(string $tag): int;

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @param array<string> $tags The tags the entries must have
* @return integer The number of entries which have been affected by this flush or NULL if the number is unknown
* @api
*/
public function flushByTags(array $tags): int;

/**
* Finds and returns all cache entry identifiers which are tagged by the
* specified tag.
Expand Down
15 changes: 15 additions & 0 deletions Neos.Cache/Classes/Backend/TaggableMultiBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@ public function flushByTag(string $tag): int
return $count;
}

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @throws \Throwable
* @api
*/
public function flushByTags(array $tags): int
{
$flushed = 0;
foreach ($tags as $tag) {
$flushed += $this->flushByTag($tag);
}
return $flushed;
}

/**
* @param string $tag
* @return string[]
Expand Down
14 changes: 14 additions & 0 deletions Neos.Cache/Classes/Backend/TransientMemoryBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,20 @@ public function flushByTag(string $tag): int
return count($identifiers);
}

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @api
*/
public function flushByTags(array $tags): int
{
$flushed = 0;
foreach ($tags as $tag) {
$flushed += $this->flushByTag($tag);
}
return $flushed;
}

/**
* Does nothing
*
Expand Down
21 changes: 21 additions & 0 deletions Neos.Cache/Classes/Frontend/AbstractFrontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,27 @@ public function flushByTag(string $tag): int
return 0;
}

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @param array<string> $tags The tags the entries must have
* @return integer The number of entries which have been affected by this flush
* @throws \InvalidArgumentException
* @api
*/
public function flushByTags(array $tags): int
{
foreach ($tags as $tag) {
if (!$this->isValidTag($tag)) {
throw new \InvalidArgumentException('"' . $tag . '" is not a valid tag for a cache entry.', 1646209443);
}
}
if ($this->backend instanceof TaggableBackendInterface) {
return $this->backend->flushByTags($tags);
}
return 0;
}

/**
* Does garbage collection
*
Expand Down
9 changes: 9 additions & 0 deletions Neos.Cache/Classes/Frontend/FrontendInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ public function flush();
*/
public function flushByTag(string $tag): int;

/**
* Removes all cache entries of this cache which are tagged by any of the specified tags.
*
* @param array<string> $tags The tags the entries must have
* @return integer The number of entries which have been affected by this flush or NULL if the number is unknown
* @api
*/
public function flushByTags(array $tags): int;

/**
* Does garbage collection
*
Expand Down
43 changes: 43 additions & 0 deletions Neos.Cache/Tests/Functional/Backend/RedisBackendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,31 @@ public function flushByTagFlushesEntryByTag()
self::assertCount(10, $this->backend->findIdentifiersByTag('tag2'));
}

/**
* @test
*/
public function flushByTagsFlushesEntryByTags()
{
for ($i = 0; $i < 10; $i++) {
$this->backend->set('entry_' . $i, 'foo', ['tag1', 'tag2']);
}
for ($i = 10; $i < 20; $i++) {
$this->backend->set('entry_' . $i, 'foo', ['tag2']);
}
for ($i = 20; $i < 30; $i++) {
$this->backend->set('entry_' . $i, 'foo', ['tag3']);
}
self::assertCount(10, $this->backend->findIdentifiersByTag('tag1'));
self::assertCount(20, $this->backend->findIdentifiersByTag('tag2'));
self::assertCount(10, $this->backend->findIdentifiersByTag('tag3'));

$count = $this->backend->flushByTags(['tag1', 'tag3']);
self::assertEquals(20, $count, 'flushByTag returns amount of flushed entries');
self::assertCount(0, $this->backend->findIdentifiersByTag('tag1'));
self::assertCount(10, $this->backend->findIdentifiersByTag('tag2'));
self::assertCount(0, $this->backend->findIdentifiersByTag('tag3'));
}

/**
* @test
*/
Expand All @@ -196,6 +221,24 @@ public function flushByTagRemovesEntries()
self::assertEquals([], $entryIdentifiers);
}

/**
* @test
*/
public function flushByTagsRemovesEntries()
{
$this->backend->set('some_entry', 'foo', ['tag1', 'tag2']);
$this->backend->set('some_other_entry', 'bar', ['tag3']);

$this->backend->flushByTags(['tag1', 'tag3']);

$entryIdentifiers = [];
foreach ($this->backend as $entryIdentifier => $entryValue) {
$entryIdentifiers[] = $entryIdentifier;
}

self::assertEquals([], $entryIdentifiers);
}

/**
* @test
*/
Expand Down
1 change: 1 addition & 0 deletions Neos.Cache/Tests/Unit/Backend/AbstractBackendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public function has(string $entryIdentifier): bool {}
public function remove(string $entryIdentifier): bool {}
public function flush(): void {}
public function flushByTag(string $tag): int {}
public function flushByTags(array $tags): int {}
public function findIdentifiersByTag(string $tag): array {}
public function collectGarbage(): void {}
public function setSomeOption($value) {
Expand Down
19 changes: 19 additions & 0 deletions Neos.Cache/Tests/Unit/Backend/ApcuBackendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,25 @@ public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
self::assertTrue($backend->has('BackendAPCUTest3'), 'BackendAPCUTest3');
}

/**
* @test
*/
public function flushByTagsRemovesCacheEntriesWithSpecifiedTags()
{
$backend = $this->setUpBackend();

$data = 'some data' . microtime();
$backend->set('BackendAPCUTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
$backend->set('BackendAPCUTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
$backend->set('BackendAPCUTest3', $data, ['UnitTestTag%test']);

$backend->flushByTags(['UnitTestTag%boring', 'UnitTestTag%special']);

self::assertFalse($backend->has('BackendAPCUTest1'), 'BackendAPCUTest1');
self::assertFalse($backend->has('BackendAPCUTest2'), 'BackendAPCUTest2');
self::assertTrue($backend->has('BackendAPCUTest3'), 'BackendAPCUTest3');
}

/**
* @test
*/
Expand Down
13 changes: 13 additions & 0 deletions Neos.Cache/Tests/Unit/Backend/FileBackendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,19 @@ public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
$backend->flushByTag('UnitTestTag%special');
}

/**
* @test
*/
public function flushByTagsRemovesCacheEntriesWithSpecifiedTags()
{
$backend = $this->prepareDefaultBackend(['findIdentifiersByTag', 'remove']);

$backend->expects(self::once())->method('findIdentifiersByTag')->with('UnitTestTag%special')->will(self::returnValue(['foo', 'bar', 'baz']));
$backend->expects(self::atLeast(3))->method('remove')->withConsecutive(['foo'], ['bar'], ['baz']);

$backend->flushByTags(['UnitTestTag%special']);
}

/**
* @test
*/
Expand Down
19 changes: 19 additions & 0 deletions Neos.Cache/Tests/Unit/Backend/PdoBackendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,25 @@ public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
self::assertTrue($backend->has('PdoBackendTest3'), 'PdoBackendTest3');
}

/**
* @test
*/
public function flushByTagsRemovesCacheEntriesWithSpecifiedTags()
{
$backend = $this->setUpBackend();

$data = 'some data' . microtime();
$backend->set('PdoBackendTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
$backend->set('PdoBackendTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
$backend->set('PdoBackendTest3', $data, ['UnitTestTag%test']);

$backend->flushByTags(['UnitTestTag%boring', 'UnitTestTag%special']);

self::assertFalse($backend->has('PdoBackendTest1'), 'PdoBackendTest1');
self::assertFalse($backend->has('PdoBackendTest2'), 'PdoBackendTest2');
self::assertTrue($backend->has('PdoBackendTest3'), 'PdoBackendTest3');
}

/**
* @test
*/
Expand Down
Loading