- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
343 lines
13 KiB
PHP
343 lines
13 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\Cache\SmartCache;
|
|
use App\Framework\Cache\Strategies\CacheStrategyManager;
|
|
use App\Framework\Cache\Strategies\AdaptiveTtlCacheStrategy;
|
|
use App\Framework\Cache\Strategies\HeatMapCacheStrategy;
|
|
use App\Framework\Cache\Strategies\PredictiveCacheStrategy;
|
|
use App\Framework\Cache\CacheKey;
|
|
use App\Framework\Cache\CacheItem;
|
|
use App\Framework\Cache\CacheResult;
|
|
use App\Framework\Core\ValueObjects\Duration;
|
|
use App\Framework\Core\ValueObjects\Timestamp;
|
|
|
|
echo "=== Testing Strategy Pattern Advanced Caching ===\n\n";
|
|
|
|
// Create mock inner cache
|
|
$mockCache = new class implements \App\Framework\Cache\Cache {
|
|
private array $storage = [];
|
|
|
|
public function get(\App\Framework\Cache\CacheIdentifier ...$identifiers): \App\Framework\Cache\CacheResult
|
|
{
|
|
$items = [];
|
|
foreach ($identifiers as $identifier) {
|
|
$key = $identifier->toString();
|
|
if (isset($this->storage[$key])) {
|
|
$items[] = \App\Framework\Cache\CacheItem::hit($identifier, $this->storage[$key]['value']);
|
|
} else {
|
|
$items[] = \App\Framework\Cache\CacheItem::miss($identifier);
|
|
}
|
|
}
|
|
return \App\Framework\Cache\CacheResult::fromItems(...$items);
|
|
}
|
|
|
|
public function set(\App\Framework\Cache\CacheItem ...$items): bool
|
|
{
|
|
foreach ($items as $item) {
|
|
$this->storage[$item->key->toString()] = [
|
|
'value' => $item->value,
|
|
'ttl' => $item->ttl,
|
|
'set_at' => time()
|
|
];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function has(\App\Framework\Cache\CacheIdentifier ...$identifiers): array
|
|
{
|
|
$results = [];
|
|
foreach ($identifiers as $identifier) {
|
|
$results[$identifier->toString()] = isset($this->storage[$identifier->toString()]);
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
public function forget(\App\Framework\Cache\CacheIdentifier ...$identifiers): bool
|
|
{
|
|
foreach ($identifiers as $identifier) {
|
|
unset($this->storage[$identifier->toString()]);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function clear(): bool
|
|
{
|
|
$this->storage = [];
|
|
return true;
|
|
}
|
|
|
|
public function remember(\App\Framework\Cache\CacheKey $key, callable $callback, ?\App\Framework\Core\ValueObjects\Duration $ttl = null): \App\Framework\Cache\CacheItem
|
|
{
|
|
$result = $this->get($key);
|
|
$item = $result->getItem($key);
|
|
if ($item->isHit) {
|
|
return $item;
|
|
}
|
|
|
|
$value = $callback();
|
|
$this->set(\App\Framework\Cache\CacheItem::forSet($key, $value, $ttl));
|
|
return \App\Framework\Cache\CacheItem::hit($key, $value);
|
|
}
|
|
};
|
|
|
|
echo "1. Testing Individual Strategies:\n\n";
|
|
|
|
try {
|
|
// Test AdaptiveTtlCacheStrategy
|
|
echo " 🔧 Testing AdaptiveTtlCacheStrategy:\n";
|
|
$adaptiveStrategy = new AdaptiveTtlCacheStrategy();
|
|
|
|
$testKey = CacheKey::fromString('adaptive_test_key');
|
|
|
|
// Simulate access pattern
|
|
for ($i = 0; $i < 15; $i++) {
|
|
$adaptiveStrategy->onCacheAccess($testKey, true, Duration::fromMilliseconds(10 + rand(0, 20)));
|
|
usleep(50000); // 0.05 second delay
|
|
}
|
|
|
|
$originalTtl = Duration::fromHours(1);
|
|
$adaptedTtl = $adaptiveStrategy->onCacheSet($testKey, "test_value", $originalTtl);
|
|
|
|
echo " ✅ Original TTL: {$originalTtl->toSeconds()}s\n";
|
|
echo " ✅ Adapted TTL: {$adaptedTtl->toSeconds()}s\n";
|
|
|
|
$stats = $adaptiveStrategy->getStats();
|
|
echo " 📊 Tracked keys: {$stats['total_tracked_keys']}\n";
|
|
echo " 📊 Strategy: {$stats['strategy']}\n\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing AdaptiveTtlCacheStrategy: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
try {
|
|
// Test HeatMapCacheStrategy
|
|
echo " 🌡️ Testing HeatMapCacheStrategy:\n";
|
|
$heatMapStrategy = new HeatMapCacheStrategy();
|
|
|
|
$hotKey = CacheKey::fromString('hot_cache_key');
|
|
$coldKey = CacheKey::fromString('cold_cache_key');
|
|
|
|
// Hot key - many accesses
|
|
for ($i = 0; $i < 30; $i++) {
|
|
$heatMapStrategy->onCacheAccess($hotKey, true, Duration::fromMilliseconds(5 + rand(0, 10)));
|
|
usleep(10000);
|
|
}
|
|
|
|
// Cold key - few accesses
|
|
for ($i = 0; $i < 2; $i++) {
|
|
$heatMapStrategy->onCacheAccess($coldKey, true, Duration::fromMilliseconds(50 + rand(0, 30)));
|
|
usleep(100000);
|
|
}
|
|
|
|
$stats = $heatMapStrategy->getStats();
|
|
echo " ✅ Total tracked keys: {$stats['total_tracked_keys']}\n";
|
|
echo " ✅ Strategy: {$stats['strategy']}\n";
|
|
|
|
$analysis = $stats['analysis'];
|
|
echo " 🔥 Hot keys found: " . count($analysis['hot_keys']) . "\n";
|
|
echo " 🧊 Cold keys found: " . count($analysis['cold_keys']) . "\n";
|
|
echo " ⚠️ Performance insights: " . count($analysis['performance_insights']) . "\n\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing HeatMapCacheStrategy: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
try {
|
|
// Test PredictiveCacheStrategy
|
|
echo " 🔮 Testing PredictiveCacheStrategy:\n";
|
|
$predictiveStrategy = new PredictiveCacheStrategy();
|
|
|
|
$predictKey = CacheKey::fromString('predictive_test_key');
|
|
|
|
// Register warming callback
|
|
$predictiveStrategy->registerWarmingCallback($predictKey, function() {
|
|
return ['id' => 123, 'name' => 'Test User', 'email' => 'test@example.com'];
|
|
});
|
|
|
|
// Simulate regular access pattern
|
|
for ($i = 0; $i < 8; $i++) {
|
|
$predictiveStrategy->onCacheAccess($predictKey, true, Duration::fromMilliseconds(15 + rand(0, 25)));
|
|
usleep(30000);
|
|
}
|
|
|
|
$predictions = $predictiveStrategy->generatePredictions();
|
|
echo " ✅ Generated predictions: " . count($predictions) . "\n";
|
|
|
|
if (!empty($predictions)) {
|
|
$topPrediction = $predictions[0];
|
|
echo " 🎯 Top prediction confidence: " . round($topPrediction['confidence'], 3) . "\n";
|
|
echo " 🎯 Prediction reason: {$topPrediction['reason']}\n";
|
|
}
|
|
|
|
$stats = $predictiveStrategy->getStats();
|
|
echo " 📊 Total patterns: {$stats['total_patterns']}\n";
|
|
echo " 📊 Strategy: {$stats['strategy']}\n\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing PredictiveCacheStrategy: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "2. Testing Strategy Manager:\n\n";
|
|
|
|
try {
|
|
// Test CacheStrategyManager
|
|
echo " 🎯 Testing CacheStrategyManager:\n";
|
|
|
|
$strategyManager = new CacheStrategyManager();
|
|
$strategyManager->addStrategy(new AdaptiveTtlCacheStrategy());
|
|
$strategyManager->addStrategy(new HeatMapCacheStrategy());
|
|
$strategyManager->addStrategy(new PredictiveCacheStrategy());
|
|
|
|
echo " ✅ Strategies registered: {$strategyManager->getStrategyCount()}\n";
|
|
|
|
$testKey = CacheKey::fromString('manager_test_key');
|
|
|
|
// Test access notification
|
|
$strategyManager->notifyAccess($testKey, true, Duration::fromMilliseconds(20));
|
|
|
|
// Test set notification with TTL modification
|
|
$originalTtl = Duration::fromMinutes(30);
|
|
$finalTtl = $strategyManager->notifySet($testKey, "test_value", $originalTtl);
|
|
|
|
echo " ✅ Original TTL: {$originalTtl->toSeconds()}s\n";
|
|
echo " ✅ Final TTL after strategies: {$finalTtl->toSeconds()}s\n";
|
|
|
|
$managerStats = $strategyManager->getStats();
|
|
echo " 📊 Enabled strategies: {$managerStats['strategy_manager']['enabled_strategies']}\n";
|
|
echo " 📊 Strategy names: " . implode(', ', $managerStats['strategy_manager']['strategy_names']) . "\n\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing CacheStrategyManager: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "3. Testing SmartCache with Strategies:\n\n";
|
|
|
|
try {
|
|
// Test SmartCache with default strategies
|
|
echo " 🚀 Testing SmartCache with Default Strategies:\n";
|
|
|
|
$smartCache = SmartCache::withDefaultStrategies($mockCache);
|
|
|
|
echo " ✅ SmartCache created with strategy support\n";
|
|
|
|
$testKey = CacheKey::fromString('smart_cache_test');
|
|
|
|
// Test remember with strategy integration
|
|
$result = $smartCache->remember($testKey, function() {
|
|
return ['data' => 'Smart cache test value', 'timestamp' => time()];
|
|
}, Duration::fromMinutes(15));
|
|
|
|
echo " ✅ Cache remember successful: " . ($result->isHit ? 'Hit' : 'Miss') . "\n";
|
|
|
|
// Simulate multiple accesses to build patterns
|
|
for ($i = 0; $i < 10; $i++) {
|
|
$smartCache->get($testKey);
|
|
usleep(25000);
|
|
}
|
|
|
|
// Get comprehensive stats
|
|
$stats = $smartCache->getStats();
|
|
echo " 📊 Cache type: {$stats['cache_type']}\n";
|
|
echo " 📊 Strategy support: " . ($stats['strategy_support'] ? 'Yes' : 'No') . "\n";
|
|
|
|
if (isset($stats['strategy_stats'])) {
|
|
$strategyStats = $stats['strategy_stats'];
|
|
echo " 📊 Total strategies: {$strategyStats['strategy_manager']['total_strategies']}\n";
|
|
echo " 📊 Enabled strategies: {$strategyStats['strategy_manager']['enabled_strategies']}\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing SmartCache with strategies: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "4. Testing Performance-Focused Configuration:\n\n";
|
|
|
|
try {
|
|
// Test performance-focused strategy configuration
|
|
echo " ⚡ Testing Performance-Focused Configuration:\n";
|
|
|
|
$performanceCache = SmartCache::withPerformanceStrategies($mockCache);
|
|
|
|
$perfKey = CacheKey::fromString('performance_test_key');
|
|
|
|
// Simulate high-frequency access
|
|
for ($i = 0; $i < 20; $i++) {
|
|
$performanceCache->remember($perfKey, function() use ($i) {
|
|
return ['iteration' => $i, 'data' => str_repeat('x', 100)];
|
|
}, Duration::fromMinutes(5));
|
|
usleep(10000);
|
|
}
|
|
|
|
$adaptiveStats = $performanceCache->getStrategyStats('adaptive_ttl');
|
|
if ($adaptiveStats) {
|
|
echo " ⚡ Adaptive TTL extension factor: {$adaptiveStats['adaptation_factors']['extension_factor']}\n";
|
|
echo " ⚡ Adaptive TTL reduction factor: {$adaptiveStats['adaptation_factors']['reduction_factor']}\n";
|
|
}
|
|
|
|
$heatMapStats = $performanceCache->getStrategyStats('heat_map');
|
|
if ($heatMapStats) {
|
|
echo " 🌡️ Heat map hot threshold: {$heatMapStats['thresholds']['hot_threshold']}\n";
|
|
echo " 🌡️ Heat map max tracked keys: {$heatMapStats['max_tracked_keys']}\n";
|
|
}
|
|
|
|
echo " ✅ Performance configuration tested successfully\n\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing performance configuration: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "5. Testing Development-Focused Configuration:\n\n";
|
|
|
|
try {
|
|
// Test development-focused strategy configuration
|
|
echo " 🔧 Testing Development-Focused Configuration:\n";
|
|
|
|
$devCache = SmartCache::withDevelopmentStrategies($mockCache);
|
|
|
|
$devKey = CacheKey::fromString('development_test_key');
|
|
|
|
// Test with detailed tracking
|
|
for ($i = 0; $i < 8; $i++) {
|
|
$devCache->set(CacheItem::forSet($devKey, "dev_value_{$i}", Duration::fromMinutes(10)));
|
|
$devCache->get($devKey);
|
|
usleep(50000);
|
|
}
|
|
|
|
$devStats = $devCache->getStats();
|
|
if (isset($devStats['strategy_stats']['strategies']['heat_map'])) {
|
|
$heatStats = $devStats['strategy_stats']['strategies']['heat_map'];
|
|
echo " 🔧 Heat map analysis window: {$heatStats['thresholds']['analysis_window_hours']} hours\n";
|
|
echo " 🔧 Max tracked keys: {$heatStats['max_tracked_keys']}\n";
|
|
}
|
|
|
|
if (isset($devStats['strategy_stats']['strategies']['predictive'])) {
|
|
$predictStats = $devStats['strategy_stats']['strategies']['predictive'];
|
|
echo " 🔮 Prediction window: {$predictStats['prediction_window_hours']} hours\n";
|
|
echo " 🔮 Confidence threshold: {$predictStats['confidence_threshold']}\n";
|
|
}
|
|
|
|
echo " ✅ Development configuration tested successfully\n\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing development configuration: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "=== Strategy Pattern Advanced Caching Test Completed ===\n";
|
|
echo "\n🎯 Summary of Strategy Pattern Implementation:\n";
|
|
echo " 1. ✅ Individual strategies work independently\n";
|
|
echo " 2. ✅ CacheStrategyManager orchestrates multiple strategies\n";
|
|
echo " 3. ✅ SmartCache integrates strategies seamlessly\n";
|
|
echo " 4. ✅ Pre-configured strategy sets (Default, Performance, Development)\n";
|
|
echo " 5. ✅ Composable and modular strategy system\n";
|
|
echo "\n💡 The Strategy Pattern provides:\n";
|
|
echo " • Modular cache optimization strategies\n";
|
|
echo " • Composable cache intelligence\n";
|
|
echo " • Configurable strategy combinations\n";
|
|
echo " • Separation of concerns for cache behavior\n";
|
|
echo " • Easy testing and extensibility\n"; |