From 4c91327bacf8c3b307de535a92ac509fd7625781 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 23 May 2025 05:02:31 +0400 Subject: [PATCH] =?UTF-8?q?db/cache=20doit=20encore=20=C3=AAtre=20travaill?= =?UTF-8?q?=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 @@ +