Skip to content

Commit

Permalink
bug #35803 [Cache] Fix versioned namespace atomic clears (trvrnrth)
Browse files Browse the repository at this point in the history
This PR was merged into the 4.4 branch.

Discussion
----------

[Cache] Fix versioned namespace atomic clears

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| License       | MIT

When using namespace versioning to achieve atomic cache clears, only delete cache keys matching the old/current version.

This resolves tag inconsistency issues whereby the process running the clear would delete keys set against the new version by more recently spawned concurrent processes. Most seriously this could result in newly set data keys remaining, but with empty associated tag sets meaning the invalidation via tags was no longer possible.

Clearing specific prefixes is not supported when using versioned namespaces as it is desirable to clear all old keys as they will no longer be used and would otherwise eventually fill cache memory.

Commits
-------

971b177 Fix versioned namespace clears
  • Loading branch information
nicolas-grekas committed Feb 24, 2020
2 parents 2d53ff6 + 971b177 commit c0caef1
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/Symfony/Component/Cache/Traits/AbstractTrait.php
Expand Up @@ -111,9 +111,14 @@ public function hasItem($key)
*/
public function clear(/*string $prefix = ''*/)
{
$prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : '';
$this->deferred = [];
if ($cleared = $this->versioningIsEnabled) {
if ('' === $namespaceVersionToClear = $this->namespaceVersion) {
foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) {
$namespaceVersionToClear = $v;
}
}
$namespaceToClear = $this->namespace.$namespaceVersionToClear;
$namespaceVersion = substr_replace(base64_encode(pack('V', mt_rand())), static::NS_SEPARATOR, 5);
try {
$cleared = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0);
Expand All @@ -124,10 +129,13 @@ public function clear(/*string $prefix = ''*/)
$this->namespaceVersion = $namespaceVersion;
$this->ids = [];
}
} else {
$prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : '';
$namespaceToClear = $this->namespace.$prefix;
}

try {
return $this->doClear($this->namespace.$prefix) || $cleared;
return $this->doClear($namespaceToClear) || $cleared;
} catch (\Exception $e) {
CacheItem::log($this->logger, 'Failed to clear the cache: '.$e->getMessage(), ['exception' => $e]);

Expand Down

0 comments on commit c0caef1

Please sign in to comment.