- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
362 lines
13 KiB
PHP
362 lines
13 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\Cache\AdaptiveTtlCache;
|
|
use App\Framework\Cache\CacheHeatMap;
|
|
use App\Framework\Cache\CacheKey;
|
|
use App\Framework\Cache\PredictiveCacheWarming;
|
|
use App\Framework\Core\ValueObjects\Duration;
|
|
use App\Framework\Core\ValueObjects\Timestamp;
|
|
|
|
echo "=== Testing Advanced Caching Strategies ===\n\n";
|
|
|
|
echo "1. Testing Adaptive TTL Cache:\n";
|
|
|
|
try {
|
|
// 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,
|
|
];
|
|
}
|
|
|
|
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);
|
|
}
|
|
};
|
|
|
|
$adaptiveCache = new AdaptiveTtlCache(
|
|
innerCache: $mockCache,
|
|
minTtl: Duration::fromMinutes(5),
|
|
maxTtl: Duration::fromHours(6),
|
|
learningWindow: 10
|
|
);
|
|
|
|
echo " ✅ AdaptiveTtlCache created successfully\n";
|
|
|
|
// Test adaptive behavior
|
|
$testKey = CacheKey::fromString('adaptive_test_key');
|
|
|
|
// Simulate frequent access pattern
|
|
for ($i = 0; $i < 15; $i++) {
|
|
$adaptiveCache->get($testKey);
|
|
usleep(100000); // 0.1 second delay
|
|
}
|
|
|
|
// Set a value and check adaptive TTL
|
|
$originalTtl = Duration::fromHours(1);
|
|
$result = $adaptiveCache->remember($testKey, fn () => "test_value", $originalTtl);
|
|
|
|
echo " ✅ Adaptive caching with frequent access pattern tested\n";
|
|
|
|
$stats = $adaptiveCache->getAdaptiveStats();
|
|
echo " 📊 Adaptive Stats:\n";
|
|
echo " • Tracked keys: {$stats['total_tracked_keys']}\n";
|
|
echo " • Learning window: {$stats['learning_window']}\n";
|
|
echo " • TTL bounds: {$stats['ttl_bounds']['min_seconds']}s - {$stats['ttl_bounds']['max_seconds']}s\n";
|
|
|
|
if (! empty($stats['key_patterns'])) {
|
|
$pattern = reset($stats['key_patterns']);
|
|
echo " • Sample key accesses: {$pattern['total_accesses']}\n";
|
|
echo " • Access frequency: {$pattern['access_frequency']}/hour\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing AdaptiveTtlCache: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "2. Testing Cache Heat Map:\n";
|
|
|
|
try {
|
|
$heatMap = new CacheHeatMap(
|
|
maxTrackedKeys: 1000,
|
|
hotThreshold: 20, // 20 accesses per hour
|
|
coldThreshold: 1, // 1 access per hour
|
|
analysisWindowHours: 2
|
|
);
|
|
|
|
echo " ✅ CacheHeatMap created successfully\n";
|
|
|
|
// Simulate access patterns
|
|
$hotKey = CacheKey::fromString('hot_cache_key');
|
|
$coldKey = CacheKey::fromString('cold_cache_key');
|
|
$mediumKey = CacheKey::fromString('medium_cache_key');
|
|
|
|
// Hot key - many accesses
|
|
for ($i = 0; $i < 50; $i++) {
|
|
$heatMap->recordAccess($hotKey, true, Duration::fromMilliseconds(10 + rand(0, 20)));
|
|
usleep(10000); // Small delay
|
|
}
|
|
|
|
// Cold key - few accesses
|
|
for ($i = 0; $i < 3; $i++) {
|
|
$heatMap->recordAccess($coldKey, true, Duration::fromMilliseconds(50 + rand(0, 30)));
|
|
usleep(100000); // Longer delay
|
|
}
|
|
|
|
// Medium key - moderate accesses with some misses
|
|
for ($i = 0; $i < 15; $i++) {
|
|
$isHit = $i % 3 !== 0; // 1/3 miss rate
|
|
$heatMap->recordAccess($mediumKey, $isHit, Duration::fromMilliseconds(30 + rand(0, 40)));
|
|
usleep(50000);
|
|
}
|
|
|
|
// Record some write operations
|
|
$heatMap->recordWrite($hotKey, 1024, Duration::fromMilliseconds(5));
|
|
$heatMap->recordWrite($mediumKey, 2048, Duration::fromMilliseconds(8));
|
|
|
|
echo " ✅ Simulated access patterns recorded\n";
|
|
|
|
// Analyze heat map
|
|
$analysis = $heatMap->getHeatMapAnalysis();
|
|
|
|
echo " 📊 Heat Map Analysis:\n";
|
|
echo " • Total tracked keys: {$analysis['total_tracked_keys']}\n";
|
|
echo " • Hot keys found: " . count($analysis['hot_keys']) . "\n";
|
|
echo " • Cold keys found: " . count($analysis['cold_keys']) . "\n";
|
|
echo " • Performance issues: " . count($analysis['performance_insights']) . "\n";
|
|
|
|
if (! empty($analysis['hot_keys'])) {
|
|
$hotKeyData = $analysis['hot_keys'][0];
|
|
echo " • Top hot key: {$hotKeyData['key']}\n";
|
|
echo " - Accesses/hour: {$hotKeyData['accesses_per_hour']}\n";
|
|
echo " - Hit rate: {$hotKeyData['hit_rate']}\n";
|
|
echo " - Avg retrieval: {$hotKeyData['avg_retrieval_time_ms']}ms\n";
|
|
}
|
|
|
|
// Get performance bottlenecks
|
|
$bottlenecks = $heatMap->getPerformanceBottlenecks();
|
|
if (! empty($bottlenecks)) {
|
|
echo " • Performance bottlenecks detected: " . count($bottlenecks) . "\n";
|
|
$topBottleneck = $bottlenecks[0];
|
|
echo " - Type: {$topBottleneck['type']}\n";
|
|
echo " - Impact score: " . round($topBottleneck['impact_score'], 2) . "\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing CacheHeatMap: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "3. Testing Predictive Cache Warming:\n";
|
|
|
|
try {
|
|
// Use the same mock cache from earlier
|
|
$predictiveWarming = new PredictiveCacheWarming(
|
|
cache: $mockCache,
|
|
predictionWindowHours: 1,
|
|
confidenceThreshold: 0.5,
|
|
maxConcurrentWarming: 3
|
|
);
|
|
|
|
echo " ✅ PredictiveCacheWarming created successfully\n";
|
|
|
|
// Create test keys and patterns
|
|
$userDataKey = CacheKey::fromString('user_data_123');
|
|
$userPrefsKey = CacheKey::fromString('user_preferences_123');
|
|
$dashboardKey = CacheKey::fromString('dashboard_data');
|
|
|
|
// Register warming callbacks
|
|
$predictiveWarming->registerWarmingCallback($userDataKey, function () {
|
|
return ['id' => 123, 'name' => 'John Doe', 'email' => 'john@example.com'];
|
|
});
|
|
|
|
$predictiveWarming->registerWarmingCallback($userPrefsKey, function () {
|
|
return ['theme' => 'dark', 'language' => 'en', 'notifications' => true];
|
|
});
|
|
|
|
$predictiveWarming->registerWarmingCallback($dashboardKey, function () {
|
|
return ['stats' => ['views' => 1250, 'clicks' => 89], 'updated' => time()];
|
|
});
|
|
|
|
echo " ✅ Warming callbacks registered\n";
|
|
|
|
// Simulate access patterns to build predictions
|
|
$baseTime = Timestamp::now()->subtract(Duration::fromHours(2));
|
|
|
|
// Simulate regular morning access pattern for user data
|
|
for ($i = 0; $i < 5; $i++) {
|
|
$accessTime = $baseTime->add(Duration::fromMinutes($i * 15));
|
|
$predictiveWarming->recordAccess($userDataKey, ['time_of_day' => 'morning', 'user_agent' => 'web']);
|
|
}
|
|
|
|
// Simulate dependency: when user data is accessed, preferences are often needed
|
|
$predictiveWarming->recordDependency($userDataKey, $userPrefsKey);
|
|
|
|
// Dashboard accessed less frequently but regularly
|
|
for ($i = 0; $i < 3; $i++) {
|
|
$accessTime = $baseTime->add(Duration::fromHours($i));
|
|
$predictiveWarming->recordAccess($dashboardKey, ['page' => 'dashboard']);
|
|
}
|
|
|
|
echo " ✅ Access patterns recorded for prediction\n";
|
|
|
|
// Generate predictions
|
|
$predictions = $predictiveWarming->generatePredictions();
|
|
|
|
echo " 🔮 Generated Predictions:\n";
|
|
foreach (array_slice($predictions, 0, 5) as $prediction) {
|
|
$keyString = $prediction['key']->toString();
|
|
$confidence = round($prediction['confidence'], 3);
|
|
echo " • Key: {$keyString}\n";
|
|
echo " - Confidence: {$confidence}\n";
|
|
echo " - Reason: {$prediction['reason']}\n";
|
|
echo " - Predicted access: {$prediction['predicted_access_time']->format('H:i:s')}\n";
|
|
}
|
|
|
|
// Perform predictive warming
|
|
$warmingResults = $predictiveWarming->performPredictiveWarming();
|
|
|
|
echo " 🔥 Warming Results:\n";
|
|
foreach ($warmingResults as $result) {
|
|
echo " • Key: {$result['key']}\n";
|
|
echo " - Status: {$result['status']}\n";
|
|
echo " - Reason: {$result['reason']}\n";
|
|
if (isset($result['duration_ms'])) {
|
|
echo " - Duration: {$result['duration_ms']}ms\n";
|
|
}
|
|
}
|
|
|
|
// Get warming statistics
|
|
$stats = $predictiveWarming->getWarmingStats();
|
|
echo " 📊 Warming Statistics:\n";
|
|
echo " • Total patterns: {$stats['total_patterns']}\n";
|
|
echo " • Active warming jobs: {$stats['active_warming_jobs']}\n";
|
|
echo " • Completed operations: {$stats['completed_warming_operations']}\n";
|
|
echo " • Success rate: " . round($stats['warming_success_rate'] * 100, 1) . "%\n";
|
|
echo " • Avg warming time: {$stats['avg_warming_time_ms']}ms\n";
|
|
|
|
echo "\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error testing PredictiveCacheWarming: {$e->getMessage()}\n\n";
|
|
}
|
|
|
|
echo "4. Testing Integration Scenarios:\n";
|
|
|
|
try {
|
|
// Test combining multiple advanced strategies
|
|
echo " 🔗 Testing strategy integration:\n";
|
|
|
|
// Adaptive TTL with Heat Map monitoring
|
|
$combinedKey = CacheKey::fromString('integrated_test_key');
|
|
|
|
// Simulate high-frequency access that should trigger adaptive TTL extension
|
|
for ($i = 0; $i < 25; $i++) {
|
|
$adaptiveCache->get($combinedKey);
|
|
$heatMap->recordAccess($combinedKey, true, Duration::fromMilliseconds(15 + rand(0, 10)));
|
|
usleep(50000);
|
|
}
|
|
|
|
// Set value with adaptive cache
|
|
$adaptiveCache->remember($combinedKey, fn () => "integrated_value", Duration::fromMinutes(30));
|
|
|
|
// Record as predictive pattern
|
|
$predictiveWarming->recordAccess($combinedKey, ['integration_test' => true]);
|
|
|
|
echo " ✅ High-frequency access pattern simulated\n";
|
|
|
|
// Check heat map classification
|
|
$hotKeys = $heatMap->getHotKeys(5);
|
|
$isHot = array_key_exists($combinedKey->toString(), $hotKeys);
|
|
|
|
echo " • Key classified as hot: " . ($isHot ? 'Yes' : 'No') . "\n";
|
|
|
|
if ($isHot) {
|
|
echo " • Access frequency: " . round($hotKeys[$combinedKey->toString()], 2) . " per hour\n";
|
|
}
|
|
|
|
// Generate prediction for the key
|
|
$predictions = $predictiveWarming->generatePredictions();
|
|
$keyPredictions = array_filter($predictions, fn ($p) => $p['key']->toString() === $combinedKey->toString());
|
|
|
|
if (! empty($keyPredictions)) {
|
|
$prediction = reset($keyPredictions);
|
|
echo " • Prediction confidence: " . round($prediction['confidence'], 3) . "\n";
|
|
echo " • Prediction reason: {$prediction['reason']}\n";
|
|
}
|
|
|
|
echo " ✅ Integration scenario completed successfully\n";
|
|
|
|
} catch (\Throwable $e) {
|
|
echo " ❌ Error in integration testing: {$e->getMessage()}\n";
|
|
}
|
|
|
|
echo "\n=== Advanced Caching Strategies Test Completed ===\n";
|
|
echo "\n📈 Summary of Advanced Strategies:\n";
|
|
echo " 1. ✅ Adaptive TTL Cache - Dynamic TTL based on access patterns\n";
|
|
echo " 2. ✅ Cache Heat Map - Usage pattern analysis and optimization\n";
|
|
echo " 3. ✅ Predictive Cache Warming - ML-based preloading strategies\n";
|
|
echo " 4. ✅ Strategy Integration - Combined approach for maximum efficiency\n";
|
|
echo "\n💡 These strategies enhance the existing comprehensive cache system with:\n";
|
|
echo " • Intelligent TTL adaptation\n";
|
|
echo " • Real-time performance monitoring\n";
|
|
echo " • Proactive cache population\n";
|
|
echo " • Data-driven optimization recommendations\n";
|