bug #31479 [Cache] fix saving unrelated keys in recursive callback calls (nicolas-grekas)
This PR was merged into the 4.2 branch.
Discussion
----------
[Cache] fix saving unrelated keys in recursive callback calls
| Q | A
| ------------- | ---
| Branch? | 4.2
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #31399
| License | MIT
| Doc PR | -
Commits
-------
4443c2018c
[Cache] fix saving unrelated keys in recursive callback calls
This commit is contained in:
commit
1ecc6a6c03
@ -59,6 +59,26 @@ abstract class AdapterTestCase extends CachePoolTest
|
||||
$this->assertFalse($isHit);
|
||||
}
|
||||
|
||||
public function testRecursiveGet()
|
||||
{
|
||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
||||
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
|
||||
}
|
||||
|
||||
$cache = $this->createCachePool(0, __FUNCTION__);
|
||||
|
||||
$v = $cache->get('k1', function () use (&$counter, $cache) {
|
||||
$v = $cache->get('k2', function () use (&$counter) { return ++$counter; });
|
||||
$v = $cache->get('k2', function () use (&$counter) { return ++$counter; });
|
||||
|
||||
return $v;
|
||||
});
|
||||
|
||||
$this->assertSame(1, $counter);
|
||||
$this->assertSame(1, $v);
|
||||
$this->assertSame(1, $cache->get('k2', function () { return 2; }));
|
||||
}
|
||||
|
||||
public function testGetMetadata()
|
||||
{
|
||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
||||
|
@ -23,6 +23,7 @@ class PhpArrayAdapterTest extends AdapterTestCase
|
||||
{
|
||||
protected $skippedTests = [
|
||||
'testGet' => 'PhpArrayAdapter is read-only.',
|
||||
'testRecursiveGet' => 'PhpArrayAdapter is read-only.',
|
||||
'testBasicUsage' => 'PhpArrayAdapter is read-only.',
|
||||
'testBasicUsageWithLongKey' => 'PhpArrayAdapter is read-only.',
|
||||
'testClear' => 'PhpArrayAdapter is read-only.',
|
||||
|
@ -31,6 +31,7 @@ trait ContractsTrait
|
||||
}
|
||||
|
||||
private $callbackWrapper = [LockRegistry::class, 'compute'];
|
||||
private $computing = [];
|
||||
|
||||
/**
|
||||
* Wraps the callback passed to ->get() in a callable.
|
||||
@ -68,26 +69,27 @@ trait ContractsTrait
|
||||
CacheItem::class
|
||||
);
|
||||
|
||||
return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata) {
|
||||
return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata, $key) {
|
||||
// don't wrap nor save recursive calls
|
||||
if (null === $callbackWrapper = $this->callbackWrapper) {
|
||||
if (isset($this->computing[$key])) {
|
||||
$value = $callback($item, $save);
|
||||
$save = false;
|
||||
|
||||
return $value;
|
||||
}
|
||||
$this->callbackWrapper = null;
|
||||
|
||||
$this->computing[$key] = $key;
|
||||
$startTime = microtime(true);
|
||||
|
||||
try {
|
||||
$value = $callbackWrapper($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) {
|
||||
$value = ($this->callbackWrapper)($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) {
|
||||
$setMetadata($item, $startTime, $metadata);
|
||||
});
|
||||
$setMetadata($item, $startTime, $metadata);
|
||||
|
||||
return $value;
|
||||
} finally {
|
||||
$this->callbackWrapper = $callbackWrapper;
|
||||
unset($this->computing[$key]);
|
||||
}
|
||||
}, $beta, $metadata);
|
||||
}
|
||||
|
Reference in New Issue
Block a user