Skip to content

Commit

Permalink
Adds the ability to use custom id for lock acquiring
Browse files Browse the repository at this point in the history
  • Loading branch information
butschster committed Mar 16, 2023
1 parent a5d3c19 commit b02d4e7
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 17 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ $id = $lock->lock('pdf:create', ttl: new \DateInterval('PT10S'));
$id = $lock->lock('pdf:create', wait: 5);
// or
$id = $lock->lock('pdf:create', wait: new \DateInterval('PT5S'));

// Acquire lock with id - 14e1b600-9e97-11d8-9f32-f2801f1b9fd1
$id = $lock->lock('pdf:create', id: '14e1b600-9e97-11d8-9f32-f2801f1b9fd1');
```

### Acquire read lock
Expand All @@ -72,6 +75,9 @@ $id = $lock->lockRead('pdf:create', ttl: new \DateInterval('PT10S'));
$id = $lock->lockRead('pdf:create', wait: 5);
// or
$id = $lock->lockRead('pdf:create', wait: new \DateInterval('PT5S'));

// Acquire lock with id - 14e1b600-9e97-11d8-9f32-f2801f1b9fd1
$id = $lock->lockRead('pdf:create', id: '14e1b600-9e97-11d8-9f32-f2801f1b9fd1');
```

### Release lock
Expand Down
8 changes: 6 additions & 2 deletions src/Lock.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,20 @@ public function __construct(
* other processes that attempt to lock the same resource will be blocked until the lock is released.
*
* @param non-empty-string $resource The name of the resource to be locked.
* @param non-empty-string|null $id The lock ID. If not specified, a random UUID will be generated.
* @param int|DateInterval $ttl The time-to-live of the lock, in seconds. Defaults to 0 (forever).
* @param int|DateInterval $waitTTL How long to wait to acquire lock until returning false.
* @return false|non-empty-string Returns lock ID if the lock was acquired successfully, false otherwise.
*/
public function lock(
string $resource,
?string $id = null,
int|DateInterval $ttl = 0,
int|DateInterval $waitTTL = 0,
): false|string {
$request = new Request();
$request->setResource($resource);
$request->setId($id = $this->identityGenerator->generate());
$request->setId($id ??= $this->identityGenerator->generate());
$request->setTtl($this->convertTimeToSeconds($ttl));
$request->setWait($this->convertTimeToSeconds($waitTTL));

Expand All @@ -57,18 +59,20 @@ public function lock(
* will be blocked until all shared locks are released.
*
* @param non-empty-string $resource The name of the resource to be locked.
* @param non-empty-string|null $id The lock ID. If not specified, a random UUID will be generated.
* @param int|DateInterval $ttl The time-to-live of the lock, in seconds. Defaults to 0 (forever).
* @param int|DateInterval $waitTTL How long to wait to acquire lock until returning false.
* @return false|non-empty-string Returns lock ID if the lock was acquired successfully, false otherwise.
*/
public function lockRead(
string $resource,
?string $id = null,
int|DateInterval $ttl = 0,
int|DateInterval $waitTTL = 0,
): false|string {
$request = new Request();
$request->setResource($resource);
$request->setId($id = $this->identityGenerator->generate());
$request->setId($id ??= $this->identityGenerator->generate());
$request->setTtl($this->convertTimeToSeconds($ttl));
$request->setWait($this->convertTimeToSeconds($waitTTL));

Expand Down
45 changes: 30 additions & 15 deletions tests/src/LockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,28 +45,33 @@ public function testLock(
int|\DateInterval|\DateTimeInterface $wait,
int $expectedWaitSec,
bool $expectedResult = true,
?string $id = null,
): void {
$this->idGenerator->shouldReceive('generate')->once()->andReturn('some-id');
if ($id === null) {
$this->idGenerator->shouldReceive('generate')->once()->andReturn('some-id');
}

$this->rpc->shouldReceive('call')
->withArgs(function (string $method, Request $request, string $response) use (
$expectedTtlSec,
$expectedWaitSec,
$callMethod
$callMethod,
$id
): bool {
return $method === $callMethod
&& $request->getResource() === 'resource'
&& $request->getId() === 'some-id'
&& $request->getId() === ($id === null ? 'some-id' : $id)
&& $request->getTtl() === $expectedTtlSec
&& $request->getWait() === $expectedWaitSec
&& $response === Response::class;
&& $request->getWait() === $expectedWaitSec
&& $response === Response::class;
})
->andReturn(new Response(['ok' => $expectedResult]));

$result = $this->lock->$method(resource: 'resource', id: $id, ttl: $ttl, waitTTL: $wait);
if ($expectedResult) {
$this->assertSame('some-id', $this->lock->$method('resource', $ttl, $wait));
$this->assertSame(($id === null ? 'some-id' : $id), $result);
} else {
$this->assertFalse($this->lock->$method('resource', $ttl, $wait));
$this->assertFalse($result);
}
}

Expand Down Expand Up @@ -131,7 +136,7 @@ public function testUpdateTTL($ttl, int $expectedTtl, bool $result): void
{
$this->rpc->shouldReceive('call')
->once()
->withArgs(function (string $method, Request $request, string $response) use($expectedTtl): bool {
->withArgs(function (string $method, Request $request, string $response) use ($expectedTtl): bool {
return $method === 'lock.UpdateTTL'
&& $request->getResource() === 'resource'
&& $request->getId() === 'some-id'
Expand Down Expand Up @@ -165,13 +170,23 @@ public function lockTypeDataProvider(): \Generator
{
foreach ($this->lockDataProvider() as $name => $data) {
foreach ([true, false] as $result) {
yield 'lock: ' . $name . ' | ' . \var_export($result, true) => ['lock', 'lock.Lock', ...$data, $result];
yield 'read-lock: ' . $name . ' | ' . \var_export($result, true) => [
'lockRead',
'lock.LockRead',
...$data,
$result,
];
foreach (['id1', null] as $id) {
yield 'lock: ' . $name . ' | ' .$id. ' | ' . \var_export($result, true) => [
'lock',
'lock.Lock',
...$data,
$result,
$id
];

yield 'read-lock: ' . $name . ' | ' .$id. ' | ' . \var_export($result, true) => [
'lockRead',
'lock.LockRead',
...$data,
$result,
$id
];
}
}
}
}
Expand Down

0 comments on commit b02d4e7

Please sign in to comment.