diff --git a/src/cache/CacheData.php b/src/cache/CacheData.php new file mode 100644 index 0000000..5ce5b83 --- /dev/null +++ b/src/cache/CacheData.php @@ -0,0 +1,46 @@ +name = $name ?? ""; + $this->compute = func::withn($compute ?? static::COMPUTE); + } + + protected string $name; + + function getName() : string { + return $this->name; + } + + protected ?func $compute; + + /** calculer la donnée */ + function compute() { + $compute = $this->compute; + $data = $compute !== null? $compute->invoke(): null; + return $data; + } + + /** spécifier le chemin du cache à partir du fichier de base */ + abstract function setDatafile(?string $basefile): void; + + /** indiquer si le cache existe */ + abstract function exists(): bool; + + /** charger la donnée depuis le cache */ + abstract function load(); + + /** sauvegarder la donnée dans le cache et la retourner */ + abstract function save($data); + + /** supprimer le cache */ + abstract function delete(); +} diff --git a/src/cache/CacheFile.php b/src/cache/CacheFile.php index 01ea78a..f40ed80 100644 --- a/src/cache/CacheFile.php +++ b/src/cache/CacheFile.php @@ -22,21 +22,21 @@ class CacheFile extends SharedFile { else return new static($file, $data); } - protected static function ensure_source($data, ?IDataCache &$source, bool $allowArray=true): bool { - if ($data === null || $data instanceof IDataCache) { + protected static function ensure_source($data, ?CacheData &$source, bool $allowArray=true): bool { + if ($data === null || $data instanceof CacheData) { $source = $data; - } elseif (is_subclass_of($data, IDataCache::class)) { + } elseif (is_subclass_of($data, CacheData::class)) { $source = new $data(); } elseif (func::is_callable($data)) { - $source = new DataCache(null, $data); + $source = new DataCacheData(null, $data); } elseif (is_array($data) && $allowArray) { return false; } elseif (is_iterable($data)) { - $source = new DataCache(null, static function() use ($data) { + $source = new DataCacheData(null, static function() use ($data) { yield from $data; }); } else { - throw ValueException::invalid_type($source, IDataCache::class); + throw ValueException::invalid_type($source, CacheData::class); } return true; } @@ -53,13 +53,8 @@ class CacheFile extends SharedFile { $data ??= $params["data"] ?? null; $this->sources = null; if (self::ensure_source($data, $source)) { - if ($source !== null) { - $source->setDatafile($basefile); - $key = $source->getName(); - } else { - $key = ""; - } - $this->sources = [$key => $source]; + if ($source !== null) $source->setDatafile($basefile); + $this->sources = ["" => $source]; } else { $sources = []; $index = 0; @@ -89,7 +84,7 @@ class CacheFile extends SharedFile { protected bool $cacheNull; - /** @var ?IDataCache[] */ + /** @var ?CacheData[] */ protected ?array $sources; /** @@ -268,7 +263,7 @@ class CacheFile extends SharedFile { $data = $source->load(); } if ($this->shouldCache($data)) { - $source->save($data); + $data = $source->save($data); } else { # ne pas garder le fichier s'il ne faut pas mettre en cache $source->delete(); diff --git a/src/cache/CursorCacheData.php b/src/cache/CursorCacheData.php new file mode 100644 index 0000000..bcfdd33 --- /dev/null +++ b/src/cache/CursorCacheData.php @@ -0,0 +1,36 @@ +initStorage(cache::storage()); + $this->channel = $channel; + } + + function setDatafile(?string $basefile): void { + } + + protected CursorChannel $channel; + + function exists(): bool { + return $this->channel->count() > 0; + } + + function load() { + return $this->channel; + } + + function save($data) { + if (!is_iterable($data)) $data = [$data]; + $this->channel->rechargeAll($data); + return $this->channel; + } + + function delete() { + $this->channel->delete(null); + } +} diff --git a/src/cache/DataCache.php b/src/cache/DataCacheData.php similarity index 74% rename from src/cache/DataCache.php rename to src/cache/DataCacheData.php index cf2775b..7ada552 100644 --- a/src/cache/DataCache.php +++ b/src/cache/DataCacheData.php @@ -7,7 +7,7 @@ use nulib\os\path; use nulib\php\func; use Traversable; -class DataCache implements IDataCache { +class DataCacheData extends CacheData { /** @var string identifiant de cette donnée */ const NAME = null; @@ -15,22 +15,14 @@ class DataCache implements IDataCache { const COMPUTE = null; function __construct(?string $name=null, $compute=null, ?string $basefile=null) { - $this->name = $name ?? static::NAME ?? ""; - $this->compute = func::withn($compute ?? static::COMPUTE); + $name ??= static::NAME ?? ""; + $compute ??= static::COMPUTE; + parent::__construct($name, $compute); $this->setDatafile($basefile); } - protected string $name; - - function getName() : string { - return $this->name; - } - - protected ?func $compute; - function compute() { - $compute = $this->compute; - $data = $compute !== null? $compute->invoke(): null; + $data = parent::compute(); if ($data instanceof Traversable) $data = cl::all($data); return $data; } @@ -56,8 +48,9 @@ class DataCache implements IDataCache { return file::reader($this->datafile)->unserialize(); } - function save($data): void { + function save($data) { file::writer($this->datafile)->serialize($data); + return $data; } function delete(): void { diff --git a/src/cache/IDataCache.php b/src/cache/IDataCache.php deleted file mode 100644 index e25424d..0000000 --- a/src/cache/IDataCache.php +++ /dev/null @@ -1,27 +0,0 @@ -get(null, $noCache); } - static function all($cursorId, ?iterable $rows, ?array $params=null): iterable { - self::verifix_id($dataId); - $noCache = !self::should_cache($dataId["id"], $dataId["group_id"]); - $cache = self::new($cursorId, "_rows", new CursorCache($cursorId, $rows), $params); + static function all($cursorId, $rows, ?array $params=null): ?iterable { + self::verifix_id($cursorId); + $noCache = !self::should_cache($cursorId["id"], $cursorId["group_id"]); + $cache = self::new($cursorId, "_rows", new CursorCacheData($cursorId, $rows), $params); return $cache->get(null, $noCache); } } diff --git a/tbin/test-nucache.php b/tbin/test-nucache.php index 43f06df..f3590c0 100755 --- a/tbin/test-nucache.php +++ b/tbin/test-nucache.php @@ -2,7 +2,7 @@ $duration, @@ -52,11 +52,11 @@ if (in_array("two", $what)) { } if (in_array("three", $what)) { - $data31 = new DataCache("data31name", function () { + $data31 = new DataCacheData("data31name", function () { return 31; }); - $data32 = new DataCache(null, function () { + $data32 = new DataCacheData(null, function () { return 32; }); diff --git a/tests/cache/SourceTest.php b/tests/cache/SourceTest.php deleted file mode 100644 index b35d3f6..0000000 --- a/tests/cache/SourceTest.php +++ /dev/null @@ -1,66 +0,0 @@ - 1, "s" => null, "i" => null, "b" => null], - ["pk" => 2, "s" => "false", "i" => 0, "b" => 0], - ["pk" => 3, "s" => "first", "i" => 1, "b" => 1], - ["pk" => 4, "s" => "second", "i" => 2, "b" => 1], - ], iterator_to_array($dest)); - } - - function testDirect() { - $destStorage = new SqliteStorage(new Sqlite(__DIR__.'/dest.db')); - new Capacitor($destStorage, $dest = new CursorChannel("source")); - - $sourceDb = new SourceDb(); - $dest->rechargeAll($sourceDb->all("select * from source")); - - $this->assertSource($dest); - } - - function testCache() { - $getSource = function() { - $db = new SourceDb(); - msg::info("query source"); - yield from $db->all("select * from source"); - }; - - $params = [ - "duration" => 2, - "override_duration" => true, - ]; - - msg::info("initial"); - cache::nc(); - $dest = cache::all("source", $getSource(), $params); - $this->assertSource($dest); - - msg::info("cached"); - $dest = cache::all("source", $getSource(), $params); - $this->assertSource($dest); - - sleep(4); - msg::info("expired"); - $dest = cache::all("source", $getSource(), $params); - $this->assertSource($dest); - - sleep(4); - msg::info("end"); - } -} diff --git a/tests/cache/cacheTest.php b/tests/cache/cacheTest.php index 3833d55..3a16cb0 100644 --- a/tests/cache/cacheTest.php +++ b/tests/cache/cacheTest.php @@ -21,38 +21,46 @@ class cacheTest extends _TestCase { msg::note("fin gendata"); } - function _testRows(iterable $rows) { + function _testRows(iterable $rows, int $expectedCount) { $count = 0; foreach ($rows as $key => $row) { - msg::info("got $key => {a={$row["a"]}, b={$row["b"]}}"); + $parts = ["got $key => {"]; + $i = 0; + foreach ($row as $k => $v) { + if ($i++ > 0) $parts[] = ", "; + $parts[] = "$k=$v"; + } + $parts[] = "}"; + msg::info(implode("", $parts)); $count++; } - self::assertSame(3, $count); + self::assertSame($expectedCount, $count); } - function _testGet(string $dataId, callable $gencompute) { + + function _testGet(string $dataId, int $expectedCount, callable $gencompute) { msg::section($dataId); - cache::nc(); + cache::nc(true, true); msg::step("premier"); $rows = cache::get($dataId, $gencompute()); - $this->_testRows($rows); + $this->_testRows($rows, $expectedCount); msg::step("deuxième"); $rows = cache::get($dataId, $gencompute()); - $this->_testRows($rows); + $this->_testRows($rows, $expectedCount); msg::step("vider le cache"); cache::nc(true, true); msg::step("premier"); $rows = cache::get($dataId, $gencompute()); - $this->_testRows($rows); + $this->_testRows($rows, $expectedCount); msg::step("deuxième"); $rows = cache::get($dataId, $gencompute()); - $this->_testRows($rows); + $this->_testRows($rows, $expectedCount); } function testGetStatic() { - $this->_testGet("getStatic", function() { + $this->_testGet("getStatic", 3, function () { return static function () { msg::note("getdata"); return self::DATA; @@ -61,12 +69,40 @@ class cacheTest extends _TestCase { } function testGetGenerator() { - $this->_testGet("getGenerator", function() { + $this->_testGet("getGenerator", 3, function () { return $this->gendata(); }); } - function testAll() { - + function _testAll(string $cursorId, int $expectedCount, callable $gencompute) { + msg::section($cursorId); + cache::nc(true, true); + + msg::step("premier"); + $rows = cache::all($cursorId, $gencompute()); + $this->_testRows($rows, $expectedCount); + msg::step("deuxième"); + $rows = cache::all($cursorId, $gencompute()); + $this->_testRows($rows, $expectedCount); + + msg::step("vider le cache"); + cache::nc(true, true); + + msg::step("premier"); + $rows = cache::all($cursorId, $gencompute()); + $this->_testRows($rows, $expectedCount); + msg::step("deuxième"); + $rows = cache::all($cursorId, $gencompute()); + $this->_testRows($rows, $expectedCount); + } + + function testAllGenerator() { + $this->_testAll("allGenerator", 4, function() { + return static function() { + $db = new SourceDb(); + msg::note("query source"); + yield from $db->all("select * from source"); + }; + }); } }