suite implémentation cache
This commit is contained in:
parent
ec0c0eef3e
commit
c80d99e829
17
src/file/cache/CacheData.php
vendored
17
src/file/cache/CacheData.php
vendored
@ -12,10 +12,9 @@ class CacheData {
|
|||||||
/** @var callable une fonction permettant de calculer la donnée */
|
/** @var callable une fonction permettant de calculer la donnée */
|
||||||
const COMPUTE = null;
|
const COMPUTE = null;
|
||||||
|
|
||||||
function __construct(?array $params=null) {
|
function __construct(?string $name=null, $compute=null) {
|
||||||
$this->name = $params["name"] ?? static::NAME;
|
$this->name = $name ?? static::NAME ?? bin2hex(random_bytes(8));
|
||||||
$this->name ??= bin2hex(random_bytes(8));
|
$this->compute = func::withn($compute ?? static::COMPUTE);
|
||||||
$this->compute = func::withn($params["compute"] ?? static::COMPUTE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string $name;
|
protected string $name;
|
||||||
@ -27,9 +26,12 @@ class CacheData {
|
|||||||
return $compute !== null? $compute->invoke(): null;
|
return $compute !== null? $compute->invoke(): null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getName() : string {
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
/** obtenir la donnée, en l'itérant au préalable si elle est traversable */
|
/** obtenir la donnée, en l'itérant au préalable si elle est traversable */
|
||||||
function get(?string &$name, $compute=null) {
|
function get($compute=null) {
|
||||||
$name = $this->name;
|
|
||||||
$this->compute ??= func::withn($compute);
|
$this->compute ??= func::withn($compute);
|
||||||
$data = $this->compute();
|
$data = $this->compute();
|
||||||
if ($data instanceof Traversable) {
|
if ($data instanceof Traversable) {
|
||||||
@ -39,8 +41,7 @@ class CacheData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** obtenir un itérateur sur la donnée ou null s'il n'y a pas de données */
|
/** obtenir un itérateur sur la donnée ou null s'il n'y a pas de données */
|
||||||
function all(?string &$name, $compute=null): ?iterable {
|
function all($compute=null): ?iterable {
|
||||||
$name = $this->name;
|
|
||||||
$this->compute ??= func::withn($compute);
|
$this->compute ??= func::withn($compute);
|
||||||
$data = $this->compute();
|
$data = $this->compute();
|
||||||
if ($data !== null && !is_iterable($data)) $data = [$data];
|
if ($data !== null && !is_iterable($data)) $data = [$data];
|
||||||
|
88
src/file/cache/CacheFile.php
vendored
88
src/file/cache/CacheFile.php
vendored
@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\file\cache;
|
namespace nulib\file\cache;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use nulib\file;
|
||||||
use nulib\file\SharedFile;
|
use nulib\file\SharedFile;
|
||||||
use nulib\os\path;
|
use nulib\os\path;
|
||||||
use nulib\php\time\DateTime;
|
use nulib\php\time\DateTime;
|
||||||
@ -23,7 +25,6 @@ class CacheFile extends SharedFile {
|
|||||||
$this->duration = Delay::with($params["duration"] ?? static::DURATION);
|
$this->duration = Delay::with($params["duration"] ?? static::DURATION);
|
||||||
$this->overrideDuration = $params["override_duration"] ?? false;
|
$this->overrideDuration = $params["override_duration"] ?? false;
|
||||||
$this->cacheNull = $params["cache_null"] ?? false;
|
$this->cacheNull = $params["cache_null"] ?? false;
|
||||||
$this->datafiles = [];
|
|
||||||
parent::__construct($file);
|
parent::__construct($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,8 +40,6 @@ class CacheFile extends SharedFile {
|
|||||||
|
|
||||||
protected bool $cacheNull;
|
protected bool $cacheNull;
|
||||||
|
|
||||||
protected array $datafiles;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vérifier si le fichier est valide. s'il est invalide, il faut le recréer.
|
* vérifier si le fichier est valide. s'il est invalide, il faut le recréer.
|
||||||
*
|
*
|
||||||
@ -52,7 +51,7 @@ class CacheFile extends SharedFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** charger les données. le fichier a déjà été verrouillé en lecture */
|
/** charger les données. le fichier a déjà été verrouillé en lecture */
|
||||||
protected function loadData(): ?array {
|
protected function loadMetadata(): ?array {
|
||||||
$this->rewind();
|
$this->rewind();
|
||||||
[
|
[
|
||||||
"start" => $start,
|
"start" => $start,
|
||||||
@ -74,7 +73,7 @@ class CacheFile extends SharedFile {
|
|||||||
if ($this->isValid()) {
|
if ($this->isValid()) {
|
||||||
/** @var Delay $duration */
|
/** @var Delay $duration */
|
||||||
["duration" => $duration,
|
["duration" => $duration,
|
||||||
] = $this->loadData();
|
] = $this->loadMetadata();
|
||||||
$expired = $duration->isElapsed();
|
$expired = $duration->isElapsed();
|
||||||
} else {
|
} else {
|
||||||
$expired = false;
|
$expired = false;
|
||||||
@ -84,7 +83,7 @@ class CacheFile extends SharedFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** sauvegarder les données. le fichier a déjà été verrouillé en écriture */
|
/** sauvegarder les données. le fichier a déjà été verrouillé en écriture */
|
||||||
protected function saveData(?DateTime $start=null, ?Delay $duration=null): void {
|
protected function saveMetadata(?DateTime $start, ?Delay $duration, array $datafiles): void {
|
||||||
$duration ??= $this->duration;
|
$duration ??= $this->duration;
|
||||||
if ($start === null) {
|
if ($start === null) {
|
||||||
$start = new DateTime();
|
$start = new DateTime();
|
||||||
@ -94,15 +93,76 @@ class CacheFile extends SharedFile {
|
|||||||
$this->serialize([
|
$this->serialize([
|
||||||
"start" => $start,
|
"start" => $start,
|
||||||
"duration" => $duration,
|
"duration" => $duration,
|
||||||
"datafiles" => $this->datafiles,
|
"datafiles" => $datafiles,
|
||||||
], false, true);
|
], false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadData(string $datafile) {
|
||||||
|
$datafile = path::join($this->basedir, $datafile);
|
||||||
|
return file::reader($datafile)->unserialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveData(string $datafile, $data): void {
|
||||||
|
$datafile = path::join($this->basedir, $datafile);
|
||||||
|
file::writer($datafile)->serialize($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function unlinkDatafile(string $datafile): void {
|
||||||
|
@unlink(path::join($this->basedir, $datafile));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function unlinkFiles(?array $datafiles): void {
|
||||||
|
if ($datafiles === null && $this->isValid()) {
|
||||||
|
$this->lockRead();
|
||||||
|
try {
|
||||||
|
["datafiles" => $datafiles
|
||||||
|
] = $this->loadMetadata();
|
||||||
|
} finally {
|
||||||
|
$this->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@unlink($this->file);
|
||||||
|
if ($datafiles !== null) {
|
||||||
|
foreach ($datafiles as $datafile) {
|
||||||
|
$this->unlinkDatafile($datafile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** tester si $value peut être mis en cache */
|
/** tester si $value peut être mis en cache */
|
||||||
function shouldCache($value): bool {
|
protected function shouldCache($value): bool {
|
||||||
return $this->cacheNull || $value !== null;
|
return $this->cacheNull || $value !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get(?CacheData $data=null, bool $noCache=false) {
|
||||||
|
$this->lockRead();
|
||||||
|
try {
|
||||||
|
$datafile = $data->getName();
|
||||||
|
$datafile = "{$this->basename}.data.{$datafile}.cache";
|
||||||
|
#XXX mettre à jour datafiles dans metadata
|
||||||
|
if ($this->shouldUpdate($noCache)) {
|
||||||
|
$this->lockWrite();
|
||||||
|
try {
|
||||||
|
$data = $data->get();
|
||||||
|
if ($this->shouldCache($data)) {
|
||||||
|
$this->saveData($datafile, $data);
|
||||||
|
} else {
|
||||||
|
# ne pas garder le fichier s'il ne faut pas mettre en cache
|
||||||
|
$this->unlinkDatafile($datafile);
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->unlinkDatafile($datafile);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$data = $this->loadData($datafile);
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
} finally {
|
||||||
|
$this->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** obtenir les informations sur le fichier */
|
/** obtenir les informations sur le fichier */
|
||||||
function getInfos(): array {
|
function getInfos(): array {
|
||||||
$this->lockRead();
|
$this->lockRead();
|
||||||
@ -118,7 +178,7 @@ class CacheFile extends SharedFile {
|
|||||||
"start" => $start,
|
"start" => $start,
|
||||||
"duration" => $duration,
|
"duration" => $duration,
|
||||||
"datafiles" => $datafiles,
|
"datafiles" => $datafiles,
|
||||||
] = $this->loadData();
|
] = $this->loadMetadata();
|
||||||
return [
|
return [
|
||||||
"valid" => true,
|
"valid" => true,
|
||||||
"size" => $this->getSize(),
|
"size" => $this->getSize(),
|
||||||
@ -148,10 +208,10 @@ class CacheFile extends SharedFile {
|
|||||||
[
|
[
|
||||||
"start" => $start,
|
"start" => $start,
|
||||||
"duration" => $duration,
|
"duration" => $duration,
|
||||||
] = $this->loadData();
|
] = $this->loadMetadata();
|
||||||
if ($action < 0) $duration->subDuration($nduration);
|
if ($action < 0) $duration->subDuration($nduration);
|
||||||
elseif ($action > 0) $duration->addDuration($nduration);
|
elseif ($action > 0) $duration->addDuration($nduration);
|
||||||
$this->saveData($start, $duration);
|
$this->saveMetadata($start, $duration);
|
||||||
} finally {
|
} finally {
|
||||||
$this->unlock();
|
$this->unlock();
|
||||||
}
|
}
|
||||||
@ -163,11 +223,7 @@ class CacheFile extends SharedFile {
|
|||||||
try {
|
try {
|
||||||
if ($force || $this->shouldUpdate()) {
|
if ($force || $this->shouldUpdate()) {
|
||||||
$this->lockWrite();
|
$this->lockWrite();
|
||||||
@unlink($this->file);
|
$this->unlinkFiles();
|
||||||
$basedir = $this->basedir;
|
|
||||||
foreach ($this->datafiles as $datafile) {
|
|
||||||
@unlink(path::join($basedir, $datafile));
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user