db/cache doit encore être travaillé
This commit is contained in:
parent
ba0ad15d78
commit
4c91327bac
116
src/db/cache/CacheChannel.php
vendored
Normal file
116
src/db/cache/CacheChannel.php
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
namespace nulib\db\cache;
|
||||
|
||||
use nulib\cl;
|
||||
use nulib\db\CapacitorChannel;
|
||||
use nulib\php\time\DateTime;
|
||||
use nulib\php\time\Delay;
|
||||
|
||||
class CacheChannel extends CapacitorChannel {
|
||||
/** @var int durée de vie par défaut du cache */
|
||||
const DURATION = "1D"; // jusqu'au lendemain
|
||||
|
||||
const INCLUDES = null;
|
||||
|
||||
const EXCLUDES = null;
|
||||
|
||||
const COLUMN_DEFINITIONS = [
|
||||
"group_id" => "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);
|
||||
}
|
||||
}
|
51
src/db/cache/RowsChannel.php
vendored
Normal file
51
src/db/cache/RowsChannel.php
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
namespace nulib\db\cache;
|
||||
|
||||
use Closure;
|
||||
use IteratorAggregate;
|
||||
use nulib\cl;
|
||||
use nulib\db\CapacitorChannel;
|
||||
use Traversable;
|
||||
|
||||
class RowsChannel extends CapacitorChannel implements IteratorAggregate {
|
||||
const COLUMN_DEFINITIONS = [
|
||||
"key" => "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);
|
||||
}
|
||||
}
|
37
src/db/cache/cache.php
vendored
Normal file
37
src/db/cache/cache.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace nulib\db\cache;
|
||||
|
||||
use nulib\db\Capacitor;
|
||||
use nulib\db\CapacitorStorage;
|
||||
use nulib\db\sqlite\SqliteStorage;
|
||||
|
||||
class cache {
|
||||
protected static ?CapacitorStorage $storage = null;
|
||||
|
||||
static function set_storage(CapacitorStorage $storage): CapacitorStorage {
|
||||
return self::$storage = $storage;
|
||||
}
|
||||
|
||||
protected static function get_storage(): CapacitorStorage {
|
||||
return self::$storage ??= new SqliteStorage("");
|
||||
}
|
||||
|
||||
protected static ?CacheChannel $channel = null;
|
||||
|
||||
static function set(?CacheChannel $channel): CacheChannel {
|
||||
$channel ??= new CacheChannel();
|
||||
new Capacitor(self::get_storage(), $channel);
|
||||
return self::$channel = $channel;
|
||||
}
|
||||
|
||||
static function get(): CacheChannel {
|
||||
if (self::$channel !== null) return self::$channel;
|
||||
else return self::set(null);
|
||||
}
|
||||
|
||||
static function new(?RowsChannel $channel, $id=null, ?callable $builder=null): RowsChannel {
|
||||
$channel ??= new RowsChannel($id, $builder);
|
||||
new Capacitor(self::get_storage(), $channel);
|
||||
return $channel;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user