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

@@ -20,6 +20,9 @@ import { ComponentFileUploader } from './ComponentFileUploader.js';
import { FileUploadWidget } from './FileUploadWidget.js';
import { optimisticStateManager } from './OptimisticStateManager.js';
import { accessibilityManager } from './AccessibilityManager.js';
import { ErrorBoundary } from './ErrorBoundary.js';
import { RequestDeduplicator } from './RequestDeduplicator.js';
import * as StateSerializer from './StateSerializer.js';
class LiveComponentManager {
constructor() {
@@ -42,6 +45,30 @@ class LiveComponentManager {
// DevTools Integration
this.devTools = null; // Will be set by DevTools when available
// Error Handling
this.errorBoundary = new ErrorBoundary(this);
// Request Deduplication
this.requestDeduplicator = new RequestDeduplicator();
// Shared Configuration
this.config = sharedConfig;
// Tooltip Manager
this.tooltipManager = tooltipManager;
// Action Loading Manager
this.actionLoadingManager = actionLoadingManager;
// UI Helper
this.uiHelper = new LiveComponentUIHelper(this);
// Loading State Manager
this.loadingStateManager = new LoadingStateManager(
this.actionLoadingManager,
optimisticStateManager
);
}
/**
@@ -140,6 +167,9 @@ class LiveComponentManager {
// Setup accessibility features
this.setupAccessibility(componentId, element);
// Initialize tooltips for component
this.tooltipManager.initComponent(element);
console.log(`[LiveComponent] Initialized: ${componentId}`);
}
@@ -282,9 +312,9 @@ class LiveComponentManager {
this.setupFileUploadHandlers(config.element);
}
// Update state
// Update state using StateSerializer
if (state) {
config.element.dataset.state = JSON.stringify(state);
StateSerializer.setStateOnElement(config.element, state);
}
// Restore focus after update
@@ -614,18 +644,46 @@ class LiveComponentManager {
return;
}
// Check for pending duplicate request
const pendingRequest = this.requestDeduplicator.getPendingRequest(componentId, method, params);
if (pendingRequest) {
console.log(`[LiveComponent] Deduplicating request: ${componentId}.${method}`);
return await pendingRequest;
}
// Check for cached result
const cachedResult = this.requestDeduplicator.getCachedResult(componentId, method, params);
if (cachedResult) {
console.log(`[LiveComponent] Using cached result: ${componentId}.${method}`);
return cachedResult;
}
let operationId = null;
const startTime = performance.now();
try {
// Get current state from element
const stateJson = config.element.dataset.state || '{}';
const stateWrapper = JSON.parse(stateJson);
// Show loading state (uses LoadingStateManager for configurable indicators)
const loadingConfig = this.loadingStateManager.getConfig(componentId);
this.loadingStateManager.showLoading(componentId, config.element, {
fragments,
type: loadingConfig.type,
optimistic: true // Check optimistic UI first
});
// Create request promise
const requestPromise = (async () => {
try {
// Get current state from element using StateSerializer
const stateWrapper = StateSerializer.getStateFromElement(config.element) || {
id: componentId,
component: '',
data: {},
version: 1
};
// Extract actual state data from wrapper format
// Wrapper format: {id, component, data, version}
// Server expects just the data object
const state = stateWrapper.data || stateWrapper;
const state = stateWrapper.data || {};
// Apply optimistic update for immediate UI feedback
// This updates the UI before server confirmation
@@ -741,9 +799,12 @@ class LiveComponentManager {
this.setupActionHandlers(config.element);
}
// Update component state
// Re-initialize tooltips after DOM update
this.tooltipManager.initComponent(config.element);
// Update component state using StateSerializer
if (data.state) {
config.element.dataset.state = JSON.stringify(data.state);
StateSerializer.setStateOnElement(config.element, data.state);
}
// Handle server events
@@ -753,29 +814,50 @@ class LiveComponentManager {
console.log(`[LiveComponent] Action executed: ${componentId}.${method}`, data);
// Log successful action to DevTools
const endTime = performance.now();
this.logActionToDevTools(componentId, method, params, startTime, endTime, true);
// Log successful action to DevTools
const endTime = performance.now();
this.logActionToDevTools(componentId, method, params, startTime, endTime, true);
} catch (error) {
console.error(`[LiveComponent] Action failed:`, error);
// Cache successful result
this.requestDeduplicator.cacheResult(componentId, method, params, data);
// Log failed action to DevTools
const endTime = performance.now();
this.logActionToDevTools(componentId, method, params, startTime, endTime, false, error.message);
// Hide loading state
this.loadingStateManager.hideLoading(componentId);
// Rollback optimistic update on error
if (operationId) {
const snapshot = optimisticStateManager.getSnapshot(componentId);
if (snapshot) {
config.element.dataset.state = JSON.stringify(snapshot);
optimisticStateManager.clearPendingOperations(componentId);
optimisticStateManager.clearSnapshot(componentId);
return data;
} catch (error) {
console.error(`[LiveComponent] Action failed:`, error);
// Log failed action to DevTools
const endTime = performance.now();
this.logActionToDevTools(componentId, method, params, startTime, endTime, false, error.message);
// Rollback optimistic update on error
if (operationId) {
const snapshot = optimisticStateManager.getSnapshot(componentId);
if (snapshot) {
StateSerializer.setStateOnElement(config.element, snapshot);
optimisticStateManager.clearPendingOperations(componentId);
optimisticStateManager.clearSnapshot(componentId);
}
}
}
this.handleError(componentId, error);
}
// Hide loading state on error
this.loadingStateManager.hideLoading(componentId);
// Handle error via ErrorBoundary
await this.errorBoundary.handleError(componentId, method, error, {
params,
fragments
});
throw error;
}
})();
// Register pending request for deduplication
return this.requestDeduplicator.registerPendingRequest(componentId, method, params, requestPromise);
}
/**
@@ -1154,9 +1236,9 @@ class LiveComponentManager {
this.setupFileUploadHandlers(config.element);
}
// Update component state
// Update component state using StateSerializer
if (data.state) {
config.element.dataset.state = JSON.stringify(data.state);
StateSerializer.setStateOnElement(config.element, data.state);
}
// Handle server events
@@ -1260,6 +1342,22 @@ class LiveComponentManager {
// Cleanup accessibility features
this.accessibilityManager.cleanup(componentId);
// Cleanup error handler
this.errorBoundary.clearErrorHandler(componentId);
// Cleanup request deduplication
this.requestDeduplicator.clearComponent(componentId);
// Cleanup tooltips
this.tooltipManager.cleanupComponent(config.element);
// Hide any active loading states
this.loadingStateManager.hideLoading(componentId);
this.loadingStateManager.clearConfig(componentId);
// Cleanup UI components
this.uiHelper.cleanup(componentId);
// Remove from registry
this.components.delete(componentId);
@@ -1413,9 +1511,9 @@ class LiveComponentManager {
this.setupActionHandlers(config.element);
}
// Update state
// Update state using StateSerializer
if (result.state) {
config.element.dataset.state = JSON.stringify(result.state);
StateSerializer.setStateOnElement(config.element, result.state);
}
// Dispatch events
@@ -1584,4 +1682,11 @@ export { ComponentPlayground };
export { ComponentFileUploader } from './ComponentFileUploader.js';
export { FileUploadWidget } from './FileUploadWidget.js';
export { ChunkedUploader } from './ChunkedUploader.js';
// Export UI integration modules
export { tooltipManager } from './TooltipManager.js';
export { actionLoadingManager } from './ActionLoadingManager.js';
export { LiveComponentUIHelper } from './LiveComponentUIHelper.js';
export { LoadingStateManager } from './LoadingStateManager.js';
export default LiveComponent;