Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/8.1' into 8.2
Browse files Browse the repository at this point in the history
  • Loading branch information
mhsdesign committed Feb 23, 2023
2 parents b33551e + e27d245 commit 3a881e1
Show file tree
Hide file tree
Showing 20 changed files with 623 additions and 55 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/add-pr-labels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Add Labels to Pull Request

on:
pull_request:
types: [opened, reopened, synchronize, edited]

jobs:
add-labels:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Maybe remove base branch label
if: github.event.action == 'edited' && github.event.changes.base.ref.from != ''
uses: actions-ecosystem/action-remove-labels@v1
with:
labels: ${{ github.event.changes.base.ref.from }}
- name: Add feature label
if: startsWith(github.event.pull_request.title, 'FEATURE:')
uses: actions-ecosystem/action-add-labels@v1
with:
labels: 'Feature'
- name: Add bugfix label
if: startsWith(github.event.pull_request.title, 'BUGFIX:')
uses: actions-ecosystem/action-add-labels@v1
with:
labels: 'Bug'
- name: Add task label
if: startsWith(github.event.pull_request.title, 'TASK:')
uses: actions-ecosystem/action-add-labels@v1
with:
labels: 'Task'
- name: Add target branch label
uses: actions-ecosystem/action-add-labels@v1
with:
labels: ${{ github.base_ref }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8 changes: 6 additions & 2 deletions Neos.Cache/Classes/Backend/ApcuBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class ApcuBackend extends IndependentAbstractBackend implements TaggableBackendI
protected $identifierPrefix;

/**
* @var \APCUIterator
* @var \APCUIterator|null
*/
protected $cacheEntriesIterator;

Expand Down Expand Up @@ -111,7 +111,7 @@ public function getPrefixedIdentifier(string $entryIdentifier): string
* @param string $entryIdentifier An identifier for this specific cache entry
* @param string $data The data to be stored
* @param array $tags Tags to associate with this cache entry
* @param integer $lifetime Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited lifetime.
* @param int|null $lifetime Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited lifetime.
* @return void
* @throws Exception if no cache frontend has been set.
* @throws \InvalidArgumentException if the identifier is not valid
Expand All @@ -133,6 +133,8 @@ public function set(string $entryIdentifier, string $data, array $tags = [], int
} else {
throw new Exception('Could not set value.', 1232986877);
}

$this->cacheEntriesIterator = null;
}

/**
Expand Down Expand Up @@ -175,6 +177,7 @@ public function has(string $entryIdentifier): bool
public function remove(string $entryIdentifier): bool
{
$this->removeIdentifierFromAllTags($entryIdentifier);
$this->cacheEntriesIterator = null;
return apcu_delete($this->getPrefixedIdentifier($entryIdentifier));
}

Expand Down Expand Up @@ -238,6 +241,7 @@ public function flushByTag(string $tag): int
foreach ($identifiers as $identifier) {
$this->remove($identifier);
}
$this->cacheEntriesIterator = null;
return count($identifiers);
}

Expand Down
21 changes: 13 additions & 8 deletions Neos.Cache/Classes/Backend/PdoBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ class PdoBackend extends IndependentAbstractBackend implements TaggableBackendIn
protected $batchSize = 999;

/**
* @var \ArrayIterator
* @var \ArrayIterator|null
*/
protected $cacheEntriesIterator = null;
protected $cacheEntriesIterator;

/**
* Sets the DSN to use
Expand Down Expand Up @@ -158,7 +158,7 @@ protected function setBatchSize(int $batchSize): void
* @param string $entryIdentifier An identifier for this specific cache entry
* @param string $data The data to be stored
* @param array $tags Tags to associate with this cache entry
* @param integer $lifetime Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited lifetime.
* @param int|null $lifetime Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited lifetime.
* @return void
* @throws Exception if no cache frontend has been set.
* @throws \InvalidArgumentException if the identifier is not valid
Expand Down Expand Up @@ -200,6 +200,7 @@ public function set(string $entryIdentifier, string $data, array $tags = [], int
}

$this->databaseHandle->commit();
$this->cacheEntriesIterator = null;
} catch (\Exception $exception) {
$this->databaseHandle->rollBack();

Expand Down Expand Up @@ -254,7 +255,7 @@ public function has(string $entryIdentifier): bool
*
* @param string $entryIdentifier Specifies the cache entry to remove
* @return boolean true if (at least) one entry could be removed or false if no entry was found
* @throws Exception
* @throws \Exception
* @api
*/
public function remove(string $entryIdentifier): bool
Expand All @@ -265,6 +266,7 @@ public function remove(string $entryIdentifier): bool
try {
$rowsWereDeleted = $this->removeWithoutTransaction($entryIdentifier);
$this->databaseHandle->commit();
$this->cacheEntriesIterator = null;

return $rowsWereDeleted;
} catch (\Exception $exception) {
Expand Down Expand Up @@ -300,7 +302,7 @@ private function removeWithoutTransaction(string $entryIdentifier)
* Removes all cache entries of this cache.
*
* @return void
* @throws Exception
* @throws \Exception
* @api
*/
public function flush(): void
Expand All @@ -321,6 +323,7 @@ public function flush(): void
$statementHandle->execute([$this->context(), $this->cacheIdentifier]);

$this->databaseHandle->commit();
$this->cacheEntriesIterator = null;
} catch (\Exception $exception) {
$this->databaseHandle->rollBack();

Expand All @@ -333,7 +336,7 @@ public function flush(): void
*
* @param string $tag The tag the entries must have
* @return integer
* @throws Exception
* @throws \Exception
* @api
*/
public function flushByTag(string $tag): int
Expand All @@ -351,13 +354,14 @@ public function flushByTag(string $tag): int
$statementHandle->execute([$this->context(), $this->cacheIdentifier, $tag]);

$this->databaseHandle->commit();
$this->cacheEntriesIterator = null;

return $flushed;
} catch (\Exception $exception) {
$this->databaseHandle->rollBack();

throw $exception;
}

return $flushed;
}

/**
Expand Down Expand Up @@ -461,6 +465,7 @@ public function collectGarbage(): void

throw $exception;
}
$this->cacheEntriesIterator = null;
}

/**
Expand Down
18 changes: 13 additions & 5 deletions Neos.Cache/Classes/Backend/SimpleFileBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class SimpleFileBackend extends IndependentAbstractBackend implements PhpCapable
protected $useIgBinary = false;

/**
* @var \DirectoryIterator
* @var \DirectoryIterator|null
*/
protected $cacheFilesIterator;

Expand All @@ -99,7 +99,7 @@ public function __construct(EnvironmentConfiguration $environmentConfiguration,
* Sets a reference to the cache frontend which uses this backend and
* initializes the default cache directory.
*
* @param \Neos\Cache\Frontend\FrontendInterface $cache The cache frontend
* @param FrontendInterface $cache The cache frontend
* @return void
* @throws Exception
*/
Expand Down Expand Up @@ -139,7 +139,7 @@ public function getCacheDirectory(): string
* @param string $entryIdentifier An identifier for this specific cache entry
* @param string $data The data to be stored
* @param array $tags Ignored in this type of cache backend
* @param integer $lifetime Ignored in this type of cache backend
* @param int|null $lifetime Ignored in this type of cache backend
* @return void
* @throws Exception if the directory does not exist or is not writable or exceeds the maximum allowed path length, or if no cache frontend has been set.
* @throws \InvalidArgumentException
Expand All @@ -161,6 +161,7 @@ public function set(string $entryIdentifier, string $data, array $tags = [], int
if ($this->cacheEntryFileExtension === '.php') {
OpcodeCacheHelper::clearAllActive($cacheEntryPathAndFilename);
}
$this->cacheFilesIterator = null;
return;
}

Expand Down Expand Up @@ -259,7 +260,8 @@ public function remove(string $entryIdentifier): bool

if ($result === true) {
clearstatcache(true, $cacheEntryPathAndFilename);
return $result;
$this->cacheFilesIterator = null;
return true;
}
} catch (\Exception $e) {
}
Expand All @@ -279,6 +281,7 @@ public function remove(string $entryIdentifier): bool
public function flush(): void
{
Files::emptyDirectoryRecursively($this->cacheDirectory);
$this->cacheFilesIterator = null;
}

/**
Expand Down Expand Up @@ -544,11 +547,16 @@ protected function writeCacheFile(string $cacheEntryPathAndFilename, string $dat
for ($i = 0; $i < 3; $i++) {
$result = false;
try {
$file = fopen($cacheEntryPathAndFilename, 'wb');
// It's important that we use the 'c' flag below, as `fopen` will otherwise truncate the file
// if it already exists. If we used 'w' and then didn't get the lock, the file would end up empty.
// https://www.php.net/manual/en/function.fopen.php#refsect1-function.fopen-parameters
$file = fopen($cacheEntryPathAndFilename, 'cb');
if ($file === false) {
continue;
}
if (flock($file, LOCK_EX) !== false) {
// We need to truncate the file in case it was already present
ftruncate($file, 0);
$result = !(fwrite($file, $data) === false);
flock($file, LOCK_UN);
}
Expand Down
123 changes: 123 additions & 0 deletions Neos.Cache/Tests/Unit/Backend/ApcuBackendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,128 @@ public function backendAllowsForIteratingOverEntries()
self::assertEquals(100, $i);
}

/**
* @test
*/
public function iterationOverEmptyCacheYieldsNoData()
{
$backend = $this->setUpBackend();
$cache = new VariableFrontend('UnitTestCache', $backend);
$data = \iterator_to_array(
$cache->getIterator()
);
self::assertEmpty($data);
}

/**
* @test
*/
public function iterationOverNotEmptyCacheYieldsData()
{
$backend = $this->setUpBackend();
$cache = new VariableFrontend('UnitTestCache', $backend);

$cache->set('first', 'firstData');
$cache->set('second', 'secondData');

$data = \iterator_to_array(
$cache->getIterator()
);
self::assertEquals(
['first' => 'firstData', 'second' => 'secondData'],
$data
);
}

/**
* @test
*/
public function iterationResetsWhenDataIsSet()
{
$backend = $this->setUpBackend();
$cache = new VariableFrontend('UnitTestCache', $backend);

$cache->set('first', 'firstData');
$cache->set('second', 'secondData');

\iterator_to_array(
$cache->getIterator()
);

$cache->set('third', 'thirdData');

$data = \iterator_to_array(
$cache->getIterator()
);
self::assertEquals(
['first' => 'firstData', 'second' => 'secondData', 'third' => 'thirdData'],
$data
);
}

/**
* @test
*/
public function iterationResetsWhenDataFlushed()
{
$backend = $this->setUpBackend();
$cache = new VariableFrontend('UnitTestCache', $backend);

$cache->set('first', 'firstData');
\iterator_to_array(
$cache->getIterator()
);

$backend->flush();

$data = \iterator_to_array(
$cache->getIterator()
);
self::assertEmpty($data);
}

/**
* @test
*/
public function iterationResetsWhenDataFlushedByTag()
{
$backend = $this->setUpBackend();
$cache = new VariableFrontend('UnitTestCache', $backend);

$cache->set('first', 'firstData', ['tag']);
\iterator_to_array(
$cache->getIterator()
);

$backend->flushByTag('tag');

$data = \iterator_to_array(
$cache->getIterator()
);
self::assertEmpty($data);
}

/**
* @test
*/
public function iterationResetsWhenDataGetsRemoved()
{
$backend = $this->setUpBackend();
$cache = new VariableFrontend('UnitTestCache', $backend);

$cache->set('first', 'firstData');
\iterator_to_array(
$cache->getIterator()
);

$backend->remove('first');

$data = \iterator_to_array(
$cache->getIterator()
);
self::assertEmpty($data);
}

/**
* Sets up the APCu backend used for testing
*
Expand All @@ -303,6 +425,7 @@ protected function setUpBackend()
$cache = $this->createMock(FrontendInterface::class);
$backend = new ApcuBackend($this->getEnvironmentConfiguration(), []);
$backend->setCache($cache);
$backend->flush(); // I'd rather start with a clean directory in the first place, but I can't get the "vfs" thing to work

return $backend;
}
Expand Down

0 comments on commit 3a881e1

Please sign in to comment.