forked from ConvertGroupsAS/magento2-patches
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Patch-Magento_Framework-M2.2-cron-prevent-already-running.patch
219 lines (219 loc) · 6.01 KB
/
Patch-Magento_Framework-M2.2-cron-prevent-already-running.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
--- /dev/null 2018-05-18 09:11:58.401867852 +0300
+++ /Lock/Backend/Database.php 2018-05-18 09:32:25.700949036 +0300
@@ -0,0 +1,158 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+declare(strict_types=1);
+namespace Magento\Framework\Lock\Backend;
+
+use Magento\Framework\App\DeploymentConfig;
+use Magento\Framework\App\ResourceConnection;
+use Magento\Framework\Config\ConfigOptionsListConstants;
+use Magento\Framework\Exception\AlreadyExistsException;
+use Magento\Framework\Exception\InputException;
+use Magento\Framework\Phrase;
+
+class Database implements \Magento\Framework\Lock\LockManagerInterface
+{
+ /** @var ResourceConnection */
+ private $resource;
+
+ /** @var DeploymentConfig */
+ private $deploymentConfig;
+
+ /** @var string Lock prefix */
+ private $prefix;
+
+ /** @var string|false Holds current lock name if set, otherwise false */
+ private $currentLock = false;
+
+ public function __construct(
+ ResourceConnection $resource,
+ DeploymentConfig $deploymentConfig,
+ string $prefix = null
+ ) {
+ $this->resource = $resource;
+ $this->deploymentConfig = $deploymentConfig;
+ $this->prefix = $prefix;
+ }
+
+ /**
+ * Sets a lock for name
+ *
+ * @param string $name lock name
+ * @param int $timeout How long to wait lock acquisition in seconds, negative value means infinite timeout
+ * @return bool
+ * @throws InputException
+ * @throws AlreadyExistsException
+ */
+ public function lock(string $name, int $timeout = -1): bool
+ {
+ $name = $this->addPrefix($name);
+
+ /**
+ * Before MySQL 5.7.5, only a single simultaneous lock per connection can be acquired.
+ * This limitation can be removed once MySQL minimum requirement has been raised,
+ * currently we support MySQL 5.6 way only.
+ */
+ if ($this->currentLock) {
+ throw new AlreadyExistsException(
+ new Phrase(
+ 'Current connection is already holding lock for $1, only single lock allowed',
+ [$this->currentLock]
+ )
+ );
+ }
+
+ $result = (bool)$this->resource->getConnection()->query(
+ "SELECT GET_LOCK(?, ?);",
+ [(string)$name, (int)$timeout]
+ )->fetchColumn();
+
+ if ($result === true) {
+ $this->currentLock = $name;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Releases a lock for name
+ *
+ * @param string $name lock name
+ * @return bool
+ * @throws InputException
+ */
+ public function unlock(string $name): bool
+ {
+ $name = $this->addPrefix($name);
+
+ $result = (bool)$this->resource->getConnection()->query(
+ "SELECT RELEASE_LOCK(?);",
+ [(string)$name]
+ )->fetchColumn();
+
+ if ($result === true) {
+ $this->currentLock = false;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Tests of lock is set for name
+ *
+ * @param string $name lock name
+ * @return bool
+ * @throws InputException
+ */
+ public function isLocked(string $name): bool
+ {
+ $name = $this->addPrefix($name);
+
+ return (bool)$this->resource->getConnection()->query(
+ "SELECT IS_USED_LOCK(?);",
+ [(string)$name]
+ )->fetchColumn();
+ }
+
+ /**
+ * Adds prefix and checks for max length of lock name
+ *
+ * Limited to 64 characters in MySQL.
+ *
+ * @param string $name
+ * @return string $name
+ * @throws InputException
+ */
+ private function addPrefix(string $name): string
+ {
+ $name = $this->getPrefix() . '|' . $name;
+
+ if (strlen($name) > 64) {
+ throw new InputException(new Phrase('Lock name too long: %1...', [substr($name, 0, 64)]));
+ }
+
+ return $name;
+ }
+
+ /**
+ * Get installation specific lock prefix to avoid lock conflicts
+ *
+ * @return string lock prefix
+ */
+ private function getPrefix(): string
+ {
+ if ($this->prefix === null) {
+ $this->prefix = (string)$this->deploymentConfig->get(
+ ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT
+ . '/'
+ . ConfigOptionsListConstants::KEY_NAME,
+ ''
+ );
+ }
+
+ return $this->prefix;
+ }
+}
--- /dev/null 2018-05-18 09:11:58.401867852 +0300
+++ /Lock/LockManagerInterface.php 2018-05-18 09:33:25.780470807 +0300
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+declare(strict_types=1);
+namespace Magento\Framework\Lock;
+
+/**
+ * Interface of a lock manager
+ *
+ * @api
+ */
+interface LockManagerInterface
+{
+ /**
+ * Sets a lock
+ *
+ * @param string $name lock name
+ * @param int $timeout How long to wait lock acquisition in seconds, negative value means infinite timeout
+ * @return bool
+ * @api
+ */
+ public function lock(string $name, int $timeout = -1): bool;
+
+ /**
+ * Releases a lock
+ *
+ * @param string $name lock name
+ * @return bool
+ * @api
+ */
+ public function unlock(string $name): bool;
+
+ /**
+ * Tests if lock is set
+ *
+ * @param string $name lock name
+ * @return bool
+ * @api
+ */
+ public function isLocked(string $name): bool;
+}
--- /dev/null 2018-05-18 09:11:58.401867852 +0300
+++ /Lock/README.md 2018-05-18 09:34:10.920059113 +0300
@@ -0,0 +1,8 @@
+# Lock library
+
+Lock library provides mechanism to acquire Magento system-wide lock. Default implementation is based on MySQL locks, where any locks are automatically released on connection close.
+
+The library provides interface *LockManagerInterface* which provides following methods:
+* *lock* - Acquires a named lock
+* *unlock* - Releases a named lock
+* *isLocked* - Tests if a named lock exists