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