Skip to content

Commit 211715a

Browse files
committed
Stop acquiring distributed lock as soon as majority cannot be met
1 parent f2d29aa commit 211715a

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

src/Mutex/DistributedMutex.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ protected function acquireWithToken(string $key, float $expireTimeout)
5252

5353
// 2.
5454
$acquiredIndexes = [];
55+
$notAcquired = 0;
5556
$errored = 0;
5657
$exception = null;
5758
foreach ($this->mutexes as $index => $mutex) {
@@ -68,6 +69,14 @@ protected function acquireWithToken(string $key, float $expireTimeout)
6869

6970
++$errored;
7071
}
72+
73+
if (end($acquiredIndexes) !== $index) {
74+
++$notAcquired;
75+
}
76+
77+
if (!$this->isCountMajority(count($this->mutexes) - $notAcquired)) {
78+
break;
79+
}
7180
}
7281

7382
// 3.

tests/Mutex/DistributedMutexTest.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public function testTooFewServerToAcquire(int $count, int $available): void
9393
$mutex = $this->createDistributedMutexMock($count);
9494

9595
$i = 0;
96-
$mutex->expects(self::exactly($count))
96+
$mutex->expects(self::atMost((int) floor($count / 2) + $count - $available))
9797
->method('acquireMutex')
9898
->willReturnCallback(static function () use (&$i, $available) {
9999
if ($i++ < $available) {
@@ -307,6 +307,9 @@ public static function provideMinorityCases(): iterable
307307
yield [4, 0];
308308
yield [4, 1];
309309
yield [4, 2];
310+
yield [5, 2];
311+
yield [6, 2];
312+
yield [6, 3];
310313
}
311314

312315
/**
@@ -321,6 +324,7 @@ public static function provideMajorityCases(): iterable
321324
yield [3, 2];
322325
yield [3, 3];
323326
yield [4, 3];
327+
yield [5, 3];
324328
}
325329

326330
public function testAcquireMutexLogger(): void
@@ -329,12 +333,12 @@ public function testAcquireMutexLogger(): void
329333
$logger = $this->createMock(LoggerInterface::class);
330334
$mutex->setLogger($logger);
331335

332-
$mutex->expects(self::exactly(3))
336+
$mutex->expects(self::exactly(2))
333337
->method('acquireMutex')
334338
->with(self::isInstanceOf(AbstractSpinlockMutex::class), 'distributed', 1.0, \INF)
335339
->willThrowException($this->createMock(/* PredisException::class */ LockAcquireException::class));
336340

337-
$logger->expects(self::exactly(3))
341+
$logger->expects(self::exactly(2))
338342
->method('warning')
339343
->with('Could not set {key} = {token} at server #{index}', self::anything());
340344

0 commit comments

Comments
 (0)