-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,8 +21,12 @@ public function __construct(array $options = []) | |
parent::__construct($options); | ||
|
||
$this->options = array_merge([ | ||
'global' => option('bnomei.nitro.global'), | ||
'atomic' => option('bnomei.nitro.atomic'), | ||
'sleep' => option('bnomei.nitro.sleep'), | ||
'auto-clean-cache' => option('bnomei.nitro.auto-clean-cache'), | ||
'json-encode-flags' => option('bnomei.nitro.json-encode-flags'), | ||
'cacheDir' => realpath(__DIR__.'/../').'/cache', // must be here as well for when used without nitro like as uuid cache | ||
'max-dirty-cache' => intval(option('bnomei.nitro.max-dirty-cache')), // @phpstan-ignore-line | ||
'debug' => option('debug'), | ||
], $options); | ||
|
@@ -36,11 +40,13 @@ public function __construct(array $options = []) | |
if ($this->options['auto-clean-cache']) { | ||
$this->clean(); | ||
} | ||
|
||
$this->atomic(); | ||
} | ||
|
||
public function __destruct() | ||
{ | ||
$this->write(); | ||
$this->write(lock: false); | ||
} | ||
|
||
public function key(string|array $key): string | ||
|
@@ -134,13 +140,15 @@ public function remove(string|array $key): bool | |
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function flush(): bool | ||
public function flush(bool $write = true): bool | ||
{ | ||
if (count($this->data) === 0) { | ||
$this->isDirty++; | ||
} | ||
$this->data = []; | ||
$this->write(); | ||
if ($write) { | ||
$this->write(); | ||
} | ||
|
||
return true; | ||
} | ||
|
@@ -155,19 +163,34 @@ private function clean(): void | |
protected function file(?string $key = null): string | ||
{ | ||
/** @var FileCache $cache */ | ||
$cache = kirby()->cache('bnomei.nitro.sfc'); | ||
if ($this->options['global']) { | ||
Check failure on line 166 in classes/Nitro/SingleFileCache.php GitHub Actions / phpstan
Check failure on line 166 in classes/Nitro/SingleFileCache.php GitHub Actions / phpstan
|
||
$cache = $this->options['cacheDir']; | ||
} else { | ||
$cache = kirby()->cache('bnomei.nitro.sfc')->root(); | ||
Check failure on line 169 in classes/Nitro/SingleFileCache.php GitHub Actions / phpstan
|
||
} | ||
|
||
return $cache->root().'/single-file-cache.json'; | ||
return $cache.'/single-file-cache.json'; | ||
} | ||
|
||
public function write(): bool | ||
public function write(bool $lock = true): bool | ||
{ | ||
$this->unlock(); | ||
|
||
if ($this->isDirty === 0) { | ||
if ($lock) { | ||
$this->unlock(); | ||
} | ||
|
||
return false; | ||
} | ||
$this->isDirty = 0; | ||
|
||
return F::write($this->file(), json_encode($this->data, $this->options['json-encode-flags'])); | ||
$success = F::write($this->file(), json_encode($this->data, $this->options['json-encode-flags'])); | ||
if ($lock) { | ||
$this->lock(); | ||
} | ||
|
||
return $success; | ||
} | ||
|
||
private static function isCallable(mixed $value): bool | ||
|
@@ -203,4 +226,58 @@ public function count(): int | |
{ | ||
return count($this->data); | ||
} | ||
|
||
private function isLocked() | ||
Check failure on line 230 in classes/Nitro/SingleFileCache.php GitHub Actions / phpstan
|
||
{ | ||
if (! $this->options['atomic']) { | ||
return false; | ||
} | ||
|
||
return F::exists($this->file().'.lock'); | ||
} | ||
|
||
public function lock(): bool | ||
{ | ||
if (! $this->options['atomic']) { | ||
return false; | ||
} | ||
|
||
return F::write($this->file().'.lock', date('c')); | ||
} | ||
|
||
public function unlock(): bool | ||
{ | ||
if (! $this->options['atomic']) { | ||
return false; | ||
} | ||
|
||
return F::remove($this->file().'.lock'); | ||
} | ||
|
||
private function atomic(): bool | ||
{ | ||
if (! $this->options['atomic']) { | ||
return false; | ||
} | ||
|
||
// this is what makes it atomic | ||
// get php max execution time | ||
$maxExecutionTime = (int) ini_get('max_execution_time'); | ||
if ($maxExecutionTime === 0) { | ||
$maxExecutionTime = 30; // default, might happen in xdebug mode | ||
} | ||
$maxCycles = $maxExecutionTime * 1000 * 1000; // seconds to microseconds | ||
$sleep = $this->options['sleep']; | ||
|
||
while ($this->isLocked()) { | ||
$maxCycles -= $sleep; | ||
if ($maxCycles <= 0) { | ||
throw new \Exception('Something is very wrong. SingleFileCache could not get lock within '.$maxExecutionTime.' seconds! Are using xdebug breakpoints or maybe you need to forcibly `kirby nitro:unlock`?'); | ||
} | ||
|
||
usleep($sleep); | ||
} | ||
|
||
return $this->lock(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
namespace Bnomei; | ||
|
||
use Kirby\Cache\FileCache; | ||
|
||
class NitroCache extends FileCache | ||
{ | ||
// make a magic call to all methods of the cache | ||
public function __call($method, $args) | ||
Check failure on line 10 in classes/NitroCache.php GitHub Actions / phpstan
Check failure on line 10 in classes/NitroCache.php GitHub Actions / phpstan
Check failure on line 10 in classes/NitroCache.php GitHub Actions / phpstan
Check failure on line 10 in classes/NitroCache.php GitHub Actions / phpstan
Check failure on line 10 in classes/NitroCache.php GitHub Actions / phpstan
|
||
{ | ||
return call_user_func_array([Nitro::singleton()->cache(), $method], $args); | ||
Check failure on line 12 in classes/NitroCache.php GitHub Actions / phpstan
|
||
} | ||
} |