From 4494c8ecc32b1eda5e1d5531acd5c11d5430d2a8 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 13 May 2024 17:59:15 +0400 Subject: [PATCH] FileCachedValue utilise Delay --- nur_bin/cachectl.php | 4 +-- nur_src/b/io/FileCachedValue.php | 53 +++++++++++++++++++------------- src/php/time/DateInterval.php | 6 ++++ src/php/time/DateTime.php | 5 +++ src/php/time/Delay.php | 48 +++++++++++++++++++++++------ 5 files changed, 83 insertions(+), 33 deletions(-) diff --git a/nur_bin/cachectl.php b/nur_bin/cachectl.php index f1ceedc..e531e78 100755 --- a/nur_bin/cachectl.php +++ b/nur_bin/cachectl.php @@ -44,7 +44,7 @@ Application::run(new class extends Application { protected $args; - function setActionUpdate(int $action, int $updateDuration): void { + function setActionUpdate(int $action, $updateDuration): void { $this->action = self::ACTION_UPDATE; switch ($action) { case self::ACTION_UPDATE_SUB: $this->updateAction = -1; break; @@ -81,7 +81,7 @@ Application::run(new class extends Application { case self::ACTION_READ: if ($showSection) msg::section($file); $cache = new CacheFile($file, [ - "duration" => PHP_INT_MAX, + "duration" => "INF", "override_duration" => true, ]); yaml::dump($cache->get()); diff --git a/nur_src/b/io/FileCachedValue.php b/nur_src/b/io/FileCachedValue.php index 8ff5d1c..3ff90e6 100644 --- a/nur_src/b/io/FileCachedValue.php +++ b/nur_src/b/io/FileCachedValue.php @@ -7,15 +7,14 @@ use Exception; use Generator; use nur\A; use nur\b\coll\TBaseArray; -use nur\b\date\Date; -use nur\b\date\Datetime; use nur\b\IllegalAccessException; use nur\b\params\Parametrable; use nur\b\params\Tparametrable; use nur\data\types\Tmd; use nur\file; use nur\os; -use nur\ref\ref_cache; +use nur\sery\php\time\DateTime; +use nur\sery\php\time\Delay; /** * Class FileCachedValue: un fichier utilisé pour mettre en cache certaines @@ -28,8 +27,8 @@ abstract class FileCachedValue extends Parametrable implements ArrayAccess, Coun /** @var string chemin vers le fichier cache par défaut */ const FILE = null; - /** @var int durée de vie par défaut du cache en secondes */ - const DURATION = 8 * ref_cache::HOUR; + /** @var int durée de vie par défaut du cache */ + const DURATION = "1D"; // jusqu'au lendemain /** @var bool faut-il mettre en cache la valeur nulle? */ const CACHE_NULL = false; @@ -50,7 +49,7 @@ abstract class FileCachedValue extends Parametrable implements ArrayAccess, Coun const PARAMETRABLE_PARAMS_SCHEMA = [ "file" => ["?string", null, "chemin vers le fichier"], - "duration" => ["int", null, "durée de vie du cache en secondes"], + "duration" => [Delay::class, null, "durée de vie du cache"], "override_duration" => ["bool", false, "faut-il ignorer la duration inscrite dans le fichier et prendre la valeur locale?"], "cache_null" => ["bool", false, "faut-il mettre en cache la valeur null?"], "data" => ["array", null, "données supplémentaires"] @@ -67,7 +66,7 @@ abstract class FileCachedValue extends Parametrable implements ArrayAccess, Coun return $cacheFile; } - /** @var int */ + /** @var Delay */ protected $ppDuration; /** @var bool */ @@ -94,8 +93,8 @@ abstract class FileCachedValue extends Parametrable implements ArrayAccess, Coun $outf = file::open($file, "wb"); try { $contents = $this->serialize($data); - $tstart = time(); - $duration = $this->ppDuration; + $tstart = new DateTime(); + $duration = Delay::with($this->ppDuration, $tstart); fwrite($outf, serialize([$tstart, $duration])."\n"); fwrite($outf, $contents); } finally { @@ -150,19 +149,25 @@ abstract class FileCachedValue extends Parametrable implements ArrayAccess, Coun protected function loadInfos(): array { [$tstart, $duration] = unserialize(fgets($this->fp)); - if ($this->ppOverrideDuration) $duration = $this->ppDuration; + if (is_int($tstart)) { + $tstart = new DateTime($tstart); + $duration = new Delay($duration, $tstart); + } + if ($this->ppOverrideDuration) { + $duration = Delay::with($this->ppDuration, $tstart); + } return [$tstart, $duration]; } protected function shouldUpdate(bool $noCache=false) { + /** @var Delay $duration */ $this->_open(); $cleanup = true; try { $this->_lock(LOCK_SH); if ($this->isValidFile()) { - $now = time(); [$tstart, $duration] = $this->loadInfos(); - $expired = $now - $tstart > $duration; + $expired = $duration->isElapsed(); } else { $expired = false; $noCache = true; @@ -234,16 +239,18 @@ abstract class FileCachedValue extends Parametrable implements ArrayAccess, Coun $this->_lock(LOCK_SH); if (!$this->isValidFile()) return ["valid" => false]; $size = filesize($this->ppFile); + /** + * @var DateTime $tstart + * @var Delay $duration + */ [$tstart, $duration] = $this->loadInfos(); - $dateStart = new Datetime($tstart); - $dateEnd = new Datetime($tstart + $duration); return [ "valid" => true, "size" => $size, "tstart" => $tstart, - "duration" => $duration, - "date_start" => $dateStart->format(), - "date_end" => $dateEnd->format(), + "duration" => strval($duration), + "date_start" => $tstart->format(), + "date_end" => $duration->getDest()->format(), ]; } finally { $this->cleanup(); @@ -253,17 +260,21 @@ abstract class FileCachedValue extends Parametrable implements ArrayAccess, Coun const UPDATE_SUB = -1, UPDATE_SET = 0, UPDATE_ADD = 1; /** mettre à jour la durée de validité du fichier */ - function updateDuration(int $duration, int $action=1): void { + function updateDuration($nduration, int $action=1): void { $this->_open(); try { $this->_lock(LOCK_SH); if (!$this->isValidFile()) return; $this->_lock(LOCK_EX); $fp = $this->fp; - [$tstart, $oduration] = $this->loadInfos(); + /** + * @var DateTime $tstart + * @var Delay $duration + */ + [$tstart, $duration] = $this->loadInfos(); $contents = stream_get_contents($fp); - if ($action < 0) $duration = $oduration - $duration; - elseif ($action > 0) $duration = $oduration + $duration; + if ($action < 0) $duration->subDuration($nduration); + elseif ($action > 0) $duration->addDuration($nduration); fseek($fp, 0); ftruncate($fp, 0); fwrite($fp, serialize([$tstart, $duration])."\n"); diff --git a/src/php/time/DateInterval.php b/src/php/time/DateInterval.php index f8303b8..766ec53 100644 --- a/src/php/time/DateInterval.php +++ b/src/php/time/DateInterval.php @@ -4,6 +4,11 @@ namespace nur\sery\php\time; use InvalidArgumentException; class DateInterval extends \DateInterval { + static function with($interval): self { + if ($interval instanceof static) return $interval; + else return new static($interval); + } + protected static function to_string(DateInterval $interval) { $string = "P"; $y = $interval->y; @@ -24,6 +29,7 @@ class DateInterval extends \DateInterval { } function __construct($duration) { + if (is_int($duration)) $duration = "PT${duration}S"; if ($duration instanceof \DateInterval) { $this->y = $duration->y; $this->m = $duration->m; diff --git a/src/php/time/DateTime.php b/src/php/time/DateTime.php index 91cfdd0..dece2e3 100644 --- a/src/php/time/DateTime.php +++ b/src/php/time/DateTime.php @@ -24,6 +24,11 @@ use InvalidArgumentException; * @property-read string $YmdHMSZ */ class DateTime extends \DateTime { + static function with($datetime): self { + if ($datetime instanceof static) return $datetime; + else return new static($datetime); + } + const DMY_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))?$/'; const YMD_PATTERN = '/^((?:\d{2})?\d{2})(\d{2})(\d{2})$/'; const DMYHIS_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))? +(\d+)[h:.](\d+)(?:[:.](\d+))?$/'; diff --git a/src/php/time/Delay.php b/src/php/time/Delay.php index 1df71ae..4cf861f 100644 --- a/src/php/time/Delay.php +++ b/src/php/time/Delay.php @@ -13,6 +13,7 @@ use InvalidArgumentException; * - une chaine de la forme "x[WDHMS]y" où x et y sont des nombres et la lettre * est l'unité de temps: W représente une semaine, D une journée, H une heure, * M une minute et S une seconde. + * - la chaine "INF" qui représente une durée infinie * * Dans cette dernière forme, le timestamp destination est calculé en ajoutant x * unités. puis l'unité inférieure est ramenée à (0 + y) @@ -24,6 +25,11 @@ use InvalidArgumentException; * NB: la valeur y pour l'unité S est ignorée */ class Delay { + static function with($delay, ?DateTimeInterface $from=null): self { + if ($delay instanceof static) return $delay; + else return new static($delay, $from); + } + /** valeurs par défaut de x et y pour les unités supportées */ const DEFAULTS = [ "w" => [0, 5], @@ -35,6 +41,7 @@ class Delay { static function compute_dest(int $x, string $u, ?int $y, DateTime $from): array { $dest = DateTime::clone($from); + $yu = null; switch ($u) { case "w": if ($x > 0) { @@ -43,29 +50,28 @@ class Delay { } $w = 7 - intval($dest->format("w")); $dest->add(new \DateInterval("P${w}D")); - $u = "h"; + $yu = "h"; break; case "d": $dest->add(new \DateInterval("P${x}D")); - $u = "h"; + $yu = "h"; break; case "h": $dest->add(new \DateInterval("PT${x}H")); - $u = "m"; + $yu = "m"; break; case "m": $dest->add(new \DateInterval("PT${x}M")); - $u = "s"; + $yu = "s"; break; case "s": $dest->add(new \DateInterval("PT${x}S")); - $u = null; break; } - if ($y !== null && $u !== null) { + if ($y !== null && $yu !== null) { $h = intval($dest->format("H")); $m = intval($dest->format("i")); - switch ($u) { + switch ($yu) { case "h": $dest->setTime($y, 0, 0, 0); break; @@ -77,13 +83,18 @@ class Delay { break; } } - $repr = $y !== null? "$x$y$y": "$x"; + $u = strtoupper($u); + $repr = $y !== null? "$x$u$y": "$x"; return [$dest, $repr]; } function __construct($delay, ?DateTimeInterface $from=null) { if ($from === null) $from = new DateTime(); - if (is_int($delay)) { + if ($delay === "INF") { + $dest = DateTime::clone($from); + $dest->add(new DateInterval("P9999Y")); + $repr = "INF"; + } elseif (is_int($delay)) { [$dest, $repr] = self::compute_dest($delay, "s", null, $from); } elseif (is_string($delay) && preg_match('/^\d+$/', $delay)) { $x = intval($delay); @@ -111,6 +122,22 @@ class Delay { return $this->dest; } + function addDuration($duration) { + if (is_int($duration) && $duration < 0) { + $this->dest->sub(DateInterval::with(-$duration)); + } else { + $this->dest->add(DateInterval::with($duration)); + } + } + + function subDuration($duration) { + if (is_int($duration) && $duration < 0) { + $this->dest->add(DateInterval::with(-$duration)); + } else { + $this->dest->sub(DateInterval::with($duration)); + } + } + /** @var string */ protected $repr; @@ -125,7 +152,8 @@ class Delay { /** retourner true si le délai imparti est écoulé */ function isElapsed(?DateTimeInterface $now=null): bool { - return $this->_getDiff($now)->invert == 0; + if ($this->repr === "INF") return false; + else return $this->_getDiff($now)->invert == 0; } /**