124 lines
4.3 KiB
PHP
124 lines
4.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\Cache\Cache;
|
|
use App\Framework\Cache\CacheKey;
|
|
use App\Framework\Cache\CacheItem;
|
|
use App\Framework\Cache\Driver\InMemoryCache;
|
|
use App\Framework\Cache\GeneralCache;
|
|
use App\Framework\Serializer\Php\PhpSerializer;
|
|
use App\Framework\Cache\Warming\Strategies\PredictiveWarmingStrategy;
|
|
use App\Framework\Cache\Warming\ValueObjects\WarmupPriority;
|
|
use App\Framework\Core\ValueObjects\Duration;
|
|
|
|
describe('PredictiveWarmingStrategy', function () {
|
|
beforeEach(function () {
|
|
// Use real cache instead of mocks
|
|
$inMemoryCache = new InMemoryCache();
|
|
$serializer = new PhpSerializer();
|
|
$this->cache = new GeneralCache($inMemoryCache, $serializer);
|
|
});
|
|
|
|
it('has correct name', function () {
|
|
$strategy = new PredictiveWarmingStrategy($this->cache);
|
|
|
|
expect($strategy->getName())->toBe('predictive');
|
|
});
|
|
|
|
it('has background priority', function () {
|
|
$strategy = new PredictiveWarmingStrategy($this->cache);
|
|
|
|
expect($strategy->getPriority())->toBe(WarmupPriority::BACKGROUND->value);
|
|
});
|
|
|
|
it('should not run without sufficient access patterns', function () {
|
|
// No access patterns in cache (cache miss)
|
|
$strategy = new PredictiveWarmingStrategy($this->cache);
|
|
|
|
expect($strategy->shouldRun())->toBeFalse();
|
|
});
|
|
|
|
it('should run with sufficient access patterns', function () {
|
|
// Set up access patterns in cache (10+ patterns)
|
|
$accessPatterns = [];
|
|
for ($i = 0; $i < 15; $i++) {
|
|
$accessPatterns["pattern_{$i}"] = [
|
|
'access_count' => 10 + $i,
|
|
'hourly_distribution' => array_fill(0, 24, 0.04),
|
|
'daily_distribution' => array_fill(0, 7, 0.14),
|
|
];
|
|
}
|
|
|
|
// Store in cache with the key that PredictiveWarmingStrategy uses
|
|
$key = CacheKey::fromString('warmup_access_patterns');
|
|
$this->cache->set(CacheItem::forSet($key, $accessPatterns, Duration::fromHours(1)));
|
|
|
|
$strategy = new PredictiveWarmingStrategy($this->cache);
|
|
|
|
expect($strategy->shouldRun())->toBeTrue();
|
|
});
|
|
|
|
it('estimates reasonable duration', function () {
|
|
$strategy = new PredictiveWarmingStrategy($this->cache);
|
|
|
|
$duration = $strategy->getEstimatedDuration();
|
|
|
|
expect($duration)->toBeGreaterThan(0);
|
|
expect($duration)->toBeLessThan(300); // Should be < 5 minutes
|
|
});
|
|
|
|
it('warms predicted cache keys', function () {
|
|
// Set up access patterns with high probability
|
|
$currentHour = (int) date('G');
|
|
$currentDay = (int) date('N') - 1;
|
|
|
|
$accessPatterns = [
|
|
'key1' => [
|
|
'access_count' => 50,
|
|
'hourly_distribution' => array_fill(0, 24, 0.04),
|
|
'daily_distribution' => array_fill(0, 7, 0.14),
|
|
],
|
|
'key2' => [
|
|
'access_count' => 30,
|
|
'hourly_distribution' => array_fill(0, 24, 0.04),
|
|
'daily_distribution' => array_fill(0, 7, 0.14),
|
|
],
|
|
];
|
|
|
|
// Boost current hour/day to ensure high probability
|
|
$accessPatterns['key1']['hourly_distribution'][$currentHour] = 0.5;
|
|
$accessPatterns['key1']['daily_distribution'][$currentDay] = 0.5;
|
|
|
|
// Store access patterns in cache
|
|
$key = CacheKey::fromString('warmup_access_patterns');
|
|
$this->cache->set(CacheItem::forSet($key, $accessPatterns));
|
|
|
|
$strategy = new PredictiveWarmingStrategy($this->cache);
|
|
$result = $strategy->warmup();
|
|
|
|
// Result should complete without errors
|
|
expect($result->itemsFailed)->toBe(0);
|
|
});
|
|
|
|
it('skips low probability keys', function () {
|
|
$accessPatterns = [
|
|
'low_prob_key' => [
|
|
'access_count' => 2, // Below MIN_ACCESS_COUNT
|
|
'hourly_distribution' => array_fill(0, 24, 0.01),
|
|
'daily_distribution' => array_fill(0, 7, 0.01),
|
|
],
|
|
];
|
|
|
|
// Store low probability access patterns in cache
|
|
$key = CacheKey::fromString('warmup_access_patterns');
|
|
$this->cache->set(CacheItem::forSet($key, $accessPatterns));
|
|
|
|
$strategy = new PredictiveWarmingStrategy($this->cache);
|
|
$result = $strategy->warmup();
|
|
|
|
// No items warmed due to low probability
|
|
expect($result->itemsWarmed)->toBe(0);
|
|
});
|
|
});
|