Skip to content

Commit ec62bf7

Browse files
committed
MAGETWO-98151: Add support ZooKeeper locks
1 parent 7710c22 commit ec62bf7

File tree

8 files changed

+619
-14
lines changed

8 files changed

+619
-14
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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\Zookeeper as ZookeeperLock;
11+
use Magento\Framework\Lock\LockBackendFactory;
12+
use Magento\Framework\Config\File\ConfigFilePool;
13+
use Magento\Framework\App\DeploymentConfig\FileReader;
14+
use Magento\Framework\Stdlib\ArrayManager;
15+
16+
/**
17+
* \Magento\Framework\Lock\Backend\Zookeeper test case
18+
*/
19+
class ZookeeperTest extends \PHPUnit\Framework\TestCase
20+
{
21+
/**
22+
* @var FileReader
23+
*/
24+
private $configReader;
25+
26+
/**
27+
* @var \Magento\Framework\ObjectManagerInterface
28+
*/
29+
private $objectManager;
30+
31+
/**
32+
* @var LockBackendFactory
33+
*/
34+
private $lockBackendFactory;
35+
36+
/**
37+
* @var ArrayManager
38+
*/
39+
private $arrayManager;
40+
41+
/**
42+
* @var ZookeeperLock
43+
*/
44+
private $model;
45+
46+
/**
47+
* @inheritdoc
48+
*/
49+
protected function setUp()
50+
{
51+
if (!extension_loaded('zookeeper')) {
52+
$this->markTestSkipped('php extension Zookeeper is not installed.');
53+
}
54+
55+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
56+
$this->configReader = $this->objectManager->get(FileReader::class);
57+
$this->lockBackendFactory = $this->objectManager->create(LockBackendFactory::class);
58+
$this->arrayManager = $this->objectManager->create(ArrayManager::class);
59+
$config = $this->configReader->load(ConfigFilePool::APP_ENV);
60+
61+
if ($this->arrayManager->get('lock/provider', $config) !== 'zookeeper') {
62+
$this->markTestSkipped('Zookeeper is not configured during installation.');
63+
}
64+
65+
$this->model = $this->lockBackendFactory->create();
66+
$this->assertInstanceOf(ZookeeperLock::class, $this->model);
67+
}
68+
69+
public function testLockAndUnlock()
70+
{
71+
$name = 'test_lock';
72+
73+
$this->assertFalse($this->model->isLocked($name));
74+
75+
$this->assertTrue($this->model->lock($name));
76+
$this->assertTrue($this->model->isLocked($name));
77+
78+
$this->assertTrue($this->model->unlock($name));
79+
$this->assertFalse($this->model->isLocked($name));
80+
}
81+
82+
public function testUnlockWithoutExistingLock()
83+
{
84+
$name = 'test_lock';
85+
86+
$this->assertFalse($this->model->isLocked($name));
87+
$this->assertFalse($this->model->unlock($name));
88+
}
89+
}
90+

lib/internal/Magento/Framework/Lock/Backend/Zookeeper.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class Zookeeper implements LockManagerInterface
3131
private $path;
3232

3333
/**
34+
* The name of sequence nodes
35+
*
3436
* @var string
3537
*/
3638
private $lockName = 'lock-';
@@ -70,12 +72,17 @@ class Zookeeper implements LockManagerInterface
7072
*/
7173
private $locks = [];
7274

75+
/**
76+
* The default path to storage locks
77+
*/
78+
const DEFAULT_PATH = '/magento/locks';
79+
7380
/**
7481
* @param string $host The host to connect to Zookeeper
7582
* @param string $path The base path to locks in Zookeeper
7683
* @throws RuntimeException
7784
*/
78-
public function __construct(string $host, string $path = '/magento/locks')
85+
public function __construct(string $host, string $path = self::DEFAULT_PATH)
7986
{
8087
if (empty($path)) {
8188
throw new RuntimeException(
@@ -164,7 +171,7 @@ private function getFullPathToLock(string $name): string
164171
* @return \Zookeeper
165172
* @throws RuntimeException
166173
*/
167-
private function getProvider(): \Zookeeper
174+
public function getProvider(): \Zookeeper
168175
{
169176
if (!$this->zookeeper) {
170177
$this->zookeeper = new \Zookeeper($this->host);

lib/internal/Magento/Framework/Lock/LockBackendFactory.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Magento\Framework\App\DeploymentConfig;
1414
use Magento\Framework\Lock\Backend\Database as DatabaseLock;
1515
use Magento\Framework\Lock\Backend\Zookeeper as ZookeeperLock;
16+
use Magento\Framework\Lock\Backend\Cache as CacheLock;
1617

1718
/**
1819
* The factory to create object that implements LockManagerInterface
@@ -47,14 +48,22 @@ class LockBackendFactory
4748
*/
4849
const LOCK_ZOOKEEPER = 'zookeeper';
4950

51+
/**
52+
* Cache lock provider name
53+
*
54+
* @const string
55+
*/
56+
const LOCK_CACHE = 'cache';
57+
5058
/**
5159
* The list of lock providers with mapping on classes
5260
*
5361
* @var array
5462
*/
5563
private $lockers = [
5664
self::LOCK_DB => DatabaseLock::class,
57-
self::LOCK_ZOOKEEPER => ZookeeperLock::class
65+
self::LOCK_ZOOKEEPER => ZookeeperLock::class,
66+
self::LOCK_CACHE => CacheLock::class,
5867
];
5968

6069
/**
@@ -77,8 +86,8 @@ public function __construct(
7786
*/
7887
public function create(): LockManagerInterface
7988
{
80-
$provider = $this->deploymentConfig->get('locks/provider', self::LOCK_DB);
81-
$config = $this->deploymentConfig->get('locks/config', []);
89+
$provider = $this->deploymentConfig->get('lock/provider', self::LOCK_DB);
90+
$config = $this->deploymentConfig->get('lock/config', []);
8291

8392
if (!isset($this->lockers[$provider])) {
8493
throw new RuntimeException(new Phrase('Unknown locks provider.'));

lib/internal/Magento/Framework/Lock/Test/Unit/LockBackendFactoryTest.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use Magento\Framework\Lock\Backend\Database as DatabaseLock;
1111
use Magento\Framework\Lock\Backend\Zookeeper as ZookeeperLock;
12+
use Magento\Framework\Lock\Backend\Cache as CacheLock;
1213
use Magento\Framework\Lock\LockBackendFactory;
1314
use Magento\Framework\ObjectManagerInterface;
1415
use Magento\Framework\Lock\LockManagerInterface;
@@ -51,7 +52,7 @@ public function testCreateWithException()
5152
{
5253
$this->deploymentConfigMock->expects($this->exactly(2))
5354
->method('get')
54-
->withConsecutive(['locks/provider', LockBackendFactory::LOCK_DB], ['locks/config', []])
55+
->withConsecutive(['lock/provider', LockBackendFactory::LOCK_DB], ['lock/config', []])
5556
->willReturnOnConsecutiveCalls('someProvider', []);
5657

5758
$this->factory->create();
@@ -68,7 +69,7 @@ public function testCreate(string $lockProvider, string $lockProviderClass, arra
6869
$lockManagerMock = $this->getMockForAbstractClass(LockManagerInterface::class);
6970
$this->deploymentConfigMock->expects($this->exactly(2))
7071
->method('get')
71-
->withConsecutive(['locks/provider', LockBackendFactory::LOCK_DB], ['locks/config', []])
72+
->withConsecutive(['lock/provider', LockBackendFactory::LOCK_DB], ['lock/config', []])
7273
->willReturnOnConsecutiveCalls($lockProvider, $config);
7374
$this->objectManagerMock->expects($this->once())
7475
->method('create')
@@ -89,6 +90,11 @@ public function createDataProvider(): array
8990
'lockProviderClass' => DatabaseLock::class,
9091
'config' => ['prefix' => 'somePrefix'],
9192
],
93+
'cache' => [
94+
'lockProvider' => LockBackendFactory::LOCK_CACHE,
95+
'lockProviderClass' => CacheLock::class,
96+
'config' => [],
97+
],
9298
];
9399

94100
if (extension_loaded('zookeeper')) {

setup/src/Magento/Setup/Model/ConfigOptionsList.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ class ConfigOptionsList implements ConfigOptionsListInterface
5050
private $configOptionsListClasses = [
5151
\Magento\Setup\Model\ConfigOptionsList\Session::class,
5252
\Magento\Setup\Model\ConfigOptionsList\Cache::class,
53-
\Magento\Setup\Model\ConfigOptionsList\PageCache::class
53+
\Magento\Setup\Model\ConfigOptionsList\PageCache::class,
54+
\Magento\Setup\Model\ConfigOptionsList\Lock::class,
5455
];
5556

5657
/**

0 commit comments

Comments
 (0)