fix(Docker): change ENV arg from 'prod' to 'production' to match actual ini filename
This commit is contained in:
58
src/Framework/Cache/Strategies/AccessPattern.php
Normal file
58
src/Framework/Cache/Strategies/AccessPattern.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\Cache\Strategies;
|
||||
|
||||
/**
|
||||
* Access pattern tracking for adaptive TTL calculation
|
||||
*/
|
||||
final class AccessPattern
|
||||
{
|
||||
/** @var array<int, Timestamp> */
|
||||
private array $accessTimes = [];
|
||||
|
||||
public function __construct(
|
||||
private readonly int $windowSize
|
||||
) {}
|
||||
|
||||
public function recordAccess(): void
|
||||
{
|
||||
$this->accessTimes[] = Timestamp::now();
|
||||
|
||||
// Keep only recent accesses within the window
|
||||
if (count($this->accessTimes) > $this->windowSize) {
|
||||
array_shift($this->accessTimes);
|
||||
}
|
||||
}
|
||||
|
||||
public function getRecentAccessCount(): int
|
||||
{
|
||||
return count($this->accessTimes);
|
||||
}
|
||||
|
||||
public function getTotalAccesses(): int
|
||||
{
|
||||
return count($this->accessTimes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate access frequency (accesses per hour)
|
||||
*/
|
||||
public function getAccessFrequency(): float
|
||||
{
|
||||
if (count($this->accessTimes) < 2) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
$oldest = $this->accessTimes[0];
|
||||
$newest = end($this->accessTimes);
|
||||
$timeSpan = $newest->diff($oldest);
|
||||
|
||||
if ($timeSpan->toSeconds() <= 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
$hours = $timeSpan->toSeconds() / 3600.0;
|
||||
|
||||
return count($this->accessTimes) / $hours;
|
||||
}
|
||||
}
|
||||
44
src/Framework/Cache/Strategies/AdaptiveTtlStats.php
Normal file
44
src/Framework/Cache/Strategies/AdaptiveTtlStats.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\Cache\Strategies;
|
||||
|
||||
/**
|
||||
* Statistics for adaptive TTL optimization
|
||||
*/
|
||||
final class AdaptiveTtlStats
|
||||
{
|
||||
private int $hits = 0;
|
||||
|
||||
private int $misses = 0;
|
||||
|
||||
public function recordHitMiss(bool $isHit): void
|
||||
{
|
||||
if ($isHit) {
|
||||
$this->hits++;
|
||||
} else {
|
||||
$this->misses++;
|
||||
}
|
||||
}
|
||||
|
||||
public function getHitRate(): float
|
||||
{
|
||||
$total = $this->hits + $this->misses;
|
||||
|
||||
return $total > 0 ? ($this->hits / $total) : 0.0;
|
||||
}
|
||||
|
||||
public function getTotalRequests(): int
|
||||
{
|
||||
return $this->hits + $this->misses;
|
||||
}
|
||||
|
||||
public function getHits(): int
|
||||
{
|
||||
return $this->hits;
|
||||
}
|
||||
|
||||
public function getMisses(): int
|
||||
{
|
||||
return $this->misses;
|
||||
}
|
||||
}
|
||||
90
src/Framework/Cache/Strategies/HeatMapEntry.php
Normal file
90
src/Framework/Cache/Strategies/HeatMapEntry.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\Cache\Strategies;
|
||||
|
||||
/**
|
||||
* Heat map entry for tracking cache key usage
|
||||
*/
|
||||
final class HeatMapEntry
|
||||
{
|
||||
/** @var array<array{timestamp: Timestamp, is_hit: bool, retrieval_time: ?float}> */
|
||||
private array $accesses = [];
|
||||
|
||||
private int $totalHits = 0;
|
||||
|
||||
private int $totalMisses = 0;
|
||||
|
||||
private float $totalRetrievalTime = 0.0;
|
||||
|
||||
private int $retrievalTimeCount = 0;
|
||||
|
||||
public function __construct(
|
||||
private readonly CacheKey $key
|
||||
) {}
|
||||
|
||||
public function recordAccess(bool $isHit, ?Duration $retrievalTime = null): void
|
||||
{
|
||||
$this->accesses[] = [
|
||||
'timestamp' => Timestamp::now(),
|
||||
'is_hit' => $isHit,
|
||||
'retrieval_time' => $retrievalTime?->toSeconds(),
|
||||
];
|
||||
|
||||
if ($isHit) {
|
||||
$this->totalHits++;
|
||||
} else {
|
||||
$this->totalMisses++;
|
||||
}
|
||||
|
||||
if ($retrievalTime !== null) {
|
||||
$this->totalRetrievalTime += $retrievalTime->toSeconds();
|
||||
$this->retrievalTimeCount++;
|
||||
}
|
||||
|
||||
// Keep only recent data to prevent memory bloat
|
||||
$cutoff = Timestamp::now()->subtract(Duration::fromHours(48)); // Keep 48 hours
|
||||
$this->accesses = array_filter(
|
||||
$this->accesses,
|
||||
fn($access) => $access['timestamp']->isAfter($cutoff)
|
||||
);
|
||||
}
|
||||
|
||||
public function getRecentAccesses(Timestamp $since): array
|
||||
{
|
||||
return array_filter(
|
||||
$this->accesses,
|
||||
fn($access) => $access['timestamp']->isAfter($since)
|
||||
);
|
||||
}
|
||||
|
||||
public function getHitRate(): float
|
||||
{
|
||||
$total = $this->totalHits + $this->totalMisses;
|
||||
|
||||
return $total > 0 ? ($this->totalHits / $total) : 0.0;
|
||||
}
|
||||
|
||||
public function getAverageRetrievalTime(): float
|
||||
{
|
||||
return $this->retrievalTimeCount > 0 ? ($this->totalRetrievalTime / $this->retrievalTimeCount) : 0.0;
|
||||
}
|
||||
|
||||
public function getTotalAccesses(): int
|
||||
{
|
||||
return count($this->accesses);
|
||||
}
|
||||
|
||||
public function getLastAccessTime(): ?Timestamp
|
||||
{
|
||||
if (empty($this->accesses)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return end($this->accesses)['timestamp'];
|
||||
}
|
||||
|
||||
public function getKey(): CacheKey
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
}
|
||||
71
src/Framework/Cache/Strategies/PredictionPattern.php
Normal file
71
src/Framework/Cache/Strategies/PredictionPattern.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\Cache\Strategies;
|
||||
|
||||
/**
|
||||
* Prediction pattern for a cache key
|
||||
*/
|
||||
final class PredictionPattern
|
||||
{
|
||||
/** @var array<array{timestamp: Timestamp, context: array}> */
|
||||
private array $accesses = [];
|
||||
|
||||
/** @var array<CacheKey> */
|
||||
private array $dependencies = [];
|
||||
|
||||
private mixed $warmingCallback = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly CacheKey $key
|
||||
) {}
|
||||
|
||||
public function recordAccess(Timestamp $timestamp, array $context = []): void
|
||||
{
|
||||
$this->accesses[] = [
|
||||
'timestamp' => $timestamp,
|
||||
'context' => $context,
|
||||
];
|
||||
|
||||
// Keep only recent accesses to prevent memory bloat
|
||||
$cutoff = $timestamp->subtract(Duration::fromHours(168)); // 1 week
|
||||
$this->accesses = array_filter(
|
||||
$this->accesses,
|
||||
fn($access) => $access['timestamp']->isAfter($cutoff)
|
||||
);
|
||||
}
|
||||
|
||||
public function addDependency(CacheKey $dependentKey): void
|
||||
{
|
||||
$this->dependencies[] = $dependentKey;
|
||||
}
|
||||
|
||||
public function setWarmingCallback(callable $callback): void
|
||||
{
|
||||
$this->warmingCallback = $callback;
|
||||
}
|
||||
|
||||
public function getKey(): CacheKey
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function getRecentAccesses(int $hours): array
|
||||
{
|
||||
$cutoff = Timestamp::now()->subtract(Duration::fromHours($hours));
|
||||
|
||||
return array_filter(
|
||||
$this->accesses,
|
||||
fn($access) => $access['timestamp']->isAfter($cutoff)
|
||||
);
|
||||
}
|
||||
|
||||
public function getDependencies(): array
|
||||
{
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
public function getWarmingCallback(): ?callable
|
||||
{
|
||||
return $this->warmingCallback;
|
||||
}
|
||||
}
|
||||
16
src/Framework/Cache/Strategies/WarmingJob.php
Normal file
16
src/Framework/Cache/Strategies/WarmingJob.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\Cache\Strategies;
|
||||
|
||||
/**
|
||||
* Active warming job
|
||||
*/
|
||||
final readonly class WarmingJob
|
||||
{
|
||||
public function __construct(
|
||||
public CacheKey $key,
|
||||
public mixed $callback,
|
||||
public string $reason,
|
||||
public Timestamp $startTime
|
||||
) {}
|
||||
}
|
||||
16
src/Framework/Cache/Strategies/WarmingResult.php
Normal file
16
src/Framework/Cache/Strategies/WarmingResult.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\Cache\Strategies;
|
||||
|
||||
/**
|
||||
* Warming operation result
|
||||
*/
|
||||
final readonly class WarmingResult
|
||||
{
|
||||
public function __construct(
|
||||
public CacheKey $key,
|
||||
public bool $successful,
|
||||
public Duration $duration,
|
||||
public string $reason
|
||||
) {}
|
||||
}
|
||||
16
src/Framework/Cache/Strategies/WriteOperation.php
Normal file
16
src/Framework/Cache/Strategies/WriteOperation.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Framework\Cache\Strategies;
|
||||
|
||||
/**
|
||||
* Write operation tracking
|
||||
*/
|
||||
final readonly class WriteOperation
|
||||
{
|
||||
public function __construct(
|
||||
public CacheKey $key,
|
||||
public int $valueSize,
|
||||
public Duration $writeTime,
|
||||
public Timestamp $timestamp
|
||||
) {}
|
||||
}
|
||||
Reference in New Issue
Block a user