feat(Production): Complete production deployment infrastructure

- 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.
This commit is contained in:
2025-10-25 19:18:37 +02:00
parent caa85db796
commit fc3d7e6357
83016 changed files with 378904 additions and 20919 deletions

View File

@@ -5,12 +5,15 @@ declare(strict_types=1);
namespace App\Framework\Discovery\Commands;
use App\Framework\Cache\Cache;
use App\Framework\Cache\CacheKey;
use App\Framework\Console\ConsoleCommand;
use App\Framework\Console\ConsoleInput;
use App\Framework\Console\ConsoleOutput;
use App\Framework\Core\PathProvider;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\DateTime\Clock;
use App\Framework\Discovery\Storage\DiscoveryCacheManager;
use App\Framework\Filesystem\Storage;
/**
* Unified console commands for clearing discovery-related caches
@@ -27,7 +30,8 @@ final readonly class ClearDiscoveryCache
private ConsoleOutput $output,
private Cache $cache,
private Clock $clock,
private PathProvider $pathProvider
private PathProvider $pathProvider,
private Storage $fileSystem
) {
}
@@ -69,8 +73,8 @@ final readonly class ClearDiscoveryCache
}
// Clear legacy cache keys from old Core command
$this->cache->forget('discovery_service');
$this->cache->forget('unified_discovery_results');
$this->cache->forget(CacheKey::fromString('discovery_service'));
$this->cache->forget(CacheKey::fromString('unified_discovery_results'));
$this->output->writeLine('✓ Legacy discovery cache keys cleared');
// Clear routes cache
@@ -81,6 +85,10 @@ final readonly class ClearDiscoveryCache
$success = false;
}
// Clear ALL file cache entries (since we can't selectively delete by prefix due to MD5 hashing)
$deletedFiles = $this->clearAllFileCache();
$this->output->writeLine("✓ Cleared {$deletedFiles} file cache entries");
if ($success) {
$this->output->writeLine('<success>All discovery caches cleared successfully!</success>');
@@ -119,4 +127,49 @@ final readonly class ClearDiscoveryCache
return unlink($routesCachePath);
}
/**
* Clear ALL file cache entries
*
* Note: We clear all cache files because FileCache uses MD5 hashing for filenames,
* making it impossible to selectively delete by cache key prefix.
* This is necessary until we implement cache tags or a better storage mechanism.
*/
private function clearAllFileCache(): int
{
$cacheDir = $this->pathProvider->resolvePath('/storage/cache');
$deletedCount = 0;
try {
// Use DirectoryIterator for large directories (handles 80K+ files)
$iterator = new \DirectoryIterator($cacheDir);
foreach ($iterator as $fileInfo) {
if ($fileInfo->isDot() || ! $fileInfo->isFile()) {
continue;
}
$filename = $fileInfo->getFilename();
// Only delete .cache.php files (keep .lock files for now)
if (! str_ends_with($filename, '.cache.php')) {
continue;
}
try {
$this->fileSystem->delete($fileInfo->getPathname());
$deletedCount++;
} catch (\Throwable $e) {
// Continue with next file if deletion fails
continue;
}
}
} catch (\Throwable $e) {
// If directory iteration fails, return 0
return 0;
}
return $deletedCount;
}
}