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);
|
$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()
|
public function testGetMetadata()
|
||||||
{
|
{
|
||||||
if (isset($this->skippedTests[__FUNCTION__])) {
|
if (isset($this->skippedTests[__FUNCTION__])) {
|
||||||
|
@ -23,6 +23,7 @@ class PhpArrayAdapterTest extends AdapterTestCase
|
|||||||
{
|
{
|
||||||
protected $skippedTests = [
|
protected $skippedTests = [
|
||||||
'testGet' => 'PhpArrayAdapter is read-only.',
|
'testGet' => 'PhpArrayAdapter is read-only.',
|
||||||
|
'testRecursiveGet' => 'PhpArrayAdapter is read-only.',
|
||||||
'testBasicUsage' => 'PhpArrayAdapter is read-only.',
|
'testBasicUsage' => 'PhpArrayAdapter is read-only.',
|
||||||
'testBasicUsageWithLongKey' => 'PhpArrayAdapter is read-only.',
|
'testBasicUsageWithLongKey' => 'PhpArrayAdapter is read-only.',
|
||||||
'testClear' => 'PhpArrayAdapter is read-only.',
|
'testClear' => 'PhpArrayAdapter is read-only.',
|
||||||
|
@ -31,6 +31,7 @@ trait ContractsTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
private $callbackWrapper = [LockRegistry::class, 'compute'];
|
private $callbackWrapper = [LockRegistry::class, 'compute'];
|
||||||
|
private $computing = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps the callback passed to ->get() in a callable.
|
* Wraps the callback passed to ->get() in a callable.
|
||||||
@ -68,26 +69,27 @@ trait ContractsTrait
|
|||||||
CacheItem::class
|
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
|
// don't wrap nor save recursive calls
|
||||||
if (null === $callbackWrapper = $this->callbackWrapper) {
|
if (isset($this->computing[$key])) {
|
||||||
$value = $callback($item, $save);
|
$value = $callback($item, $save);
|
||||||
$save = false;
|
$save = false;
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
$this->callbackWrapper = null;
|
|
||||||
|
$this->computing[$key] = $key;
|
||||||
$startTime = microtime(true);
|
$startTime = microtime(true);
|
||||||
|
|
||||||
try {
|
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);
|
||||||
});
|
});
|
||||||
$setMetadata($item, $startTime, $metadata);
|
$setMetadata($item, $startTime, $metadata);
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
} finally {
|
} finally {
|
||||||
$this->callbackWrapper = $callbackWrapper;
|
unset($this->computing[$key]);
|
||||||
}
|
}
|
||||||
}, $beta, $metadata);
|
}, $beta, $metadata);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user