fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled

- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
2025-11-09 14:46:15 +01:00
parent 85c369e846
commit 36ef2a1e2c
1366 changed files with 104925 additions and 28719 deletions

View File

@@ -0,0 +1,183 @@
<?php
declare(strict_types=1);
namespace App\Framework\ExceptionHandling\Middleware;
use App\Framework\ExceptionHandling\Scope\ErrorScope;
use App\Framework\ExceptionHandling\Scope\ErrorScopeContext;
use App\Framework\Http\HttpMiddleware;
use App\Framework\Http\MiddlewareContext;
use App\Framework\Http\MiddlewarePriority;
use App\Framework\Http\MiddlewarePriorityAttribute;
use App\Framework\Http\Next;
use App\Framework\Http\RequestStateManager;
/**
* Error Scope Middleware
*
* Automatically creates ErrorScope for HTTP requests to enable automatic
* context enrichment for all exceptions thrown during request processing.
*
* Uses Value Objects (IpAddress, UserAgent, SessionId) where possible.
* Scope is automatically cleaned up after request processing.
*/
#[MiddlewarePriorityAttribute(MiddlewarePriority::VERY_EARLY)]
final readonly class ErrorScopeMiddleware implements HttpMiddleware
{
public function __construct(
private ErrorScope $errorScope
) {
}
public function __invoke(MiddlewareContext $context, Next $next, RequestStateManager $stateManager): MiddlewareContext
{
// Create HTTP scope from request
$scopeContext = $this->createHttpScope($context->request);
// Enter scope (returns token for cleanup)
$token = $this->errorScope->enter($scopeContext);
try {
// Process request through middleware chain
$result = $next($context);
// Update scope with any additional context that became available
// (e.g., user ID after authentication, route after routing)
$this->updateScopeFromContext($scopeContext, $context, $stateManager);
return $result;
} finally {
// Always exit scope, even if exception occurred
$this->errorScope->exit($token);
}
}
/**
* Create HTTP scope context from request
*
* Uses Value Objects where possible for type safety and validation.
*/
private function createHttpScope(\App\Framework\Http\Request $request): ErrorScopeContext
{
// Extract request ID (as string, since RequestId Value Object needs secret)
$requestIdString = $request->id->toString();
// Extract IP address (as string, will be converted to Value Object in enrichContext)
$ipAddressString = $request->server->getRemoteAddr()?->value ?? null;
// Extract user agent (as string, will be converted to Value Object in enrichContext)
$userAgentString = $request->server->getUserAgent()?->value ?? null;
// Extract session ID (will be available after SessionMiddleware)
$sessionId = null;
if (property_exists($request, 'session') && $request->session !== null) {
$sessionId = $request->session->id->toString();
}
// Create scope context with metadata for later Value Object conversion
return ErrorScopeContext::http(
request: $request,
operation: null, // Will be set by routing/controller
component: null // Will be set by routing/controller
)->addMetadata([
'ip' => $ipAddressString,
'user_agent' => $userAgentString,
'request_id' => $requestIdString,
'session_id' => $sessionId,
]);
}
/**
* Update scope with additional context that became available during request processing
*
* E.g., user ID after authentication, route after routing
*/
private function updateScopeFromContext(
ErrorScopeContext $scopeContext,
MiddlewareContext $context,
RequestStateManager $stateManager
): void {
// Get current scope (should be the one we just created)
$currentScope = $this->errorScope->current();
if ($currentScope === null || $currentScope->scopeId !== $scopeContext->scopeId) {
return; // Scope changed or not found
}
// Check if user ID became available (after authentication)
$userId = $this->extractUserId($context, $stateManager);
if ($userId !== null && $currentScope->userId === null) {
// Create updated scope with user ID
$updatedScope = $currentScope->withUserId($userId);
// Replace current scope (exit and re-enter)
$this->errorScope->exit();
$this->errorScope->enter($updatedScope);
}
// Check if route information became available (after routing)
$route = $this->extractRouteInfo($context);
if ($route !== null && $currentScope->operation === null) {
$operation = "http.{$route['method']}.{$route['path']}";
$updatedScope = $currentScope->withOperation($operation, $route['controller'] ?? null);
$this->errorScope->exit();
$this->errorScope->enter($updatedScope);
}
}
/**
* Extract user ID from context or state manager
*/
private function extractUserId(MiddlewareContext $context, RequestStateManager $stateManager): ?string
{
// Try to get from request attribute (set by auth middleware)
if (method_exists($context->request, 'getAttribute')) {
$user = $context->request->getAttribute('user');
if ($user !== null && (is_object($user) && property_exists($user, 'id'))) {
return (string) $user->id;
}
if (is_string($user)) {
return $user;
}
}
// Try to get from state manager
try {
$user = $stateManager->get('user');
if ($user !== null && (is_object($user) && property_exists($user, 'id'))) {
return (string) $user->id;
}
} catch (\Throwable) {
// Ignore - user not available
}
return null;
}
/**
* Extract route information from context
*/
private function extractRouteInfo(MiddlewareContext $context): ?array
{
$request = $context->request;
// Try to get route from request attribute
if (method_exists($request, 'getAttribute')) {
$route = $request->getAttribute('route');
if ($route !== null) {
return [
'method' => $request->method->value,
'path' => $request->path,
'controller' => is_object($route) ? get_class($route) : null,
];
}
}
// Fallback: use request method and path
return [
'method' => $request->method->value,
'path' => $request->path,
'controller' => null,
];
}
}