From 3a6fd674710dfbccb985c54b788aa888110c3eb6 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 12 May 2025 15:37:43 +0400 Subject: [PATCH 1/8] Init changelog & version 0.5.1p82 --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 88437f3..6140834 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,5 @@ +## Release 0.5.1p82 du 12/05/2025-15:37 + ## Release 0.5.1p74 du 12/05/2025-15:34 * `39b2fa5` générifier la méthode d'authentification From 25cf1c5282bbdc286155853e6d1d4fc1807668cc Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 12 May 2025 15:41:11 +0400 Subject: [PATCH 2/8] modifs.mineures sans commentaires --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b6942e..eaa8bc6 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,11 @@ pci "maj projet" prel -C -commit="$(git log --grep="Init changelog . version ${version}p82" --format=%H)" +commit="$(git log --grep="Init changelog . version ${version}p82" --format=%H)" && +echo "commit=$commit" + git checkout dev74 + git cherry-pick "$commit" pp -a ~~~ From ba0ad15d78d8d7b6f18f82176c5ceaf8eac4b27f Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 21 May 2025 20:42:14 +0400 Subject: [PATCH 3/8] renommer *storage.php --- composer.json | 4 ++-- nur_bin/{mysql-storage.php => storage.mysql.php} | 0 nur_bin/{sqlite-storage.php => storage.sqlite.php} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename nur_bin/{mysql-storage.php => storage.mysql.php} (100%) rename nur_bin/{sqlite-storage.php => storage.sqlite.php} (100%) diff --git a/composer.json b/composer.json index 1ba08c0..1daac79 100644 --- a/composer.json +++ b/composer.json @@ -90,8 +90,8 @@ "nur_bin/ldap-delete.php", "nur_bin/ldap-get-infos.php", "nur_bin/ldap-search.php", - "nur_bin/sqlite-storage.php", - "nur_bin/mysql-storage.php" + "nur_bin/storage.sqlite.php", + "nur_bin/storage.mysql.php" ], "scripts": { "uc": "@php sbin/update_classes.php" diff --git a/nur_bin/mysql-storage.php b/nur_bin/storage.mysql.php similarity index 100% rename from nur_bin/mysql-storage.php rename to nur_bin/storage.mysql.php diff --git a/nur_bin/sqlite-storage.php b/nur_bin/storage.sqlite.php similarity index 100% rename from nur_bin/sqlite-storage.php rename to nur_bin/storage.sqlite.php From 4c91327bacf8c3b307de535a92ac509fd7625781 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 23 May 2025 05:02:31 +0400 Subject: [PATCH 4/8] =?UTF-8?q?db/cache=20doit=20encore=20=C3=AAtre=20trav?= =?UTF-8?q?aill=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/db/cache/CacheChannel.php | 116 ++++++++++++++++++++++++++++++++++ src/db/cache/RowsChannel.php | 51 +++++++++++++++ src/db/cache/cache.php | 37 +++++++++++ 3 files changed, 204 insertions(+) create mode 100644 src/db/cache/CacheChannel.php create mode 100644 src/db/cache/RowsChannel.php create mode 100644 src/db/cache/cache.php diff --git a/src/db/cache/CacheChannel.php b/src/db/cache/CacheChannel.php new file mode 100644 index 0000000..b1f8619 --- /dev/null +++ b/src/db/cache/CacheChannel.php @@ -0,0 +1,116 @@ + "varchar(64) not null", + "id" => "varchar(64) not null", + "date_start" => "datetime", + "duration_" => "text", + "primary key (group_id, id)", + ]; + + static function get_cache_ids($id): array { + if (is_array($id)) { + $keys = array_keys($id); + if (array_key_exists("group_id", $id)) $groupIdKey = "group_id"; + else $groupIdKey = $keys[1] ?? null; + $groupId = $id[$groupIdKey] ?? ""; + if (array_key_exists("id", $id)) $idKey = "id"; + else $idKey = $keys[0] ?? null; + $id = $id[$idKey] ?? ""; + } else { + $groupId = ""; + } + if (preg_match('/^(.*\\\\)?([^\\\\]+)$/', $groupId, $ms)) { + # si le groupe est une classe, faire un hash du package pour limiter la + # longueur du groupe + [$package, $groupId] = [$ms[1], $ms[2]]; + $package = substr(md5($package), 0, 4); + $groupId = "${groupId}_$package"; + } + return ["group_id" => $groupId, "id" => $id]; + } + + function __construct(?string $duration=null, ?string $name=null) { + parent::__construct($name); + $this->duration = $duration ?? static::DURATION; + $this->includes = static::INCLUDES; + $this->excludes = static::EXCLUDES; + } + + protected string $duration; + + protected ?array $includes; + + protected ?array $excludes; + + function getItemValues($item): ?array { + return cl::merge(self::get_cache_ids($item), [ + "item" => null, + ]); + } + + function onCreate($item, array $values, ?array $alwaysNull, ?string $duration=null): ?array { + $now = new DateTime(); + $duration ??= $this->duration; + return [ + "date_start" => $now, + "duration" => new Delay($duration, $now), + ]; + } + + function onUpdate($item, array $values, array $pvalues, ?string $duration=null): ?array { + $now = new DateTime(); + $duration ??= $this->duration; + return [ + "date_start" => $now, + "duration" => new Delay($duration, $now), + ]; + } + + function shouldUpdate($id, bool $noCache=false): bool { + if ($noCache) return true; + + $cacheIds = self::get_cache_ids($id); + $groupId = $cacheIds["group_id"]; + if ($groupId) { + $includes = $this->includes; + $shouldInclude = $includes !== null && in_array($groupId, $includes); + $excludes = $this->excludes; + $shouldExclude = $excludes !== null && in_array($groupId, $excludes); + if (!$shouldInclude || $shouldExclude) return true; + } + + $found = false; + $expired = false; + $this->each($cacheIds, + function($item, $values) use (&$found, &$expired) { + $found = true; + $expired = $values["duration"]->isElapsed(); + }); + return !$found || $expired; + } + + function setCached($id, ?string $duration=null): void { + $cacheIds = self::get_cache_ids($id); + $this->charge($cacheIds, null, [$duration]); + } + + function resetCached($id) { + $cacheIds = self::get_cache_ids($id); + $this->delete($cacheIds); + } +} diff --git a/src/db/cache/RowsChannel.php b/src/db/cache/RowsChannel.php new file mode 100644 index 0000000..a3f7055 --- /dev/null +++ b/src/db/cache/RowsChannel.php @@ -0,0 +1,51 @@ + "varchar(128) primary key not null", + "all_values" => "mediumtext", + ]; + + function __construct($id, callable $builder, ?string $duration=null) { + $this->cacheIds = $cacheIds = CacheChannel::get_cache_ids($id); + $this->builder = Closure::fromCallable($builder); + $this->duration = $duration; + $name = "{$cacheIds["group_id"]}-{$cacheIds["id"]}"; + parent::__construct($name); + } + + protected array $cacheIds; + + protected Closure $builder; + + protected ?string $duration = null; + + function getItemValues($item): ?array { + $key = array_keys($item)[0]; + $row = $item[$key]; + return [ + "key" => $key, + "item" => $row, + "all_values" => implode(" ", cl::filter_n(cl::with($row))), + ]; + } + + function getIterator(): Traversable { + $cm = cache::get(); + if ($cm->shouldUpdate($this->cacheIds)) { + $this->capacitor->reset(); + foreach (($this->builder)() as $key => $row) { + $this->charge([$key => $row]); + } + $cm->setCached($this->cacheIds, $this->duration); + } + return $this->discharge(false); + } +} diff --git a/src/db/cache/cache.php b/src/db/cache/cache.php new file mode 100644 index 0000000..401fb19 --- /dev/null +++ b/src/db/cache/cache.php @@ -0,0 +1,37 @@ + Date: Fri, 23 May 2025 06:48:57 +0400 Subject: [PATCH 5/8] =?UTF-8?q?d=C3=A9but=20impl=C3=A9mentation=20cache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/nucache.php | 7 ++ src/file/cache/CacheData.php | 49 ++++++++++ src/file/cache/CacheFile.php | 178 +++++++++++++++++++++++++++++++++++ src/tools/NucacheApp.php | 119 +++++++++++++++++++++++ 4 files changed, 353 insertions(+) create mode 100755 bin/nucache.php create mode 100644 src/file/cache/CacheData.php create mode 100644 src/file/cache/CacheFile.php create mode 100644 src/tools/NucacheApp.php diff --git a/bin/nucache.php b/bin/nucache.php new file mode 100755 index 0000000..290263c --- /dev/null +++ b/bin/nucache.php @@ -0,0 +1,7 @@ +#!/usr/bin/php +name = $params["name"] ?? static::NAME; + $this->name ??= bin2hex(random_bytes(8)); + $this->compute = func::withn($params["compute"] ?? static::COMPUTE); + } + + protected string $name; + + protected ?func $compute; + + protected function compute() { + $compute = $this->compute; + return $compute !== null? $compute->invoke(): null; + } + + /** obtenir la donnée, en l'itérant au préalable si elle est traversable */ + function get(?string &$name, $compute=null) { + $name = $this->name; + $this->compute ??= func::withn($compute); + $data = $this->compute(); + if ($data instanceof Traversable) { + $data = cl::all($data); + } + return $data; + } + + /** 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 { + $name = $this->name; + $this->compute ??= func::withn($compute); + $data = $this->compute(); + if ($data !== null && !is_iterable($data)) $data = [$data]; + return $data; + } +} diff --git a/src/file/cache/CacheFile.php b/src/file/cache/CacheFile.php new file mode 100644 index 0000000..07b30cc --- /dev/null +++ b/src/file/cache/CacheFile.php @@ -0,0 +1,178 @@ +basedir = path::dirname($file); + $basename = path::filename($file); + $this->basename = str::without_suffix(path::ext($basename), $basename); + $this->duration = Delay::with($params["duration"] ?? static::DURATION); + $this->overrideDuration = $params["override_duration"] ?? false; + $this->cacheNull = $params["cache_null"] ?? false; + $this->datafiles = []; + parent::__construct($file); + } + + /** @var string répertoire de base des fichiers de cache */ + protected string $basedir; + + /** @var string nom de base des fichiers de cache */ + protected string $basename; + + protected Delay $duration; + + protected bool $overrideDuration; + + protected bool $cacheNull; + + protected array $datafiles; + + /** + * vérifier si le fichier est valide. s'il est invalide, il faut le recréer. + * + * on assume que le fichier existe, vu qu'il a été ouvert en c+b + */ + protected function isValid(): bool { + # considèrer que le fichier est invalide s'il est de taille nulle + return $this->getSize() > 0; + } + + /** charger les données. le fichier a déjà été verrouillé en lecture */ + protected function loadData(): ?array { + $this->rewind(); + [ + "start" => $start, + "duration" => $duration, + "datafiles" => $datafiles, + ] = $this->unserialize(null, false, true); + if ($this->overrideDuration) { + $duration = Delay::with($this->duration, $start); + } + return [ + "start" => $start, + "duration" => $duration, + "datafiles" => $datafiles, + ]; + } + + /** tester s'il faut mettre les données à jour. le fichier a déjà été verrouillé en lecture */ + protected function shouldUpdate(bool $noCache=false): bool { + if ($this->isValid()) { + /** @var Delay $duration */ + ["duration" => $duration, + ] = $this->loadData(); + $expired = $duration->isElapsed(); + } else { + $expired = false; + $noCache = true; + } + return $noCache || $expired; + } + + /** sauvegarder les données. le fichier a déjà été verrouillé en écriture */ + protected function saveData(?DateTime $start=null, ?Delay $duration=null): void { + $duration ??= $this->duration; + if ($start === null) { + $start = new DateTime(); + $duration = Delay::with($duration, $start); + } + $this->ftruncate(); + $this->serialize([ + "start" => $start, + "duration" => $duration, + "datafiles" => $this->datafiles, + ], false, true); + } + + /** tester si $value peut être mis en cache */ + function shouldCache($value): bool { + return $this->cacheNull || $value !== null; + } + + /** obtenir les informations sur le fichier */ + function getInfos(): array { + $this->lockRead(); + try { + if (!$this->isValid()) { + return ["valid" => false]; + } + /** + * @var DateTime $start + * @var Delay $duration + */ + [ + "start" => $start, + "duration" => $duration, + "datafiles" => $datafiles, + ] = $this->loadData(); + return [ + "valid" => true, + "size" => $this->getSize(), + "start" => $start, + "duration" => strval($duration), + "date_start" => $start->format(), + "date_end" => $duration->getDest()->format(), + "datafiles" => $datafiles, + ]; + } finally { + $this->unlock(); + } + } + + const UPDATE_SUB = -1, UPDATE_SET = 0, UPDATE_ADD = 1; + + /** mettre à jour la durée de validité du fichier */ + function updateDuration($nduration, int $action=1): void { + $this->lockRead(); + try { + if (!$this->isValid()) return; + $this->lockWrite(); + /** + * @var DateTime $tstart + * @var Delay $duration + */ + [ + "start" => $start, + "duration" => $duration, + ] = $this->loadData(); + if ($action < 0) $duration->subDuration($nduration); + elseif ($action > 0) $duration->addDuration($nduration); + $this->saveData($start, $duration); + } finally { + $this->unlock(); + } + } + + /** supprimer les fichiers s'ils ont expiré */ + function deleteExpired(bool $force=false): bool { + $this->lockRead(); + try { + if ($force || $this->shouldUpdate()) { + $this->lockWrite(); + @unlink($this->file); + $basedir = $this->basedir; + foreach ($this->datafiles as $datafile) { + @unlink(path::join($basedir, $datafile)); + } + return true; + } + } finally { + $this->unlock(); + } + return false; + } +} diff --git a/src/tools/NucacheApp.php b/src/tools/NucacheApp.php new file mode 100644 index 0000000..9fc01d4 --- /dev/null +++ b/src/tools/NucacheApp.php @@ -0,0 +1,119 @@ + parent::ARGS, + "purpose" => "gestion de fichiers cache", + ["-r", "--read", "name" => "action", "value" => self::ACTION_READ, + "help" => "Afficher le contenu d'un fichier cache", + ], + ["-i", "--infos", "name" => "action", "value" => self::ACTION_INFOS, + "help" => "Afficher des informations sur le fichier cache", + ], + ["-k", "--clean", "name" => "action", "value" => self::ACTION_CLEAN, + "help" => "Supprimer le fichier cache s'il a expiré", + ], + ["-a", "--add-duration", "args" => 1, + "action" => [null, "->setActionUpdate", self::ACTION_UPDATE_ADD], + "help" => "Ajouter le nombre de secondes spécifié à la durée du cache", + ], + ["-b", "--sub-duration", "args" => 1, + "action" => [null, "->setActionUpdate", self::ACTION_UPDATE_SUB], + "help" => "Enlever le nombre de secondes spécifié à la durée du cache", + ], + ["-s", "--set-duration", "args" => 1, + "action" => [null, "->setActionUpdate", self::ACTION_UPDATE_SET], + "help" => "Mettre à jour la durée du cache à la valeur spécifiée", + ], + ]; + + protected $action = self::ACTION_READ; + + protected $updateAction, $updateDuration; + + protected $args; + + function setActionUpdate(int $action, $updateDuration): void { + $this->action = self::ACTION_UPDATE; + switch ($action) { + case self::ACTION_UPDATE_SUB: $this->updateAction = CacheFile::UPDATE_SUB; break; + case self::ACTION_UPDATE_SET: $this->updateAction = CacheFile::UPDATE_SET; break; + case self::ACTION_UPDATE_ADD: $this->updateAction = CacheFile::UPDATE_ADD; break; + } + $this->updateDuration = $updateDuration; + } + + protected function findCaches(string $dir, ?array &$files): void { + foreach (glob("$dir/*") as $file) { + if (is_dir($file)) { + $this->findCaches($file, $files); + } elseif (is_file($file) && fnmatch("*.cache", $file)) { + $files[] = $file; + } + } + } + + function main() { + $files = []; + foreach ($this->args as $arg) { + if (is_dir($arg)) { + $this->findCaches($arg, $files); + } elseif (is_file($arg)) { + $files[] = $arg; + } else { + msg::warning("$arg: fichier invalide ou introuvable"); + } + } + $showSection = count($files) > 1; + foreach ($files as $file) { + switch ($this->action) { + case self::ACTION_READ: + if ($showSection) msg::section($file); + $cache = new CacheFile($file, [ + "duration" => "INF", + "override_duration" => true, + ]); + //yaml::dump($cache->get()); + break; + case self::ACTION_INFOS: + if ($showSection) msg::section($file); + $cache = new CacheFile($file); + yaml::dump($cache->getInfos()); + break; + case self::ACTION_CLEAN: + msg::action(path::ppath($file)); + $cache = new CacheFile($file); + try { + if ($cache->deleteExpired()) msg::asuccess("fichier supprimé"); + else msg::astep("fichier non expiré"); + } catch (Exception $e) { + msg::afailure($e); + } + break; + case self::ACTION_UPDATE: + msg::action(path::ppath($file)); + $cache = new CacheFile($file); + try { + $cache->updateDuration($this->updateDuration, $this->updateAction); + msg::asuccess("fichier mis à jour"); + } catch (Exception $e) { + msg::afailure($e); + } + break; + default: + self::die("$this->action: action non implémentée"); + } + } + } +} From c80d99e82994783ae4307bac372b7f7bbd411911 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 23 May 2025 07:16:27 +0400 Subject: [PATCH 6/8] =?UTF-8?q?suite=20impl=C3=A9mentation=20cache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/file/cache/CacheData.php | 17 +++---- src/file/cache/CacheFile.php | 88 +++++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 24 deletions(-) diff --git a/src/file/cache/CacheData.php b/src/file/cache/CacheData.php index ec96a14..a680f9e 100644 --- a/src/file/cache/CacheData.php +++ b/src/file/cache/CacheData.php @@ -12,10 +12,9 @@ class CacheData { /** @var callable une fonction permettant de calculer la donnée */ const COMPUTE = null; - function __construct(?array $params=null) { - $this->name = $params["name"] ?? static::NAME; - $this->name ??= bin2hex(random_bytes(8)); - $this->compute = func::withn($params["compute"] ?? static::COMPUTE); + function __construct(?string $name=null, $compute=null) { + $this->name = $name ?? static::NAME ?? bin2hex(random_bytes(8)); + $this->compute = func::withn($compute ?? static::COMPUTE); } protected string $name; @@ -27,9 +26,12 @@ class CacheData { 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 */ - function get(?string &$name, $compute=null) { - $name = $this->name; + function get($compute=null) { $this->compute ??= func::withn($compute); $data = $this->compute(); 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 */ - function all(?string &$name, $compute=null): ?iterable { - $name = $this->name; + function all($compute=null): ?iterable { $this->compute ??= func::withn($compute); $data = $this->compute(); if ($data !== null && !is_iterable($data)) $data = [$data]; diff --git a/src/file/cache/CacheFile.php b/src/file/cache/CacheFile.php index 07b30cc..0c9e810 100644 --- a/src/file/cache/CacheFile.php +++ b/src/file/cache/CacheFile.php @@ -1,6 +1,8 @@ duration = Delay::with($params["duration"] ?? static::DURATION); $this->overrideDuration = $params["override_duration"] ?? false; $this->cacheNull = $params["cache_null"] ?? false; - $this->datafiles = []; parent::__construct($file); } @@ -39,8 +40,6 @@ class CacheFile extends SharedFile { protected bool $cacheNull; - protected array $datafiles; - /** * 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 */ - protected function loadData(): ?array { + protected function loadMetadata(): ?array { $this->rewind(); [ "start" => $start, @@ -74,7 +73,7 @@ class CacheFile extends SharedFile { if ($this->isValid()) { /** @var Delay $duration */ ["duration" => $duration, - ] = $this->loadData(); + ] = $this->loadMetadata(); $expired = $duration->isElapsed(); } else { $expired = false; @@ -84,7 +83,7 @@ class CacheFile extends SharedFile { } /** 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; if ($start === null) { $start = new DateTime(); @@ -94,15 +93,76 @@ class CacheFile extends SharedFile { $this->serialize([ "start" => $start, "duration" => $duration, - "datafiles" => $this->datafiles, + "datafiles" => $datafiles, ], 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 */ - function shouldCache($value): bool { + protected function shouldCache($value): bool { 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 */ function getInfos(): array { $this->lockRead(); @@ -118,7 +178,7 @@ class CacheFile extends SharedFile { "start" => $start, "duration" => $duration, "datafiles" => $datafiles, - ] = $this->loadData(); + ] = $this->loadMetadata(); return [ "valid" => true, "size" => $this->getSize(), @@ -148,10 +208,10 @@ class CacheFile extends SharedFile { [ "start" => $start, "duration" => $duration, - ] = $this->loadData(); + ] = $this->loadMetadata(); if ($action < 0) $duration->subDuration($nduration); elseif ($action > 0) $duration->addDuration($nduration); - $this->saveData($start, $duration); + $this->saveMetadata($start, $duration); } finally { $this->unlock(); } @@ -163,11 +223,7 @@ class CacheFile extends SharedFile { try { if ($force || $this->shouldUpdate()) { $this->lockWrite(); - @unlink($this->file); - $basedir = $this->basedir; - foreach ($this->datafiles as $datafile) { - @unlink(path::join($basedir, $datafile)); - } + $this->unlinkFiles(); return true; } } finally { From 3ea51e70b453c1e4e112b3255526efad10c9bad9 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 23 May 2025 16:52:26 +0400 Subject: [PATCH 7/8] gestion des fichiers de cache --- src/file/cache/CacheData.php | 4 +- src/file/cache/CacheFile.php | 334 +++++++++++++++++++++++------------ src/tools/NucacheApp.php | 23 ++- tbin/.gitignore | 1 + tbin/test-nucache.php | 62 +++++++ 5 files changed, 305 insertions(+), 119 deletions(-) create mode 100755 tbin/test-nucache.php diff --git a/src/file/cache/CacheData.php b/src/file/cache/CacheData.php index a680f9e..f81186e 100644 --- a/src/file/cache/CacheData.php +++ b/src/file/cache/CacheData.php @@ -12,8 +12,8 @@ class CacheData { /** @var callable une fonction permettant de calculer la donnée */ const COMPUTE = null; - function __construct(?string $name=null, $compute=null) { - $this->name = $name ?? static::NAME ?? bin2hex(random_bytes(8)); + function __construct($compute=null, ?string $name=null) { + $this->name = $name ?? static::NAME ?? ""; $this->compute = func::withn($compute ?? static::COMPUTE); } diff --git a/src/file/cache/CacheFile.php b/src/file/cache/CacheFile.php index 0c9e810..1a47182 100644 --- a/src/file/cache/CacheFile.php +++ b/src/file/cache/CacheFile.php @@ -2,29 +2,65 @@ namespace nulib\file\cache; use Exception; +use nulib\cl; +use nulib\cv; use nulib\file; use nulib\file\SharedFile; use nulib\os\path; use nulib\php\time\DateTime; use nulib\php\time\Delay; use nulib\str; +use nulib\ValueException; class CacheFile extends SharedFile { /** @var string|int durée de vie par défaut des données mises en cache */ const DURATION = "1D"; // jusqu'au lendemain + const EXT = ".cache"; + function __construct($file, ?array $params=null) { if ($file === null) { $rand = bin2hex(random_bytes(8)); $file = sys_get_temp_dir()."/$rand"; } - $file = path::ensure_ext($file, ".metadata.cache", ".cache"); + $file = path::ensure_ext($file, self::EXT); $this->basedir = path::dirname($file); $basename = path::filename($file); - $this->basename = str::without_suffix(path::ext($basename), $basename); - $this->duration = Delay::with($params["duration"] ?? static::DURATION); + $this->basename = str::without_suffix(self::EXT, $basename); + $this->initialDuration = Delay::with($params["duration"] ?? static::DURATION); $this->overrideDuration = $params["override_duration"] ?? false; + $this->readonly = $params["readonly"] ?? false; $this->cacheNull = $params["cache_null"] ?? false; + $data = $params["data"] ?? null; + if ($data === null) { + $this->dataDefs = null; + $this->data = null; + } elseif ($data instanceof CacheData) { + $this->dataDefs = null; + $this->data = $data; + } elseif (!is_array($data)) { + $this->dataDefs = null; + $this->data = $this->getData($data); + } else { + $dataDefs = []; + $tmpdefs = $data; + $index = 0; + foreach ($tmpdefs as $key => $data) { + $odef = $data; + if ($data instanceof CacheData) { + } elseif (cv::subclass_of($data, CacheData::class)) { + $data = new $data(); + } else { + throw ValueException::invalid_type($odef, CacheData::class); + } + if ($key === $index) { + $index++; + $key = $data->getName(); + } + $dataDefs[$key] = $data; + } + $this->dataDefs = $dataDefs; + } parent::__construct($file); } @@ -34,12 +70,33 @@ class CacheFile extends SharedFile { /** @var string nom de base des fichiers de cache */ protected string $basename; - protected Delay $duration; + protected Delay $initialDuration; protected bool $overrideDuration; + protected bool $readonly; + protected bool $cacheNull; + protected ?array $dataDefs; + + protected ?CacheData $data; + + protected function getData($data): CacheData { + if ($data === null) { + return $this->data ??= new CacheData(function() { + return $this->compute(); + }); + } + $odata = $data; + if (is_string($data) || is_int($data)) { + $data = $this->dataDefs[$data] ?? null; + if ($data === null) throw ValueException::invalid_key($odata); + } + if ($data instanceof CacheData) return $data; + throw ValueException::invalid_type($odata, CacheData::class); + } + /** * vérifier si le fichier est valide. s'il est invalide, il faut le recréer. * @@ -50,31 +107,42 @@ class CacheFile extends SharedFile { return $this->getSize() > 0; } + protected ?DateTime $start; + + protected ?Delay $duration; + + protected ?array $datafilenames; + /** charger les données. le fichier a déjà été verrouillé en lecture */ - protected function loadMetadata(): ?array { - $this->rewind(); - [ - "start" => $start, - "duration" => $duration, - "datafiles" => $datafiles, - ] = $this->unserialize(null, false, true); - if ($this->overrideDuration) { - $duration = Delay::with($this->duration, $start); + protected function loadMetadata(): void { + if ($this->isValid()) { + $this->rewind(); + [ + "start" => $start, + "duration" => $duration, + "datafiles" => $datafilenames, + ] = $this->unserialize(null, false, true); + if ($this->overrideDuration) { + $duration = Delay::with($this->initialDuration, $start); + } + $datafilenames = array_fill_keys($datafilenames, true); + } else { + $start = null; + $duration = null; + $datafilenames = []; } - return [ - "start" => $start, - "duration" => $duration, - "datafiles" => $datafiles, - ]; + $this->start = $start; + $this->duration = $duration; + $this->datafilenames = $datafilenames; } - /** tester s'il faut mettre les données à jour. le fichier a déjà été verrouillé en lecture */ + /** + * tester s'il faut mettre les données à jour. le fichier a déjà été + * verrouillé en lecture + */ protected function shouldUpdate(bool $noCache=false): bool { if ($this->isValid()) { - /** @var Delay $duration */ - ["duration" => $duration, - ] = $this->loadMetadata(); - $expired = $duration->isElapsed(); + $expired = $this->duration->isElapsed(); } else { $expired = false; $noCache = true; @@ -83,49 +151,39 @@ class CacheFile extends SharedFile { } /** sauvegarder les données. le fichier a déjà été verrouillé en écriture */ - protected function saveMetadata(?DateTime $start, ?Delay $duration, array $datafiles): void { - $duration ??= $this->duration; - if ($start === null) { - $start = new DateTime(); - $duration = Delay::with($duration, $start); + protected function saveMetadata(): void { + $this->duration ??= $this->initialDuration; + if ($this->start === null) { + $this->start = new DateTime(); + $this->duration = Delay::with($this->duration, $this->start); } + $datafilenames = array_keys($this->datafilenames); $this->ftruncate(); $this->serialize([ - "start" => $start, - "duration" => $duration, - "datafiles" => $datafiles, + "start" => $this->start, + "duration" => $this->duration, + "datafiles" => $datafilenames, ], false, true); } - function loadData(string $datafile) { - $datafile = path::join($this->basedir, $datafile); + protected function loadData(string $datafile) { return file::reader($datafile)->unserialize(); } - function saveData(string $datafile, $data): void { - $datafile = path::join($this->basedir, $datafile); + protected function saveData(string $datafile, $data): void { file::writer($datafile)->serialize($data); } - protected function unlinkDatafile(string $datafile): void { - @unlink(path::join($this->basedir, $datafile)); + protected function unlinkDatafile(string $datafilename): void { + $datafile = path::join($this->basedir, $datafilename); + @unlink($datafile); + unset($this->datafilenames[$datafilename]); } - 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); - } + protected function unlinkFiles(bool $datafilesOnly=false): void { + if (!$datafilesOnly) @unlink($this->file); + foreach ($this->datafilenames as $datafilename) { + $this->unlinkDatafile($datafilename); } } @@ -134,101 +192,157 @@ class CacheFile extends SharedFile { return $this->cacheNull || $value !== null; } - function get(?CacheData $data=null, bool $noCache=false) { - $this->lockRead(); + protected ?DateTime $ostart; + + protected ?Delay $oduration; + + protected ?array $odatafilenames; + + protected function beforeAction() { + $this->loadMetadata(); + $this->ostart = cv::clone($this->start); + $this->oduration = cv::clone($this->duration); + $this->odatafilenames = cv::clone($this->datafilenames); + } + + protected function afterAction() { + $start = $this->start; + $duration = $this->duration; + $oduration = $this->oduration; + $datafilenames = $this->datafilenames; + $modified = false; + if ($start != $this->ostart) $modified = true; + if ($duration === null || $oduration === null) $modified = true; + elseif ($duration->getDest() != $oduration->getDest()) $modified = true; + # égalité stricte uniquement pour $datafiles qui est un array + if ($datafilenames !== $this->odatafilenames) $modified = true; + if ($modified && !$this->readonly) { + $this->lockWrite(); + $this->saveMetadata(); + } + } + + protected function action(callable $callback, bool $willWrite=false) { + if ($willWrite && !$this->readonly) $this->lockWrite(); + else $this->lockRead(); try { - $datafile = $data->getName(); - $datafile = "{$this->basename}.data.{$datafile}.cache"; - #XXX mettre à jour datafiles dans metadata - if ($this->shouldUpdate($noCache)) { + $this->beforeAction(); + $result = $callback(); + $this->afterAction(); + return $result; + } finally { + $this->start = null; + $this->duration = null; + $this->datafilenames = null; + $this->unlock(true); + } + } + + protected function compute() { + return null; + } + + function get($data=null, bool $noCache=false) { + return $this->action(function () use ($data, $noCache) { + $data = $this->getData($data); + $dataname = $data->getName(); + $datafilename = ".{$this->basename}.{$dataname}".self::EXT; + $datafile = path::join($this->basedir, $datafilename); + + $updateMetadata = $this->shouldUpdate($noCache); + $updateData = !array_key_exists($datafilename, $this->datafilenames); + if (!$this->readonly && ($updateMetadata || $updateData)) { $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; + if ($updateMetadata) { + # il faut refaire tout le cache + $this->unlinkFiles(true); + $updateData = true; } - } else { + if ($updateData) { + # calculer un fichier + try { + $data = $data->get(); + } catch (Exception $e) { + # ne pas garder le fichier en cas d'exception + $this->unlinkDatafile($datafile); + throw $e; + } + } elseif (file_exists($datafile)) { + $data = $this->loadData($datafile); + } else { + $data = null; + } + if ($this->shouldCache($data)) { + $this->saveData($datafile, $data); + $this->datafilenames[$datafilename] = true; + } else { + # ne pas garder le fichier s'il ne faut pas mettre en cache + $this->unlinkDatafile($datafile); + } + } elseif (file_exists($datafile)) { $data = $this->loadData($datafile); + } else { + $data = null; } return $data; - } finally { - $this->unlock(); - } + }); } /** obtenir les informations sur le fichier */ function getInfos(): array { - $this->lockRead(); - try { + return $this->action(function () { if (!$this->isValid()) { return ["valid" => false]; } - /** - * @var DateTime $start - * @var Delay $duration - */ - [ - "start" => $start, - "duration" => $duration, - "datafiles" => $datafiles, - ] = $this->loadMetadata(); + $start = $this->start; + $duration = $this->duration; + $datafilenames = $this->datafilenames; + $datafiles = []; + foreach (array_keys($datafilenames) as $datafilename) { + $datafile = path::join($this->basedir, $datafilename); + $name = $datafilename; + str::del_prefix($name, ".{$this->basename}."); + str::del_suffix($name, self::EXT); + if (file_exists($datafile)) { + $size = filesize($datafile); + } else { + $size = null; + } + $datafiles[$name] = $size; + } return [ "valid" => true, - "size" => $this->getSize(), "start" => $start, "duration" => strval($duration), "date_start" => $start->format(), "date_end" => $duration->getDest()->format(), "datafiles" => $datafiles, ]; - } finally { - $this->unlock(); - } + }); } const UPDATE_SUB = -1, UPDATE_SET = 0, UPDATE_ADD = 1; /** mettre à jour la durée de validité du fichier */ function updateDuration($nduration, int $action=1): void { - $this->lockRead(); - try { + if ($this->readonly) return; + $this->action(function () use ($nduration, $action) { if (!$this->isValid()) return; - $this->lockWrite(); - /** - * @var DateTime $tstart - * @var Delay $duration - */ - [ - "start" => $start, - "duration" => $duration, - ] = $this->loadMetadata(); + $duration = $this->duration; if ($action < 0) $duration->subDuration($nduration); elseif ($action > 0) $duration->addDuration($nduration); - $this->saveMetadata($start, $duration); - } finally { - $this->unlock(); - } + }, true); } /** supprimer les fichiers s'ils ont expiré */ function deleteExpired(bool $force=false): bool { - $this->lockRead(); - try { + if ($this->readonly) return false; + return $this->action(function () use ($force) { if ($force || $this->shouldUpdate()) { - $this->lockWrite(); $this->unlinkFiles(); return true; } - } finally { - $this->unlock(); - } - return false; + return false; + }, true); } } diff --git a/src/tools/NucacheApp.php b/src/tools/NucacheApp.php index 9fc01d4..4c6687b 100644 --- a/src/tools/NucacheApp.php +++ b/src/tools/NucacheApp.php @@ -47,9 +47,15 @@ class NucacheApp extends Application { function setActionUpdate(int $action, $updateDuration): void { $this->action = self::ACTION_UPDATE; switch ($action) { - case self::ACTION_UPDATE_SUB: $this->updateAction = CacheFile::UPDATE_SUB; break; - case self::ACTION_UPDATE_SET: $this->updateAction = CacheFile::UPDATE_SET; break; - case self::ACTION_UPDATE_ADD: $this->updateAction = CacheFile::UPDATE_ADD; break; + case self::ACTION_UPDATE_SUB: + $this->updateAction = CacheFile::UPDATE_SUB; + break; + case self::ACTION_UPDATE_SET: + $this->updateAction = CacheFile::UPDATE_SET; + break; + case self::ACTION_UPDATE_ADD: + $this->updateAction = CacheFile::UPDATE_ADD; + break; } $this->updateDuration = $updateDuration; } @@ -72,7 +78,7 @@ class NucacheApp extends Application { } elseif (is_file($arg)) { $files[] = $arg; } else { - msg::warning("$arg: fichier invalide ou introuvable"); + msg::warning("$arg: fichier introuvable"); } } $showSection = count($files) > 1; @@ -81,14 +87,17 @@ class NucacheApp extends Application { case self::ACTION_READ: if ($showSection) msg::section($file); $cache = new CacheFile($file, [ + "readonly" => true, "duration" => "INF", "override_duration" => true, ]); - //yaml::dump($cache->get()); + yaml::dump($cache->get()); break; case self::ACTION_INFOS: if ($showSection) msg::section($file); - $cache = new CacheFile($file); + $cache = new CacheFile($file, [ + "readonly" => true, + ]); yaml::dump($cache->getInfos()); break; case self::ACTION_CLEAN: @@ -96,7 +105,7 @@ class NucacheApp extends Application { $cache = new CacheFile($file); try { if ($cache->deleteExpired()) msg::asuccess("fichier supprimé"); - else msg::astep("fichier non expiré"); + else msg::adone("fichier non expiré"); } catch (Exception $e) { msg::afailure($e); } diff --git a/tbin/.gitignore b/tbin/.gitignore index 74dd8df..f9f3cae 100644 --- a/tbin/.gitignore +++ b/tbin/.gitignore @@ -1,2 +1,3 @@ /output-forever.log /devel/ +/*.cache diff --git a/tbin/test-nucache.php b/tbin/test-nucache.php new file mode 100755 index 0000000..ddaf641 --- /dev/null +++ b/tbin/test-nucache.php @@ -0,0 +1,62 @@ +#!/usr/bin/php +get()); +} + +if (in_array("one", $what)) { + $one = new class("one") extends CacheFile { + protected function compute() { + return 1; + } + }; + Txx("one=", $one->get()); +} + +if (in_array("two", $what)) { + $two = new CacheFile("two", [ + "data" => new CacheData(function () { + return 2; + }), + ]); + Txx("two=", $two->get()); +} + +if (in_array("three", $what)) { + $data31 = new CacheData(function () { + return 31; + }, "data31name"); + + $data32 = new CacheData(function () { + return 32; + }); + + $three = new CacheFile("three", [ + "data" => [ + "data31" => $data31, + $data31, # name=data31name + "data32" => $data32, + $data32, # name="" + ], + ]); + Txx("three.0=", $three->get("data31")); + Txx("three.1=", $three->get("data31name")); + Txx("three.2=", $three->get("data32")); + Txx("three.3=", $three->get("")); +} \ No newline at end of file From 66bd7ccf12bb2197249691d690e8f29c2442cfcb Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 23 May 2025 21:20:29 +0400 Subject: [PATCH 8/8] modifs.mineures sans commentaires --- src/{db => }/cache/CacheChannel.php | 2 +- src/{file => }/cache/CacheData.php | 2 +- .../CacheDataChannel.php} | 8 +- src/{file => }/cache/CacheFile.php | 96 +++++++++++-------- .../cache.php => cache/storage_cache.php} | 10 +- src/tools/NucacheApp.php | 11 ++- tbin/test-nucache.php | 36 ++++--- 7 files changed, 102 insertions(+), 63 deletions(-) rename src/{db => }/cache/CacheChannel.php (99%) rename src/{file => }/cache/CacheData.php (97%) rename src/{db/cache/RowsChannel.php => cache/CacheDataChannel.php} (86%) rename src/{file => }/cache/CacheFile.php (80%) rename src/{db/cache/cache.php => cache/storage_cache.php} (75%) diff --git a/src/db/cache/CacheChannel.php b/src/cache/CacheChannel.php similarity index 99% rename from src/db/cache/CacheChannel.php rename to src/cache/CacheChannel.php index b1f8619..f222b09 100644 --- a/src/db/cache/CacheChannel.php +++ b/src/cache/CacheChannel.php @@ -1,5 +1,5 @@ "varchar(128) primary key not null", "all_values" => "mediumtext", @@ -38,7 +40,7 @@ class RowsChannel extends CapacitorChannel implements IteratorAggregate { } function getIterator(): Traversable { - $cm = cache::get(); + $cm = storage_cache::get(); if ($cm->shouldUpdate($this->cacheIds)) { $this->capacitor->reset(); foreach (($this->builder)() as $key => $row) { diff --git a/src/file/cache/CacheFile.php b/src/cache/CacheFile.php similarity index 80% rename from src/file/cache/CacheFile.php rename to src/cache/CacheFile.php index 1a47182..3feb150 100644 --- a/src/file/cache/CacheFile.php +++ b/src/cache/CacheFile.php @@ -1,12 +1,12 @@ basedir = path::dirname($file); @@ -32,34 +39,28 @@ class CacheFile extends SharedFile { $this->readonly = $params["readonly"] ?? false; $this->cacheNull = $params["cache_null"] ?? false; $data = $params["data"] ?? null; + $this->sources = null; if ($data === null) { - $this->dataDefs = null; - $this->data = null; + $this->source = null; } elseif ($data instanceof CacheData) { - $this->dataDefs = null; - $this->data = $data; + $this->source = $data; + } elseif (func::is_callable($data)) { + $this->source = new CacheData($data); } elseif (!is_array($data)) { - $this->dataDefs = null; - $this->data = $this->getData($data); + $this->source = self::ensure_source($data); } else { - $dataDefs = []; - $tmpdefs = $data; + $sources = []; $index = 0; - foreach ($tmpdefs as $key => $data) { - $odef = $data; - if ($data instanceof CacheData) { - } elseif (cv::subclass_of($data, CacheData::class)) { - $data = new $data(); - } else { - throw ValueException::invalid_type($odef, CacheData::class); - } + foreach ($data as $key => $source) { + $source = self::ensure_source($source); if ($key === $index) { $index++; - $key = $data->getName(); + $key = $source->getName(); } - $dataDefs[$key] = $data; + $sources[$key] = $source; } - $this->dataDefs = $dataDefs; + $this->sources = $sources; + $this->source = null; } parent::__construct($file); } @@ -78,23 +79,23 @@ class CacheFile extends SharedFile { protected bool $cacheNull; - protected ?array $dataDefs; + protected ?array $sources; - protected ?CacheData $data; + protected ?CacheData $source; - protected function getData($data): CacheData { + protected function getSource($data): CacheData { if ($data === null) { - return $this->data ??= new CacheData(function() { + return $this->source ??= new CacheData(function() { return $this->compute(); }); } - $odata = $data; - if (is_string($data) || is_int($data)) { - $data = $this->dataDefs[$data] ?? null; - if ($data === null) throw ValueException::invalid_key($odata); + $source = $data; + if (is_string($source) || is_int($source)) { + $source = $this->sources[$source] ?? null; + if ($source === null) throw ValueException::invalid_key($data); } - if ($data instanceof CacheData) return $data; - throw ValueException::invalid_type($odata, CacheData::class); + if ($source instanceof CacheData) return $source; + throw ValueException::invalid_type($data, CacheData::class); } /** @@ -102,7 +103,7 @@ class CacheFile extends SharedFile { * * on assume que le fichier existe, vu qu'il a été ouvert en c+b */ - protected function isValid(): bool { + function isValid(): bool { # considèrer que le fichier est invalide s'il est de taille nulle return $this->getSize() > 0; } @@ -244,8 +245,8 @@ class CacheFile extends SharedFile { function get($data=null, bool $noCache=false) { return $this->action(function () use ($data, $noCache) { - $data = $this->getData($data); - $dataname = $data->getName(); + $source = $this->getSource($data); + $dataname = $source->getName(); $datafilename = ".{$this->basename}.{$dataname}".self::EXT; $datafile = path::join($this->basedir, $datafilename); @@ -256,12 +257,14 @@ class CacheFile extends SharedFile { if ($updateMetadata) { # il faut refaire tout le cache $this->unlinkFiles(true); + $this->start = null; + $this->duration = null; $updateData = true; } if ($updateData) { # calculer un fichier try { - $data = $data->get(); + $data = $source->get(); } catch (Exception $e) { # ne pas garder le fichier en cas d'exception $this->unlinkDatafile($datafile); @@ -288,6 +291,19 @@ class CacheFile extends SharedFile { }); } + function all($data=null, bool $noCache=false): ?iterable { + $data = $this->get($data, $noCache); + if ($data !== null && !is_iterable($data)) $data = [$data]; + return $data; + } + + function delete($data=null): void { + $source = $this->getSource($data); + $dataname = $source->getName(); + $datafilename = ".{$this->basename}.{$dataname}".self::EXT; + $this->unlinkDatafile($datafilename); + } + /** obtenir les informations sur le fichier */ function getInfos(): array { return $this->action(function () { @@ -323,8 +339,12 @@ class CacheFile extends SharedFile { const UPDATE_SUB = -1, UPDATE_SET = 0, UPDATE_ADD = 1; - /** mettre à jour la durée de validité du fichier */ - function updateDuration($nduration, int $action=1): void { + /** + * mettre à jour la durée de validité du fichier + * + * XXX UPDATE_SET n'est pas implémenté + */ + function updateDuration($nduration, int $action=self::UPDATE_ADD): void { if ($this->readonly) return; $this->action(function () use ($nduration, $action) { if (!$this->isValid()) return; diff --git a/src/db/cache/cache.php b/src/cache/storage_cache.php similarity index 75% rename from src/db/cache/cache.php rename to src/cache/storage_cache.php index 401fb19..1fc6814 100644 --- a/src/db/cache/cache.php +++ b/src/cache/storage_cache.php @@ -1,11 +1,13 @@ [null, "->setActionUpdate", self::ACTION_UPDATE_SUB], "help" => "Enlever le nombre de secondes spécifié à la durée du cache", ], - ["-s", "--set-duration", "args" => 1, - "action" => [null, "->setActionUpdate", self::ACTION_UPDATE_SET], - "help" => "Mettre à jour la durée du cache à la valeur spécifiée", - ], + #XXX pas encore implémenté + //["-s", "--set-duration", "args" => 1, + // "action" => [null, "->setActionUpdate", self::ACTION_UPDATE_SET], + // "help" => "Mettre à jour la durée du cache à la valeur spécifiée", + //], ]; protected $action = self::ACTION_READ; diff --git a/tbin/test-nucache.php b/tbin/test-nucache.php index ddaf641..802926f 100755 --- a/tbin/test-nucache.php +++ b/tbin/test-nucache.php @@ -2,40 +2,54 @@ get()); + if ($dumpInfos) { + yaml::dump($cache->getInfos()); + } +} + //system("rm -f *.cache .*.cache"); $what = [ - "null", + //"null", "one", - "two", - "three", + //"two", + //"three", ]; +$duration = 10; if (in_array("null", $what)) { - $null = new CacheFile("null"); - Txx("null=", $null->get()); + $null = new CacheFile("null", [ + "duration" => $duration, + ]); + show("null", $null); } if (in_array("one", $what)) { - $one = new class("one") extends CacheFile { + $one = new class("one", [ + "duration" => $duration, + ]) extends CacheFile { protected function compute() { return 1; } }; - Txx("one=", $one->get()); + show("one", $one); } if (in_array("two", $what)) { $two = new CacheFile("two", [ + "duration" => $duration, "data" => new CacheData(function () { return 2; }), ]); - Txx("two=", $two->get()); + show("two", $two); } if (in_array("three", $what)) { @@ -59,4 +73,4 @@ if (in_array("three", $what)) { Txx("three.1=", $three->get("data31name")); Txx("three.2=", $three->get("data32")); Txx("three.3=", $three->get("")); -} \ No newline at end of file +}