Refactor lock.php

This commit is contained in:
Zankaria 2024-02-16 14:47:20 +01:00
parent 00b05099f3
commit 760431606d
2 changed files with 74 additions and 33 deletions

View File

@ -1,43 +1,84 @@
<?php <?php
class Lock {
function __construct($key) {
global $config;
if ($config['lock']['enabled'] == 'fs') {
$key = str_replace('/', '::', $key);
$key = str_replace("\0", '', $key);
$this->f = fopen("tmp/locks/$key", "w"); class Locks {
private static function filesystem(string $key): Lock|false {
$key = str_replace('/', '::', $key);
$key = str_replace("\0", '', $key);
$fd = fopen("tmp/locks/$key", "w");
if ($fd === false) {
return false;
} }
return new class($fd) implements Lock {
// Resources have no type in php.
private mixed $f;
function __construct($fd) {
$this->f = $fd;
}
public function get(bool $nonblock = false): Lock|false {
$wouldblock = false;
flock($this->f, LOCK_SH | ($nonblock ? LOCK_NB : 0), $wouldblock);
if ($nonblock && $wouldblock) {
return false;
}
return $this;
}
public function get_ex(bool $nonblock = false): Lock|false {
$wouldblock = false;
flock($this->f, LOCK_EX | ($nonblock ? LOCK_NB : 0), $wouldblock);
if ($nonblock && $wouldblock) {
return false;
}
return $this;
}
public function free(): Lock {
flock($this->f, LOCK_UN);
return $this;
}
};
} }
// Get a shared lock /**
function get($nonblock = false) { * No-op. Can be used for mocking.
global $config; */
if ($config['lock']['enabled'] == 'fs') { public static function none(): Lock|false {
$wouldblock = false; return new class() implements Lock {
flock($this->f, LOCK_SH | ($nonblock ? LOCK_NB : 0), $wouldblock); public function get(bool $nonblock = false): Lock|false {
if ($nonblock && $wouldblock) return false; return $this;
} }
return $this;
public function get_ex(bool $nonblock = false): Lock|false {
return $this;
}
public function free(): Lock {
return $this;
}
};
} }
// Get an exclusive lock public static function get_lock(array $config, string $key): Lock|false {
function get_ex($nonblock = false) {
global $config;
if ($config['lock']['enabled'] == 'fs') { if ($config['lock']['enabled'] == 'fs') {
$wouldblock = false; return self::filesystem($key);
flock($this->f, LOCK_EX | ($nonblock ? LOCK_NB : 0), $wouldblock); } else {
if ($nonblock && $wouldblock) return false; return self::none();
} }
return $this;
}
// Free a lock
function free() {
global $config;
if ($config['lock']['enabled'] == 'fs') {
flock($this->f, LOCK_UN);
}
return $this;
} }
} }
interface Lock {
// Get a shared lock
public function get(bool $nonblock = false): Lock|false;
// Get an exclusive lock
public function get_ex(bool $nonblock = false): Lock|false;
// Free a lock
public function free(): Lock;
}

View File

@ -3,7 +3,7 @@
class Queue { class Queue {
function __construct($key) { global $config; function __construct($key) { global $config;
if ($config['queue']['enabled'] == 'fs') { if ($config['queue']['enabled'] == 'fs') {
$this->lock = new Lock($key); $this->lock = Locks::get_lock($config, $key);
$key = str_replace('/', '::', $key); $key = str_replace('/', '::', $key);
$key = str_replace("\0", '', $key); $key = str_replace("\0", '', $key);
$this->key = "tmp/queue/$key/"; $this->key = "tmp/queue/$key/";