Skip to content

Commit fed759c

Browse files
authored
Rewrite locker api (#6)
1 parent dbb6678 commit fed759c

14 files changed

+491
-448
lines changed

README.md

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,17 @@ composer require cybercog/php-db-locker
3434
```php
3535
$dbConnection = new PDO($dsn, $username, $password);
3636

37-
$postgresLocker = new \Cog\DbLocker\Locker\PostgresAdvisoryLocker();
38-
$postgresLockId = \Cog\DbLocker\LockId\PostgresLockId::fromKeyValue('user', '4');
37+
$locker = new \Cog\DbLocker\Postgres\PostgresAdvisoryLocker();
38+
$lockId = \Cog\DbLocker\Postgres\PostgresLockKey::create('user', '4');
3939

4040
$dbConnection->beginTransaction();
41-
$isLockAcquired = $postgresLocker->acquireLock(
41+
$lock = $locker->acquireSessionLevelLockHandler(
4242
$dbConnection,
43-
$postgresLockId,
44-
\Cog\DbLocker\Locker\PostgresAdvisoryLockScopeEnum::Transaction,
45-
\Cog\DbLocker\Locker\PostgresAdvisoryLockTypeEnum::NonBlocking,
46-
\Cog\DbLocker\Locker\PostgresLockModeEnum::Exclusive,
43+
$lockId,
44+
\Cog\DbLocker\Postgres\Enum\PostgresLockWaitModeEnum::NonBlocking,
45+
\Cog\DbLocker\Postgres\Enum\PostgresLockAccessModeEnum::Exclusive,
4746
);
48-
if ($isLockAcquired) {
47+
if ($lock->wasAcquired) {
4948
// Execute logic if lock was successful
5049
} else {
5150
// Execute logic if lock acquisition has been failed
@@ -58,22 +57,24 @@ $dbConnection->commit();
5857
```php
5958
$dbConnection = new PDO($dsn, $username, $password);
6059

61-
$postgresLocker = new \Cog\DbLocker\Locker\PostgresAdvisoryLocker();
62-
$postgresLockId = \Cog\DbLocker\LockId\PostgresLockId::fromKeyValue('user', '4');
63-
64-
$isLockAcquired = $postgresLocker->acquireLock(
65-
$dbConnection,
66-
$postgresLockId,
67-
\Cog\DbLocker\Locker\PostgresAdvisoryLockScopeEnum::Session,
68-
\Cog\DbLocker\Locker\PostgresAdvisoryLockTypeEnum::NonBlocking,
69-
\Cog\DbLocker\Locker\PostgresLockModeEnum::Exclusive,
70-
);
71-
if ($isLockAcquired) {
72-
// Execute logic if lock was successful
73-
} else {
74-
// Execute logic if lock acquisition has been failed
60+
$locker = new \Cog\DbLocker\Postgres\PostgresAdvisoryLocker();
61+
$lockId = \Cog\DbLocker\Postgres\PostgresLockKey::create('user', '4');
62+
63+
try {
64+
$lock = $locker->acquireSessionLevelLockHandler(
65+
$dbConnection,
66+
$lockId,
67+
\Cog\DbLocker\Postgres\Enum\PostgresLockWaitModeEnum::NonBlocking,
68+
\Cog\DbLocker\Postgres\Enum\PostgresLockAccessModeEnum::Exclusive,
69+
);
70+
if ($lock->wasAcquired) {
71+
// Execute logic if lock was successful
72+
} else {
73+
// Execute logic if lock acquisition has been failed
74+
}
75+
} finally {
76+
$lock->release();
7577
}
76-
$postgresLocker->releaseLock($dbConnection, $postgresLockId);
7778
```
7879

7980
## Changelog

src/LockId/LockId.php

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/Locker/PostgresAdvisoryLocker.php

Lines changed: 0 additions & 141 deletions
This file was deleted.

src/Locker/PostgresLockModeEnum.php

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Cog\DbLocker\Postgres\Enum;
6+
7+
/**
8+
* PostgresLockAccessModeEnum defines the access mode of advisory lock acquisition.
9+
*
10+
* TODO: Need string values only for tests, should add match to tests instead.
11+
*/
12+
enum PostgresLockAccessModeEnum: string
13+
{
14+
case Exclusive = 'ExclusiveLock';
15+
case Share = 'ShareLock';
16+
}

src/Locker/PostgresAdvisoryLockScopeEnum.php renamed to src/Postgres/Enum/PostgresLockLevelEnum.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
declare(strict_types=1);
44

5-
namespace Cog\DbLocker\Locker;
5+
namespace Cog\DbLocker\Postgres\Enum;
66

77
/**
8-
* PostgresAdvisoryLockScopeEnum defines the scope of advisory lock acquisition.
8+
* PostgresLockLevelEnum defines the level of advisory lock acquisition.
99
*
1010
* - Session. Session-level advisory lock (without _XACT_):
1111
* - PG_ADVISORY_LOCK
@@ -18,7 +18,7 @@
1818
* - PG_TRY_ADVISORY_XACT_LOCK
1919
* - PG_TRY_ADVISORY_XACT_LOCK_SHARED
2020
*/
21-
enum PostgresAdvisoryLockScopeEnum
21+
enum PostgresLockLevelEnum
2222
{
2323
case Session;
2424
case Transaction;

src/Locker/PostgresAdvisoryLockTypeEnum.php renamed to src/Postgres/Enum/PostgresLockWaitModeEnum.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
declare(strict_types=1);
44

5-
namespace Cog\DbLocker\Locker;
5+
namespace Cog\DbLocker\Postgres\Enum;
66

77
/**
8-
* PostgresAdvisoryLockTypeEnum defines the type of advisory lock acquisition.
8+
* PostgresLockWaitModeEnum defines the type of advisory lock acquisition.
99
*
1010
* - NonBlocking. Attempt to acquire the lock without blocking (with _TRY_):
1111
* - PG_TRY_ADVISORY_LOCK
@@ -18,8 +18,8 @@
1818
* - PG_ADVISORY_XACT_LOCK
1919
* - PG_ADVISORY_XACT_LOCK_SHARED
2020
*/
21-
enum PostgresAdvisoryLockTypeEnum
21+
enum PostgresLockWaitModeEnum
2222
{
23-
case NonBlocking;
2423
case Blocking;
24+
case NonBlocking;
2525
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
/*
4+
* This file is part of PHP DB Locker.
5+
*
6+
* (c) Anton Komarev <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Cog\DbLocker\Postgres\LockHandle;
15+
16+
use Cog\DbLocker\Postgres\Enum\PostgresLockAccessModeEnum;
17+
use Cog\DbLocker\Postgres\PostgresAdvisoryLocker;
18+
use Cog\DbLocker\Postgres\PostgresLockKey;
19+
use PDO;
20+
21+
/**
22+
* @internal
23+
*/
24+
final class SessionLevelLockHandle
25+
{
26+
private bool $isReleased = false;
27+
28+
public function __construct(
29+
private readonly PDO $dbConnection,
30+
private readonly PostgresAdvisoryLocker $locker,
31+
public readonly PostgresLockKey $lockId,
32+
public readonly PostgresLockAccessModeEnum $accessMode,
33+
public readonly bool $wasAcquired,
34+
) {}
35+
36+
/**
37+
* Explicitly release the lock if it was acquired and not yet released.
38+
*
39+
* @return bool True if the lock was released, false if it wasn't acquired or already released
40+
*/
41+
public function release(): bool
42+
{
43+
/**
44+
* This code is mimicking the behavior of DB lock release.
45+
*/
46+
if (!$this->wasAcquired || $this->isReleased) {
47+
return false;
48+
}
49+
50+
$wasReleased = $this->locker->releaseSessionLevelLock(
51+
$this->dbConnection,
52+
$this->lockId,
53+
);
54+
55+
if ($wasReleased) {
56+
$this->isReleased = true;
57+
}
58+
59+
return $wasReleased;
60+
}
61+
62+
/**
63+
* Automatically release the lock when the handle is destroyed.
64+
*/
65+
public function __destruct()
66+
{
67+
// TODO: Do we need to
68+
$this->release();
69+
}
70+
}

0 commit comments

Comments
 (0)