Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ This library uses the namespace `Malkusch\Lock`.

### Mutex

The [`Malkusch\Lock\Mutex\Mutex`][5] class is an abstract class and provides the
base API for this library.
The [`Malkusch\Lock\Mutex\Mutex`][5] interface provides the base API for this library.

#### Mutex::synchronized()

Expand Down Expand Up @@ -125,9 +124,9 @@ if ($newBalance === false) {
}
```

### Extracting code result after lock release exception
#### Extracting code result after lock release exception

Mutex implementations based on [`Malkush\Lock\Mutex\LockMutex`][10] will throw
Mutex implementations based on [`Malkush\Lock\Mutex\AbstractLockMutex`][10] will throw
[`Malkusch\Lock\Exception\LockReleaseException`][11] in case of lock release
problem, but the synchronized code block will be already executed at this point.
In order to read the code result (or an exception thrown there),
Expand Down Expand Up @@ -160,9 +159,8 @@ try {

### Implementations

Because the [`Malkusch\Lock\Mutex\Mutex`](#mutex) class is an abstract class,
you can choose from one of the provided implementations or create/extend your
own implementation.
You can choose from one of the provided [`Malkusch\Lock\Mutex\Mutex`](#mutex) interface
implementations or create/extend your own implementation.

- [`FlockMutex`](#flockmutex)
- [`MemcachedMutex`](#memcachedmutex)
Expand All @@ -171,7 +169,7 @@ own implementation.
- [`SemaphoreMutex`](#semaphoremutex)
- [`TransactionalMutex`](#transactionalmutex)
- [`MySQLMutex`](#mysqlmutex)
- [`PgAdvisoryLockMutex`](#pgadvisorylockmutex)
- [`PostgreSQLMutex`](#PostgreSQLMutex)

#### FlockMutex

Expand Down Expand Up @@ -342,9 +340,9 @@ $mutex->synchronized(function () use ($bankAccount, $amount) {
});
```

#### PgAdvisoryLockMutex
#### PostgreSQLMutex

The **PgAdvisoryLockMutex** uses PostgreSQL's
The **PostgreSQLMutex** uses PostgreSQL's
[advisory locking](https://www.postgresql.org/docs/9.4/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS)
functions.

Expand All @@ -357,7 +355,7 @@ interrupted, the lock is automatically released.
```php
$pdo = new \PDO('pgsql:host=localhost;dbname=test', 'username');

$mutex = new PgAdvisoryLockMutex($pdo, 'balance');
$mutex = new PostgreSQLMutex($pdo, 'balance');
$mutex->synchronized(function () use ($bankAccount, $amount) {
$balance = $bankAccount->getBalance();
$balance -= $amount;
Expand Down
2 changes: 1 addition & 1 deletion src/Exception/ExecutionOutsideLockException.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*
* Should only be used in contexts where the is being released.
*
* @see \Malkusch\Lock\Mutex\SpinlockMutex::unlock()
* @see \Malkusch\Lock\Mutex\AbstractSpinlockMutex::unlock()
*/
class ExecutionOutsideLockException extends LockReleaseException
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
* @internal
*/
abstract class LockMutex extends Mutex
abstract class AbstractLockMutex extends AbstractMutex
{
/**
* Acquires the lock.
Expand Down
16 changes: 16 additions & 0 deletions src/Mutex/AbstractMutex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Malkusch\Lock\Mutex;

use Malkusch\Lock\Util\DoubleCheckedLocking;

abstract class AbstractMutex implements Mutex
{
#[\Override]
public function check(callable $check): DoubleCheckedLocking
{
return new DoubleCheckedLocking($this, $check);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
* @internal
*/
abstract class SpinlockMutex extends LockMutex
abstract class AbstractSpinlockMutex extends AbstractLockMutex
{
/** @var float The timeout in seconds a lock may live */
private $timeout;
Expand Down
2 changes: 1 addition & 1 deletion src/Mutex/FlockMutex.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* Flock() based mutex implementation.
*/
class FlockMutex extends LockMutex
class FlockMutex extends AbstractLockMutex
{
public const INFINITE_TIMEOUT = -1.0;

Expand Down
2 changes: 1 addition & 1 deletion src/Mutex/MemcachedMutex.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* Memcached based spinlock implementation.
*/
class MemcachedMutex extends SpinlockMutex
class MemcachedMutex extends AbstractSpinlockMutex
{
/** @var \Memcached */
private $memcache;
Expand Down
11 changes: 4 additions & 7 deletions src/Mutex/Mutex.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
use Malkusch\Lock\Util\DoubleCheckedLocking;

/**
* The mutex provides methods for exclusive execution.
* Mutex interface for exclusive execution.
*/
abstract class Mutex
interface Mutex
{
/**
* Executes a block of code exclusively.
Expand All @@ -35,7 +35,7 @@ abstract class Mutex
* @throws LockReleaseException The mutex could not be released, the code was already executed
* @throws ExecutionOutsideLockException Some code has been executed outside of the lock
*/
abstract public function synchronized(callable $code);
public function synchronized(callable $code);

/**
* Performs a double-checked locking pattern.
Expand All @@ -57,8 +57,5 @@ abstract public function synchronized(callable $code);
*
* @return DoubleCheckedLocking The double-checked locking pattern
*/
public function check(callable $check): DoubleCheckedLocking
{
return new DoubleCheckedLocking($this, $check);
}
public function check(callable $check): DoubleCheckedLocking;
}
2 changes: 1 addition & 1 deletion src/Mutex/MySQLMutex.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use Malkusch\Lock\Exception\TimeoutException;
use Malkusch\Lock\Util\LockUtil;

class MySQLMutex extends LockMutex
class MySQLMutex extends AbstractLockMutex
{
/** @var \PDO */
private $pdo;
Expand Down
2 changes: 1 addition & 1 deletion src/Mutex/NoMutex.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* Synchronization is not provided! This mutex is just implementing the
* interface without locking.
*/
class NoMutex extends Mutex
class NoMutex extends AbstractMutex
{
#[\Override]
public function synchronized(callable $code)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use Malkusch\Lock\Util\LockUtil;

class PgAdvisoryLockMutex extends LockMutex
class PostgreSQLMutex extends AbstractLockMutex
{
/** @var \PDO */
private $pdo;
Expand Down
2 changes: 1 addition & 1 deletion src/Mutex/RedisMutex.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @see http://redis.io/topics/distlock
*/
abstract class RedisMutex extends SpinlockMutex implements LoggerAwareInterface
abstract class RedisMutex extends AbstractSpinlockMutex implements LoggerAwareInterface
{
use LoggerAwareTrait;

Expand Down
2 changes: 1 addition & 1 deletion src/Mutex/SemaphoreMutex.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/**
* System V IPC based mutex implementation.
*/
class SemaphoreMutex extends LockMutex
class SemaphoreMutex extends AbstractLockMutex
{
/** @var \SysvSemaphore|resource The semaphore id */
private $semaphore;
Expand Down
2 changes: 1 addition & 1 deletion src/Mutex/TransactionalMutex.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
* A failing transaction will be replayed.
*/
class TransactionalMutex extends Mutex
class TransactionalMutex extends AbstractMutex
{
/** @var \PDO */
private $pdo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@

use Malkusch\Lock\Exception\LockAcquireException;
use Malkusch\Lock\Exception\LockReleaseException;
use Malkusch\Lock\Mutex\LockMutex;
use Malkusch\Lock\Mutex\AbstractLockMutex;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class LockMutexTest extends TestCase
class AbstractLockMutexTest extends TestCase
{
/** @var LockMutex&MockObject */
/** @var AbstractLockMutex&MockObject */
private $mutex;

#[\Override]
protected function setUp(): void
{
parent::setUp();

$this->mutex = $this->getMockBuilder(LockMutex::class)
$this->mutex = $this->getMockBuilder(AbstractLockMutex::class)
->onlyMethods(['lock', 'unlock'])
->getMock();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
use Malkusch\Lock\Exception\LockAcquireException;
use Malkusch\Lock\Exception\LockReleaseException;
use Malkusch\Lock\Exception\TimeoutException;
use Malkusch\Lock\Mutex\SpinlockMutex;
use Malkusch\Lock\Mutex\AbstractSpinlockMutex;
use phpmock\environment\SleepEnvironmentBuilder;
use phpmock\MockEnabledException;
use phpmock\phpunit\PHPMock;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

class SpinlockMutexTest extends TestCase
class AbstractSpinlockMutexTest extends TestCase
{
use PHPMock;

Expand All @@ -39,11 +39,11 @@ protected function setUp(): void
}

/**
* @return SpinlockMutex&MockObject
* @return AbstractSpinlockMutex&MockObject
*/
private function createSpinlockMutexMock(float $timeout = 3): SpinlockMutex
private function createAbstractSpinlockMutexMock(float $timeout = 3): AbstractSpinlockMutex
{
return $this->getMockBuilder(SpinlockMutex::class)
return $this->getMockBuilder(AbstractSpinlockMutex::class)
->setConstructorArgs(['test', $timeout])
->onlyMethods(['acquire', 'release'])
->getMock();
Expand All @@ -56,7 +56,7 @@ public function testFailAcquireLock(): void
{
$this->expectException(LockAcquireException::class);

$mutex = $this->createSpinlockMutexMock();
$mutex = $this->createAbstractSpinlockMutexMock();
$mutex->expects(self::any())
->method('acquire')
->willThrowException(new LockAcquireException());
Expand All @@ -74,7 +74,7 @@ public function testAcquireTimesOut(): void
$this->expectException(TimeoutException::class);
$this->expectExceptionMessage('Timeout of 3.0 seconds exceeded');

$mutex = $this->createSpinlockMutexMock();
$mutex = $this->createAbstractSpinlockMutexMock();
$mutex->expects(self::atLeastOnce())
->method('acquire')
->willReturn(false);
Expand All @@ -89,7 +89,7 @@ public function testAcquireTimesOut(): void
*/
public function testExecuteTooLong(): void
{
$mutex = $this->createSpinlockMutexMock(0.5);
$mutex = $this->createAbstractSpinlockMutexMock(0.5);
$mutex->expects(self::any())
->method('acquire')
->willReturn(true);
Expand All @@ -114,7 +114,7 @@ public function testExecuteTooLong(): void
*/
public function testExecuteBarelySucceeds(): void
{
$mutex = $this->createSpinlockMutexMock(0.5);
$mutex = $this->createAbstractSpinlockMutexMock(0.5);
$mutex->expects(self::any())->method('acquire')->willReturn(true);
$mutex->expects(self::once())->method('release')->willReturn(true);

Expand All @@ -130,7 +130,7 @@ public function testFailReleasingLock(): void
{
$this->expectException(LockReleaseException::class);

$mutex = $this->createSpinlockMutexMock();
$mutex = $this->createAbstractSpinlockMutexMock();
$mutex->expects(self::any())->method('acquire')->willReturn(true);
$mutex->expects(self::any())->method('release')->willReturn(false);

Expand All @@ -142,7 +142,7 @@ public function testFailReleasingLock(): void
*/
public function testExecuteTimeoutLeavesOneSecondForKeyToExpire(): void
{
$mutex = $this->createSpinlockMutexMock(0.2);
$mutex = $this->createAbstractSpinlockMutexMock(0.2);
$mutex->expects(self::once())
->method('acquire')
->with(self::anything(), 1.2)
Expand Down
6 changes: 3 additions & 3 deletions tests/Mutex/MutexConcurrencyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use Malkusch\Lock\Mutex\MemcachedMutex;
use Malkusch\Lock\Mutex\Mutex;
use Malkusch\Lock\Mutex\MySQLMutex;
use Malkusch\Lock\Mutex\PgAdvisoryLockMutex;
use Malkusch\Lock\Mutex\PHPRedisMutex;
use Malkusch\Lock\Mutex\PostgreSQLMutex;
use Malkusch\Lock\Mutex\PredisMutex;
use Malkusch\Lock\Mutex\SemaphoreMutex;
use Malkusch\Lock\Mutex\TransactionalMutex;
Expand Down Expand Up @@ -325,11 +325,11 @@ static function (string $uri): \Redis {
}

if (getenv('PGSQL_DSN')) {
yield 'PgAdvisoryLockMutex' => [static function (): Mutex {
yield 'PostgreSQLMutex' => [static function (): Mutex {
$pdo = new \PDO(getenv('PGSQL_DSN'), getenv('PGSQL_USER'), getenv('PGSQL_PASSWORD'));
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

return new PgAdvisoryLockMutex($pdo, 'test');
return new PostgreSQLMutex($pdo, 'test');
}];
}
}
Expand Down
Loading