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,245 @@
/**
* State Serializer for LiveComponents
*
* Provides type-safe state serialization/deserialization with versioning
* and validation.
*/
/**
* Serialize component state
*
* @param {LiveComponentState} state - Component state
* @returns {string} Serialized state JSON
*/
export function serializeState(state) {
// Validate state structure
if (!state || typeof state !== 'object') {
throw new Error('State must be an object');
}
if (!state.id || typeof state.id !== 'string') {
throw new Error('State must have a valid id');
}
if (!state.component || typeof state.component !== 'string') {
throw new Error('State must have a valid component name');
}
if (typeof state.version !== 'number' || state.version < 1) {
throw new Error('State must have a valid version number');
}
// Ensure data is an object
const data = state.data || {};
if (typeof data !== 'object' || Array.isArray(data)) {
throw new Error('State data must be an object');
}
// Create serializable state
const serializableState = {
id: state.id,
component: state.component,
data: data,
version: state.version
};
// Serialize to JSON
try {
return JSON.stringify(serializableState);
} catch (error) {
throw new Error(`Failed to serialize state: ${error.message}`);
}
}
/**
* Deserialize component state
*
* @param {string} json - Serialized state JSON
* @returns {LiveComponentState} Deserialized state
*/
export function deserializeState(json) {
if (typeof json !== 'string') {
throw new Error('State JSON must be a string');
}
if (json.trim() === '') {
// Return empty state
return {
id: '',
component: '',
data: {},
version: 1
};
}
try {
const parsed = JSON.parse(json);
// Validate structure
if (!parsed || typeof parsed !== 'object') {
throw new Error('Invalid state structure');
}
// Extract state data
const id = parsed.id || '';
const component = parsed.component || '';
const data = parsed.data || {};
const version = typeof parsed.version === 'number' ? parsed.version : 1;
// Validate data is an object
if (typeof data !== 'object' || Array.isArray(data)) {
throw new Error('State data must be an object');
}
return {
id,
component,
data,
version
};
} catch (error) {
if (error instanceof SyntaxError) {
throw new Error(`Invalid JSON format: ${error.message}`);
}
throw error;
}
}
/**
* Create state diff (changes between two states)
*
* @param {LiveComponentState} oldState - Previous state
* @param {LiveComponentState} newState - New state
* @returns {Object} State diff
*/
export function createStateDiff(oldState, newState) {
const diff = {
changed: false,
added: {},
removed: {},
modified: {},
versionChange: newState.version - oldState.version
};
const oldData = oldState.data || {};
const newData = newState.data || {};
// Find added keys
for (const key in newData) {
if (!(key in oldData)) {
diff.added[key] = newData[key];
diff.changed = true;
}
}
// Find removed keys
for (const key in oldData) {
if (!(key in newData)) {
diff.removed[key] = oldData[key];
diff.changed = true;
}
}
// Find modified keys
for (const key in newData) {
if (key in oldData) {
const oldValue = oldData[key];
const newValue = newData[key];
// Deep comparison for objects
if (JSON.stringify(oldValue) !== JSON.stringify(newValue)) {
diff.modified[key] = {
old: oldValue,
new: newValue
};
diff.changed = true;
}
}
}
return diff;
}
/**
* Merge state changes
*
* @param {LiveComponentState} baseState - Base state
* @param {Object} changes - State changes to apply
* @returns {LiveComponentState} Merged state
*/
export function mergeStateChanges(baseState, changes) {
const baseData = baseState.data || {};
const mergedData = { ...baseData, ...changes };
return {
...baseState,
data: mergedData,
version: baseState.version + 1
};
}
/**
* Validate state structure
*
* @param {LiveComponentState} state - State to validate
* @returns {boolean} True if valid
*/
export function validateState(state) {
if (!state || typeof state !== 'object') {
return false;
}
if (!state.id || typeof state.id !== 'string') {
return false;
}
if (!state.component || typeof state.component !== 'string') {
return false;
}
if (typeof state.version !== 'number' || state.version < 1) {
return false;
}
if (state.data && (typeof state.data !== 'object' || Array.isArray(state.data))) {
return false;
}
return true;
}
/**
* Get state from DOM element
*
* @param {HTMLElement} element - Component element
* @returns {LiveComponentState|null} State or null if not found
*/
export function getStateFromElement(element) {
const stateJson = element.dataset.state;
if (!stateJson) {
return null;
}
try {
return deserializeState(stateJson);
} catch (error) {
console.error('[StateSerializer] Failed to deserialize state from element:', error);
return null;
}
}
/**
* Set state on DOM element
*
* @param {HTMLElement} element - Component element
* @param {LiveComponentState} state - State to set
*/
export function setStateOnElement(element, state) {
if (!validateState(state)) {
throw new Error('Invalid state structure');
}
const stateJson = serializeState(state);
element.dataset.state = stateJson;
}