Skip to content

Instantly share code, notes, and snippets.

@rgeraads
Last active August 18, 2023 11:58
Show Gist options
  • Save rgeraads/298c1303b376a8e8cdd81138b604356c to your computer and use it in GitHub Desktop.
Save rgeraads/298c1303b376a8e8cdd81138b604356c to your computer and use it in GitHub Desktop.
Quick implementation of a lock via file
<?php declare(strict_types=1);
final class LockFile
{
private const LOCK_EXTENSION = '.lock';
private readonly string $fileName;
public function __construct(string $fileName, private readonly int $duration)
{
$this->fileName = $fileName . self::LOCK_EXTENSION;
}
public function createLock(): bool
{
if ($this->isLocked()) {
return false;
}
return touch($this->fileName);
}
public function isLocked(): bool
{
if (!is_file($this->fileName)) {
return false;
}
if ($this->isExpired()) {
return false;
}
return true;
}
public function releaseLock(): bool
{
if (is_file($this->fileName)) {
return unlink($this->fileName);
}
return false;
}
private function isExpired(): bool
{
$fileAge = time() - filemtime($this->fileName);
return $fileAge > $this->duration;
}
}
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class LockFileTest extends TestCase
{
/** @test */
public function it_should_create_a_lock_file(): void
{
$lockFile = new LockFile('/tmp/foo', 10);
self::assertTrue($lockFile->createLock());
self::assertFileExists('/tmp/foo.lock');
}
/** @test */
public function it_should_remove_a_lock_file(): void
{
$lockFile = new LockFile('/tmp/foo', 10);
self::assertTrue($lockFile->createLock());
self::assertFileExists('/tmp/foo.lock');
self::assertTrue($lockFile->releaseLock());
self::assertFileDoesNotExist('/tmp/foo.lock');
}
/** @test */
public function it_should_return_false_if_a_lock_file_could_not_be_created(): void
{
$lockFile = new LockFile('/tmp/foo', 10);
self::assertTrue($lockFile->createLock());
self::assertFalse($lockFile->createLock());
}
/** @test */
public function it_should_return_false_if_a_lock_file_could_not_be_removed(): void
{
$lockFile = new LockFile('/tmp/foo', 10);
self::assertFalse($lockFile->releaseLock());
}
/** @test */
public function it_should_show_if_a_lock_file_is_active(): void
{
$lockFile = new LockFile('/tmp/foo', 0);
self::assertFalse($lockFile->isLocked());
self::assertTrue($lockFile->createLock());
self::assertTrue($lockFile->isLocked());
sleep(1);
self::assertFalse($lockFile->isLocked());
}
public function tearDown(): void
{
@unlink('/tmp/foo.lock');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment