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