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

@@ -0,0 +1,153 @@
<?php
declare(strict_types=1);
namespace Tests\Support;
use App\Framework\LiveComponents\Services\UploadProgressTrackerInterface;
use App\Framework\LiveComponents\ValueObjects\UploadSession;
use App\Framework\LiveComponents\ValueObjects\UploadSessionId;
/**
* In-Memory Upload Progress Tracker for Testing
*
* Records all broadcast events for assertion in tests.
* Does not require actual SSE infrastructure.
*/
final class InMemoryUploadProgressTracker implements UploadProgressTrackerInterface
{
/** @var array<array{type: string, session_id: string, user_id: string, data: array}> */
private array $broadcasts = [];
public function broadcastInitialized(UploadSession $session, string $userId): int
{
$this->broadcasts[] = [
'type' => 'initialized',
'session_id' => $session->sessionId->toString(),
'user_id' => $userId,
'data' => [
'file_name' => $session->fileName,
'total_size' => $session->totalSize->toBytes(),
'total_chunks' => $session->totalChunks,
],
];
return 1; // Simulated client count
}
public function broadcastChunkUploaded(UploadSession $session, string $userId): int
{
$this->broadcasts[] = [
'type' => 'chunk_uploaded',
'session_id' => $session->sessionId->toString(),
'user_id' => $userId,
'data' => [
'uploaded_chunks' => count($session->getUploadedChunks()),
'total_chunks' => $session->totalChunks,
'progress' => $session->getProgress(),
],
];
return 1;
}
public function broadcastCompleted(UploadSession $session, string $userId): int
{
$this->broadcasts[] = [
'type' => 'completed',
'session_id' => $session->sessionId->toString(),
'user_id' => $userId,
'data' => [
'file_name' => $session->fileName,
'completed_at' => $session->completedAt?->format('Y-m-d H:i:s'),
],
];
return 1;
}
public function broadcastAborted(UploadSessionId $sessionId, string $userId, string $reason = 'User cancelled'): int
{
$this->broadcasts[] = [
'type' => 'aborted',
'session_id' => $sessionId->toString(),
'user_id' => $userId,
'data' => [
'reason' => $reason,
],
];
return 1;
}
public function broadcastError(UploadSessionId $sessionId, string $userId, string $error): int
{
$this->broadcasts[] = [
'type' => 'error',
'session_id' => $sessionId->toString(),
'user_id' => $userId,
'data' => [
'error' => $error,
],
];
return 1;
}
public function broadcastQuarantineStatus(UploadSession $session, string $userId): int
{
$this->broadcasts[] = [
'type' => 'quarantine_status',
'session_id' => $session->sessionId->toString(),
'user_id' => $userId,
'data' => [
'quarantine_status' => $session->quarantineStatus->value,
],
];
return 1;
}
public function getProgress(UploadSessionId $sessionId): ?array
{
// In-memory mock doesn't track progress state
// Return null to indicate not available
return null;
}
/**
* Get all broadcast events (for testing)
*
* @return array<array{type: string, session_id: string, user_id: string, data: array}>
*/
public function getBroadcasts(): array
{
return $this->broadcasts;
}
/**
* Get broadcasts by type (for testing)
*
* @return array<array{type: string, session_id: string, user_id: string, data: array}>
*/
public function getBroadcastsByType(string $type): array
{
return array_filter($this->broadcasts, fn($b) => $b['type'] === $type);
}
/**
* Get broadcast count by type (for testing)
*/
public function getBroadcastCount(string $type): int
{
return count($this->getBroadcastsByType($type));
}
/**
* Clear all broadcasts (for testing)
*/
public function clear(): void
{
$this->broadcasts = [];
}
}