Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 854459b

Browse filesBrowse files
[Cache] Add nonce based cache invalidation to ApcuAdapter
1 parent b85ab60 commit 854459b
Copy full SHA for 854459b

File tree

4 files changed

+59
-4
lines changed
Filter options

4 files changed

+59
-4
lines changed

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,7 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild
10371037

10381038
private function registerCacheConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
10391039
{
1040+
$container->setParameter('kernel.cache_nonce', substr(base64_encode(md5(uniqid(mt_rand(), true), true)), 0, 4));
10401041
$container->getDefinition('cache.adapter.filesystem')->replaceArgument(2, $config['directory']);
10411042

10421043
foreach (array('doctrine', 'psr6', 'redis') as $name) {

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<tag name="monolog.logger" channel="cache" />
2828
<argument /> <!-- namespace -->
2929
<argument /> <!-- default lifetime -->
30+
<argument>%kernel.cache_nonce%</argument>
3031
<call method="setLogger">
3132
<argument type="service" id="logger" on-invalid="ignore" />
3233
</call>

‎src/Symfony/Component/Cache/Adapter/ApcuAdapter.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Adapter/ApcuAdapter.php
+40-4Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
*/
1919
class ApcuAdapter extends AbstractAdapter
2020
{
21-
public function __construct($namespace = '', $defaultLifetime = 0)
21+
private $nonce;
22+
private $nonceLen;
23+
24+
public function __construct($namespace = '', $defaultLifetime = 0, $nonce = null)
2225
{
2326
if (!function_exists('apcu_fetch') || !ini_get('apc.enabled') || ('cli' === PHP_SAPI && !ini_get('apc.enable_cli'))) {
2427
throw new CacheException('APCu is not enabled');
@@ -27,22 +30,49 @@ public function __construct($namespace = '', $defaultLifetime = 0)
2730
ini_set('apc.use_request_time', 0);
2831
}
2932
parent::__construct($namespace, $defaultLifetime);
33+
$this->nonce = (string) $nonce;
34+
$this->nonceLen = strlen($nonce);
3035
}
3136

3237
/**
3338
* {@inheritdoc}
3439
*/
3540
protected function doFetch(array $ids)
3641
{
37-
return apcu_fetch($ids);
42+
$values = apcu_fetch($ids);
43+
44+
if ($this->nonceLen) {
45+
foreach ($values as $id => $v) {
46+
if (!is_string($v) || 0 !== strpos($v, $this->nonce)) {
47+
apcu_delete($id);
48+
unset($values[$id]);
49+
}
50+
}
51+
foreach ($values as $id => $v) {
52+
$values[$id] = unserialize(substr($v, $this->nonceLen));
53+
}
54+
}
55+
56+
return $values;
3857
}
3958

4059
/**
4160
* {@inheritdoc}
4261
*/
4362
protected function doHave($id)
4463
{
45-
return apcu_exists($id);
64+
if (!$this->nonceLen) {
65+
return apcu_exists($id);
66+
}
67+
$v = apcu_fetch($id, $found);
68+
69+
if ($found && (!is_string($v) || 0 !== strpos($v, $this->nonce))) {
70+
apcu_delete($id);
71+
$found = false;
72+
}
73+
74+
return $found;
75+
4676
}
4777

4878
/**
@@ -73,12 +103,18 @@ protected function doDelete(array $ids)
73103
protected function doSave(array $values, $lifetime)
74104
{
75105
try {
106+
if ($this->nonceLen) {
107+
foreach ($values as $id => $v) {
108+
$values[$id] = $this->nonce.serialize($v);
109+
}
110+
}
111+
76112
return array_keys(apcu_store($values, null, $lifetime));
77113
} catch (\Error $e) {
78114
} catch (\Exception $e) {
79115
}
80116

81-
if (1 === count($values)) {
117+
if (!$this->nonceLen && 1 === count($values)) {
82118
// Workaround https://github.com/krakjoe/apcu/issues/170
83119
apcu_delete(key($values));
84120
}

‎src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php
+17Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,21 @@ public function testUnserializable()
4343
$item = $pool->getItem('foo');
4444
$this->assertFalse($item->isHit());
4545
}
46+
47+
public function testNonce()
48+
{
49+
$namespace = str_replace('\\', '.', __CLASS__);
50+
$pool1 = new ApcuAdapter($namespace, 0, 'p1');
51+
$pool2 = new ApcuAdapter($namespace, 0, 'p2');
52+
53+
$item = $pool1->getItem('foo');
54+
$this->assertFalse($item->isHit());
55+
$this->assertTrue($pool1->save($item->set('bar')));
56+
$item = $pool1->getItem('foo');
57+
$this->assertTrue($item->isHit());
58+
$this->assertSame('bar', $item->get());
59+
$item = $pool2->getItem('foo');
60+
$this->assertFalse($item->isHit());
61+
$this->assertNull($item->get());
62+
}
4663
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.