Skip to content

Commit e74100d

Browse files
committed
Rewrite logic to two keyed lock
1 parent bc1b55f commit e74100d

File tree

5 files changed

+219
-87
lines changed

5 files changed

+219
-87
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Cog\DbLocker\Locker;
6+
7+
/**
8+
* PostgresAdvisoryLockModeEnum defines the mode of advisory lock acquisition.
9+
*
10+
* - Try: Attempt to acquire the lock without blocking (PG_TRY_ADVISORY_LOCK, PG_TRY_ADVISORY_XACT_LOCK).
11+
* - Block: Acquire the lock, blocking until it becomes available (PG_ADVISORY_LOCK, PG_ADVISORY_XACT_LOCK).
12+
*/
13+
enum PostgresAdvisoryLockModeEnum
14+
{
15+
case Try;
16+
case Block;
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Cog\DbLocker\Locker;
6+
7+
/**
8+
* PostgresAdvisoryLockScopeEnum defines the scope of advisory lock acquisition.
9+
*
10+
* - Session: Session-level advisory lock (PG_ADVISORY_LOCK, PG_TRY_ADVISORY_LOCK)
11+
* - Transaction: Transaction-level advisory lock (PG_ADVISORY_XACT_LOCK, PG_TRY_ADVISORY_XACT_LOCK)
12+
*/
13+
enum PostgresAdvisoryLockScopeEnum
14+
{
15+
case Session;
16+
case Transaction;
17+
}

src/Locker/PostgresAdvisoryLocker.php

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,48 +20,29 @@
2020
final class PostgresAdvisoryLocker
2121
{
2222
/**
23-
* Acquire transaction-level lock (recommended).
23+
* Acquire an advisory lock with configurable scope and mode.
2424
*/
25-
public function acquireLockWithinTransaction(
25+
public function acquireLock(
2626
PDO $dbConnection,
2727
PostgresLockId $postgresLockId,
28-
PostgresLockModeEnum $lockMode = PostgresLockModeEnum::Try,
28+
PostgresAdvisoryLockScopeEnum $scope = PostgresAdvisoryLockScopeEnum::Transaction,
29+
PostgresAdvisoryLockModeEnum $mode = PostgresAdvisoryLockModeEnum::Try,
2930
): bool {
30-
if ($dbConnection->inTransaction() === false) {
31-
$lockId = $postgresLockId->humanReadableValue;
32-
31+
if ($scope === PostgresAdvisoryLockScopeEnum::Transaction && $dbConnection->inTransaction() === false) {
3332
throw new LogicException(
34-
"Transaction-level advisory lock `$lockId` cannot be acquired outside of transaction",
33+
"Transaction-level advisory lock `$postgresLockId->humanReadableValue` cannot be acquired outside of transaction",
3534
);
3635
}
3736

38-
$sql = match ($lockMode) {
39-
PostgresLockModeEnum::Try => 'SELECT PG_TRY_ADVISORY_XACT_LOCK(:class_id, :object_id); -- ' . $postgresLockId->humanReadableValue,
40-
PostgresLockModeEnum::Block => 'SELECT PG_ADVISORY_XACT_LOCK(:class_id, :object_id); -- ' . $postgresLockId->humanReadableValue,
41-
};
42-
43-
$statement = $dbConnection->prepare($sql);
44-
$statement->execute(
45-
[
46-
'class_id' => $postgresLockId->classId,
47-
'object_id' => $postgresLockId->objectId,
48-
],
49-
);
50-
51-
return $statement->fetchColumn(0);
52-
}
53-
54-
/**
55-
* Acquire session-level lock (use only if transaction-level lock not applicable).
56-
*/
57-
public function acquireLockWithinSession(
58-
PDO $dbConnection,
59-
PostgresLockId $postgresLockId,
60-
PostgresLockModeEnum $lockMode = PostgresLockModeEnum::Try,
61-
): bool {
62-
$sql = match ($lockMode) {
63-
PostgresLockModeEnum::Try => 'SELECT PG_TRY_ADVISORY_LOCK(:class_id, :object_id); -- ' . $postgresLockId->humanReadableValue,
64-
PostgresLockModeEnum::Block => 'SELECT PG_ADVISORY_LOCK(:class_id, :object_id); -- ' . $postgresLockId->humanReadableValue,
37+
$sql = match ([$scope, $mode]) {
38+
[PostgresAdvisoryLockScopeEnum::Transaction, PostgresAdvisoryLockModeEnum::Try] =>
39+
'SELECT PG_TRY_ADVISORY_XACT_LOCK(:class_id, :object_id); -- ' . $postgresLockId->humanReadableValue,
40+
[PostgresAdvisoryLockScopeEnum::Transaction, PostgresAdvisoryLockModeEnum::Block] =>
41+
'SELECT PG_ADVISORY_XACT_LOCK(:class_id, :object_id); -- ' . $postgresLockId->humanReadableValue,
42+
[PostgresAdvisoryLockScopeEnum::Session, PostgresAdvisoryLockModeEnum::Try] =>
43+
'SELECT PG_TRY_ADVISORY_LOCK(:class_id, :object_id); -- ' . $postgresLockId->humanReadableValue,
44+
[PostgresAdvisoryLockScopeEnum::Session, PostgresAdvisoryLockModeEnum::Block] =>
45+
'SELECT PG_ADVISORY_LOCK(:class_id, :object_id); -- ' . $postgresLockId->humanReadableValue,
6546
};
6647

6748
$statement = $dbConnection->prepare($sql);

src/Locker/PostgresLockModeEnum.php

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

0 commit comments

Comments
 (0)