Skip to content

Rewrite locker api #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 28, 2025
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
47 changes: 24 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,17 @@ composer require cybercog/php-db-locker
```php
$dbConnection = new PDO($dsn, $username, $password);

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

$dbConnection->beginTransaction();
$isLockAcquired = $postgresLocker->acquireLock(
$lock = $locker->acquireSessionLevelLockHandler(
$dbConnection,
$postgresLockId,
\Cog\DbLocker\Locker\PostgresAdvisoryLockScopeEnum::Transaction,
\Cog\DbLocker\Locker\PostgresAdvisoryLockTypeEnum::NonBlocking,
\Cog\DbLocker\Locker\PostgresLockModeEnum::Exclusive,
$lockId,
\Cog\DbLocker\Postgres\Enum\PostgresLockWaitModeEnum::NonBlocking,
\Cog\DbLocker\Postgres\Enum\PostgresLockAccessModeEnum::Exclusive,
);
if ($isLockAcquired) {
if ($lock->wasAcquired) {
// Execute logic if lock was successful
} else {
// Execute logic if lock acquisition has been failed
Expand All @@ -58,22 +57,24 @@ $dbConnection->commit();
```php
$dbConnection = new PDO($dsn, $username, $password);

$postgresLocker = new \Cog\DbLocker\Locker\PostgresAdvisoryLocker();
$postgresLockId = \Cog\DbLocker\LockId\PostgresLockId::fromKeyValue('user', '4');

$isLockAcquired = $postgresLocker->acquireLock(
$dbConnection,
$postgresLockId,
\Cog\DbLocker\Locker\PostgresAdvisoryLockScopeEnum::Session,
\Cog\DbLocker\Locker\PostgresAdvisoryLockTypeEnum::NonBlocking,
\Cog\DbLocker\Locker\PostgresLockModeEnum::Exclusive,
);
if ($isLockAcquired) {
// Execute logic if lock was successful
} else {
// Execute logic if lock acquisition has been failed
$locker = new \Cog\DbLocker\Postgres\PostgresAdvisoryLocker();
$lockId = \Cog\DbLocker\Postgres\PostgresLockKey::create('user', '4');

try {
$lock = $locker->acquireSessionLevelLockHandler(
$dbConnection,
$lockId,
\Cog\DbLocker\Postgres\Enum\PostgresLockWaitModeEnum::NonBlocking,
\Cog\DbLocker\Postgres\Enum\PostgresLockAccessModeEnum::Exclusive,
);
if ($lock->wasAcquired) {
// Execute logic if lock was successful
} else {
// Execute logic if lock acquisition has been failed
}
} finally {
$lock->release();
}
$postgresLocker->releaseLock($dbConnection, $postgresLockId);
```

## Changelog
Expand Down
35 changes: 0 additions & 35 deletions src/LockId/LockId.php

This file was deleted.

141 changes: 0 additions & 141 deletions src/Locker/PostgresAdvisoryLocker.php

This file was deleted.

14 changes: 0 additions & 14 deletions src/Locker/PostgresLockModeEnum.php

This file was deleted.

16 changes: 16 additions & 0 deletions src/Postgres/Enum/PostgresLockAccessModeEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Cog\DbLocker\Postgres\Enum;

/**
* PostgresLockAccessModeEnum defines the access mode of advisory lock acquisition.
*
* TODO: Need string values only for tests, should add match to tests instead.
*/
enum PostgresLockAccessModeEnum: string
{
case Exclusive = 'ExclusiveLock';
case Share = 'ShareLock';
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

declare(strict_types=1);

namespace Cog\DbLocker\Locker;
namespace Cog\DbLocker\Postgres\Enum;

/**
* PostgresAdvisoryLockScopeEnum defines the scope of advisory lock acquisition.
* PostgresLockLevelEnum defines the level of advisory lock acquisition.
*
* - Session. Session-level advisory lock (without _XACT_):
* - PG_ADVISORY_LOCK
Expand All @@ -18,7 +18,7 @@
* - PG_TRY_ADVISORY_XACT_LOCK
* - PG_TRY_ADVISORY_XACT_LOCK_SHARED
*/
enum PostgresAdvisoryLockScopeEnum
enum PostgresLockLevelEnum
{
case Session;
case Transaction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

declare(strict_types=1);

namespace Cog\DbLocker\Locker;
namespace Cog\DbLocker\Postgres\Enum;

/**
* PostgresAdvisoryLockTypeEnum defines the type of advisory lock acquisition.
* PostgresLockWaitModeEnum defines the type of advisory lock acquisition.
*
* - NonBlocking. Attempt to acquire the lock without blocking (with _TRY_):
* - PG_TRY_ADVISORY_LOCK
Expand All @@ -18,8 +18,8 @@
* - PG_ADVISORY_XACT_LOCK
* - PG_ADVISORY_XACT_LOCK_SHARED
*/
enum PostgresAdvisoryLockTypeEnum
enum PostgresLockWaitModeEnum
{
case NonBlocking;
case Blocking;
case NonBlocking;
}
70 changes: 70 additions & 0 deletions src/Postgres/LockHandle/SessionLevelLockHandle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

/*
* This file is part of PHP DB Locker.
*
* (c) Anton Komarev <anton@komarev.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Cog\DbLocker\Postgres\LockHandle;

use Cog\DbLocker\Postgres\Enum\PostgresLockAccessModeEnum;
use Cog\DbLocker\Postgres\PostgresAdvisoryLocker;
use Cog\DbLocker\Postgres\PostgresLockKey;
use PDO;

/**
* @internal
*/
final class SessionLevelLockHandle
{
private bool $isReleased = false;

public function __construct(
private readonly PDO $dbConnection,
private readonly PostgresAdvisoryLocker $locker,
public readonly PostgresLockKey $lockId,
public readonly PostgresLockAccessModeEnum $accessMode,
public readonly bool $wasAcquired,
) {}

/**
* Explicitly release the lock if it was acquired and not yet released.
*
* @return bool True if the lock was released, false if it wasn't acquired or already released
*/
public function release(): bool
{
/**
* This code is mimicking the behavior of DB lock release.
*/
if (!$this->wasAcquired || $this->isReleased) {
return false;
}

$wasReleased = $this->locker->releaseSessionLevelLock(
$this->dbConnection,
$this->lockId,
);

if ($wasReleased) {
$this->isReleased = true;
}

return $wasReleased;
}

/**
* Automatically release the lock when the handle is destroyed.
*/
public function __destruct()
{
// TODO: Do we need to
$this->release();
}
}
Loading
Loading