Skip to content

Commit a12fb71

Browse files
[Magento Community Engineering] Community Contributions - 2.4-develop
- merged latest code from mainline branch
2 parents 6992ee0 + 55af84f commit a12fb71

File tree

19 files changed

+913
-31
lines changed

19 files changed

+913
-31
lines changed

app/code/Magento/PageCache/etc/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
<type name="Magento\Framework\App\FrontControllerInterface">
4141
<plugin name="page_cache_from_key_from_cookie" type="Magento\PageCache\Plugin\RegisterFormKeyFromCookie" />
4242
</type>
43+
<type name="Magento\Framework\App\Cache\RuntimeStaleCacheStateModifier">
44+
<arguments>
45+
<argument name="cacheTypes" xsi:type="array">
46+
<item name="full_page_cache" xsi:type="const">Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER</item>
47+
</argument>
48+
</arguments>
49+
</type>
4350
<preference for="Magento\PageCache\Model\VclGeneratorInterface" type="Magento\PageCache\Model\Varnish\VclGenerator"/>
4451
<preference for="Magento\PageCache\Model\VclTemplateLocatorInterface" type="Magento\PageCache\Model\Varnish\VclTemplateLocator"/>
4552
</config>

app/etc/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,13 @@
17771777
<argument name="locker" xsi:type="object">Magento\Framework\Lock\Backend\Database</argument>
17781778
</arguments>
17791779
</type>
1780+
<type name="Magento\Framework\Cache\CompositeStaleCacheNotifier">
1781+
<arguments>
1782+
<argument name="notifiers" xsi:type="array">
1783+
<item name="runtime_cache_modifier" xsi:type="object">Magento\Framework\App\Cache\RuntimeStaleCacheStateModifier</item>
1784+
</argument>
1785+
</arguments>
1786+
</type>
17801787
<preference for="Magento\Framework\HTTP\AsyncClientInterface" type="Magento\Framework\HTTP\AsyncClient\GuzzleAsyncClient" />
17811788
<preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillCompareInterface" type="Magento\Framework\MessageQueue\PoisonPill\PoisonPillCompare"/>
17821789
<preference for="Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface" type="Magento\Framework\MessageQueue\PoisonPill\PoisonPillPut"/>
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Framework\Lock\Backend;
9+
10+
use Magento\Framework\Lock\Backend\Cache;
11+
12+
/**
13+
* \Magento\Framework\Lock\Backend\Cache test case.
14+
*/
15+
class CacheTest extends \PHPUnit\Framework\TestCase
16+
{
17+
/**
18+
* @var Cache
19+
*/
20+
private $cacheInstance1;
21+
22+
/**
23+
* @var Cache
24+
*/
25+
private $cacheInstance2;
26+
27+
/**
28+
* @inheritDoc
29+
*/
30+
protected function setUp(): void
31+
{
32+
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
33+
34+
$frontendInterface1 = $objectManager->create(\Magento\Framework\App\Cache\Type\Config::class);
35+
$this->cacheInstance1 = new Cache($frontendInterface1);
36+
37+
$frontendInterface2 = $objectManager->create(\Magento\Framework\App\Cache\Type\Config::class);
38+
$this->cacheInstance2 = new Cache($frontendInterface2);
39+
}
40+
41+
/**
42+
* Verify lock mechanism in general.
43+
*
44+
* @return void
45+
*/
46+
public function testParallelLock(): void
47+
{
48+
$identifier1 = \uniqid('lock_name_1_', true);
49+
50+
$this->assertTrue($this->cacheInstance1->lock($identifier1, 2));
51+
52+
$this->assertFalse($this->cacheInstance1->lock($identifier1, 2));
53+
$this->assertFalse($this->cacheInstance2->lock($identifier1, 2));
54+
sleep(4);
55+
$this->assertFalse($this->cacheInstance1->isLocked($identifier1));
56+
57+
$this->assertTrue($this->cacheInstance2->lock($identifier1, -1));
58+
sleep(4);
59+
$this->assertTrue($this->cacheInstance1->isLocked($identifier1));
60+
}
61+
62+
/**
63+
* Verify that lock will be released after timeout expiration.
64+
*
65+
* @return void
66+
*/
67+
public function testParallelLockExpired(): void
68+
{
69+
$identifier1 = \uniqid('lock_name_1_', true);
70+
71+
$this->assertTrue($this->cacheInstance1->lock($identifier1, 1));
72+
sleep(2);
73+
$this->assertFalse($this->cacheInstance1->isLocked($identifier1));
74+
75+
$this->assertTrue($this->cacheInstance1->lock($identifier1, 1));
76+
sleep(2);
77+
$this->assertFalse($this->cacheInstance1->isLocked($identifier1));
78+
79+
$this->assertTrue($this->cacheInstance2->lock($identifier1, 1));
80+
sleep(2);
81+
$this->assertFalse($this->cacheInstance1->isLocked($identifier1));
82+
}
83+
84+
/**
85+
* Verify that lock will not be released by another lock name.
86+
*
87+
* @return void
88+
*/
89+
public function testParallelUnlock(): void
90+
{
91+
$identifier1 = \uniqid('lock_name_1_', true);
92+
$identifier2 = \uniqid('lock_name_2_', true);
93+
94+
$this->assertTrue($this->cacheInstance1->lock($identifier1, 30));
95+
$this->assertTrue($this->cacheInstance2->lock($identifier2, 30));
96+
97+
$this->assertFalse($this->cacheInstance2->unlock($identifier1));
98+
$this->assertTrue($this->cacheInstance2->unlock($identifier2));
99+
100+
$this->assertTrue($this->cacheInstance2->isLocked($identifier1));
101+
$this->assertFalse($this->cacheInstance2->isLocked($identifier2));
102+
}
103+
104+
/**
105+
* Verify that lock will not be released by another lock name when both locks will never be expired.
106+
*
107+
* @return void
108+
*/
109+
public function testParallelUnlockNoExpiration(): void
110+
{
111+
$identifier1 = \uniqid('lock_name_1_', true);
112+
$identifier2 = \uniqid('lock_name_2_', true);
113+
114+
$this->assertTrue($this->cacheInstance1->lock($identifier1, -1));
115+
$this->assertTrue($this->cacheInstance2->lock($identifier2, -1));
116+
117+
$this->assertFalse($this->cacheInstance2->unlock($identifier1));
118+
$this->assertTrue($this->cacheInstance2->unlock($identifier2));
119+
120+
$this->assertTrue($this->cacheInstance2->isLocked($identifier1));
121+
$this->assertFalse($this->cacheInstance2->isLocked($identifier2));
122+
}
123+
}

dev/tests/integration/testsuite/Magento/Framework/Lock/Backend/DatabaseTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use Magento\Framework\App\DeploymentConfig;
1212

1313
/**
14-
* \Magento\Framework\Lock\Backend\Database test case
14+
* \Magento\Framework\Lock\Backend\Database test case.
1515
*/
1616
class DatabaseTest extends \PHPUnit\Framework\TestCase
1717
{
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Framework\App\Cache;
8+
9+
/**
10+
* In memory cache state
11+
*
12+
* Used to ease testing of cache state modifications
13+
*/
14+
class InMemoryState implements StateInterface
15+
{
16+
/** @var bool[] */
17+
private $runtimeState = [];
18+
19+
/** @var bool[] */
20+
private $persistedState = [];
21+
22+
/**
23+
* InMemoryState constructor.
24+
* @param array $persistedState
25+
*/
26+
public function __construct(array $persistedState = [])
27+
{
28+
$this->persistedState = $persistedState;
29+
}
30+
31+
/**
32+
* @inheritDoc
33+
*/
34+
public function isEnabled($cacheType)
35+
{
36+
return $this->runtimeState[$cacheType]
37+
?? $this->persistedState[$cacheType]
38+
?? false;
39+
}
40+
41+
/**
42+
* @inheritDoc
43+
*/
44+
public function setEnabled($cacheType, $isEnabled)
45+
{
46+
$this->runtimeState[$cacheType] = $isEnabled;
47+
}
48+
49+
/**
50+
* @inheritDoc
51+
*/
52+
public function persist()
53+
{
54+
$this->persistedState = $this->runtimeState + $this->persistedState;
55+
$this->runtimeState = [];
56+
}
57+
58+
/**
59+
* Creates new instance with persistent state updated values
60+
*
61+
* @param bool[] $state
62+
* @return self
63+
*/
64+
public function withPersistedState(array $state): self
65+
{
66+
$newState = new self();
67+
$newState->persistedState = $state + $this->persistedState;
68+
return $newState;
69+
}
70+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Framework\App\Cache;
8+
9+
use Magento\Framework\Cache\StaleCacheNotifierInterface;
10+
11+
/**
12+
* Modifier of runtime cache state based on stale data notification from cache loader
13+
*/
14+
class RuntimeStaleCacheStateModifier implements StaleCacheNotifierInterface
15+
{
16+
/** @var StateInterface */
17+
private $cacheState;
18+
19+
/** @var string[] */
20+
private $cacheTypes;
21+
22+
/**
23+
* @param StateInterface $cacheState
24+
* @param string[] $cacheTypes
25+
*/
26+
public function __construct(StateInterface $cacheState, array $cacheTypes = [])
27+
{
28+
$this->cacheState = $cacheState;
29+
$this->cacheTypes = $cacheTypes;
30+
}
31+
32+
/**
33+
* Disabled configures cache types when stale cache was detected in the current request
34+
*/
35+
public function cacheLoaderIsUsingStaleCache()
36+
{
37+
foreach ($this->cacheTypes as $type) {
38+
$this->cacheState->setEnabled($type, false);
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)