1 | <?php |
||
12 | final class RedLock implements Locker |
||
13 | { |
||
14 | /** @var float */ |
||
15 | const CLOCK_DRIFT_FACTOR = 0.01; |
||
16 | |||
17 | /** @var \Redis[] */ |
||
18 | private $instances = []; |
||
19 | |||
20 | /** @var TokenGenerator */ |
||
21 | private $tokenGenerator; |
||
22 | |||
23 | /** @var Stopwatch */ |
||
24 | private $stopwatch; |
||
25 | |||
26 | /** @var int */ |
||
27 | private $quorum; |
||
28 | |||
29 | /** |
||
30 | * @param \Redis[] $instances Array of pre-connected \Redis objects |
||
31 | * @param TokenGenerator $tokenGenerator The token generator |
||
32 | * @param Stopwatch $stopwatch A way to measure time passed |
||
33 | */ |
||
34 | 39 | public function __construct( |
|
45 | |||
46 | /** |
||
47 | * {@inheritdoc} |
||
48 | */ |
||
49 | 12 | public function lock($resource, $ttl = null, $retryDelay = 0, $retryCount = 0) |
|
70 | |||
71 | /** |
||
72 | * {@inheritdoc} |
||
73 | */ |
||
74 | 9 | public function isResourceLocked($resource) |
|
84 | |||
85 | /** |
||
86 | * {@inheritdoc} |
||
87 | */ |
||
88 | 12 | public function unlock(Lock $lock) |
|
98 | |||
99 | /** |
||
100 | * @param Lock $lock |
||
101 | * @param int $ttl |
||
102 | * |
||
103 | * @throws LockingException |
||
104 | * |
||
105 | * @return Lock |
||
106 | */ |
||
107 | 12 | private function monitoredLockingOfAllInstances(Lock $lock, $ttl) |
|
122 | |||
123 | /** |
||
124 | * @param Lock $lock |
||
125 | * @param int $ttl |
||
126 | * |
||
127 | * @return int The number of instances locked |
||
128 | */ |
||
129 | 12 | private function lockInstances(Lock $lock, $ttl) |
|
141 | |||
142 | /** |
||
143 | * @param \Redis $instance Server instance to be locked |
||
144 | * @param Lock $lock The lock instance |
||
145 | * @param int $ttl Time to live in milliseconds |
||
146 | * |
||
147 | * @return bool |
||
148 | */ |
||
149 | 12 | private function lockInstance(\Redis $instance, Lock $lock, $ttl) |
|
159 | |||
160 | /** |
||
161 | * @param Lock $lock |
||
162 | */ |
||
163 | 6 | private function resetLock($lock) |
|
169 | |||
170 | /** |
||
171 | * @param \Redis $instance |
||
172 | * @param string $resource |
||
173 | * |
||
174 | * @return bool |
||
175 | */ |
||
176 | 18 | private function isInstanceResourceLocked(\Redis $instance, $resource) |
|
180 | |||
181 | /** |
||
182 | * @param \Redis $instance Server instance to be unlocked |
||
183 | * @param Lock $lock The lock to unlock |
||
184 | * |
||
185 | * @return bool |
||
186 | */ |
||
187 | 18 | private function unlockInstance(\Redis $instance, Lock $lock) |
|
203 | |||
204 | /** |
||
205 | * @param \Redis[] $instances |
||
206 | * |
||
207 | * @throws \Exception |
||
208 | */ |
||
209 | 39 | private function setInstances(array $instances) |
|
223 | |||
224 | 39 | private function setQuorum() |
|
229 | |||
230 | /** |
||
231 | * @param int $instancesLocked |
||
232 | * |
||
233 | * @throws LockingException |
||
234 | */ |
||
235 | 12 | private function checkQuorum($instancesLocked) |
|
241 | |||
242 | /** |
||
243 | * @param int $retryDelay |
||
244 | */ |
||
245 | 6 | private function waitBeforeRetrying($retryDelay) |
|
249 | |||
250 | /** |
||
251 | * @param int $elapsedTime |
||
252 | * @param int $ttl |
||
253 | * |
||
254 | * @throws LockingException |
||
255 | */ |
||
256 | 6 | private static function checkTtl($elapsedTime, $ttl) |
|
264 | |||
265 | /** |
||
266 | * Get the drift time based on ttl in ms. |
||
267 | * |
||
268 | * @param int $ttl |
||
269 | * |
||
270 | * @return float |
||
271 | */ |
||
272 | 6 | private static function getDrift($ttl) |
|
283 | } |
||
284 |