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
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:
180
resources/js/modules/livecomponent/RequestDeduplicator.js
Normal file
180
resources/js/modules/livecomponent/RequestDeduplicator.js
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Request Deduplication for LiveComponents
|
||||
*
|
||||
* Prevents duplicate requests for the same action with the same parameters.
|
||||
* Useful for preventing race conditions and reducing server load.
|
||||
*/
|
||||
|
||||
export class RequestDeduplicator {
|
||||
constructor() {
|
||||
this.pendingRequests = new Map();
|
||||
this.requestCache = new Map();
|
||||
this.cacheTimeout = 1000; // 1 second cache
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate request key for deduplication
|
||||
*
|
||||
* @param {string} componentId - Component ID
|
||||
* @param {string} method - Action method name
|
||||
* @param {Object} params - Action parameters
|
||||
* @returns {string} Request key
|
||||
*/
|
||||
generateKey(componentId, method, params) {
|
||||
// Sort params for consistent key generation
|
||||
const sortedParams = Object.keys(params)
|
||||
.sort()
|
||||
.reduce((acc, key) => {
|
||||
acc[key] = params[key];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const paramsString = JSON.stringify(sortedParams);
|
||||
return `${componentId}:${method}:${paramsString}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if request is already pending
|
||||
*
|
||||
* @param {string} componentId - Component ID
|
||||
* @param {string} method - Action method name
|
||||
* @param {Object} params - Action parameters
|
||||
* @returns {Promise|null} Pending request promise or null
|
||||
*/
|
||||
getPendingRequest(componentId, method, params) {
|
||||
const key = this.generateKey(componentId, method, params);
|
||||
return this.pendingRequests.get(key) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register pending request
|
||||
*
|
||||
* @param {string} componentId - Component ID
|
||||
* @param {string} method - Action method name
|
||||
* @param {Object} params - Action parameters
|
||||
* @param {Promise} promise - Request promise
|
||||
* @returns {Promise} Request promise
|
||||
*/
|
||||
registerPendingRequest(componentId, method, params, promise) {
|
||||
const key = this.generateKey(componentId, method, params);
|
||||
|
||||
// Store pending request
|
||||
this.pendingRequests.set(key, promise);
|
||||
|
||||
// Clean up when request completes
|
||||
promise
|
||||
.then(() => {
|
||||
this.pendingRequests.delete(key);
|
||||
})
|
||||
.catch(() => {
|
||||
this.pendingRequests.delete(key);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if request result is cached
|
||||
*
|
||||
* @param {string} componentId - Component ID
|
||||
* @param {string} method - Action method name
|
||||
* @param {Object} params - Action parameters
|
||||
* @returns {Object|null} Cached result or null
|
||||
*/
|
||||
getCachedResult(componentId, method, params) {
|
||||
const key = this.generateKey(componentId, method, params);
|
||||
const cached = this.requestCache.get(key);
|
||||
|
||||
if (!cached) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if cache is still valid
|
||||
const now = Date.now();
|
||||
if (now - cached.timestamp > this.cacheTimeout) {
|
||||
this.requestCache.delete(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return cached.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache request result
|
||||
*
|
||||
* @param {string} componentId - Component ID
|
||||
* @param {string} method - Action method name
|
||||
* @param {Object} params - Action parameters
|
||||
* @param {Object} result - Request result
|
||||
*/
|
||||
cacheResult(componentId, method, params, result) {
|
||||
const key = this.generateKey(componentId, method, params);
|
||||
this.requestCache.set(key, {
|
||||
result,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
|
||||
// Clean up old cache entries
|
||||
this.cleanupCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up expired cache entries
|
||||
*/
|
||||
cleanupCache() {
|
||||
const now = Date.now();
|
||||
for (const [key, cached] of this.requestCache.entries()) {
|
||||
if (now - cached.timestamp > this.cacheTimeout) {
|
||||
this.requestCache.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all pending requests
|
||||
*/
|
||||
clearPendingRequests() {
|
||||
this.pendingRequests.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all cached results
|
||||
*/
|
||||
clearCache() {
|
||||
this.requestCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear requests and cache for specific component
|
||||
*
|
||||
* @param {string} componentId - Component ID
|
||||
*/
|
||||
clearComponent(componentId) {
|
||||
// Clear pending requests
|
||||
for (const [key] of this.pendingRequests.entries()) {
|
||||
if (key.startsWith(`${componentId}:`)) {
|
||||
this.pendingRequests.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear cache
|
||||
for (const [key] of this.requestCache.entries()) {
|
||||
if (key.startsWith(`${componentId}:`)) {
|
||||
this.requestCache.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get statistics
|
||||
*
|
||||
* @returns {Object} Statistics
|
||||
*/
|
||||
getStats() {
|
||||
return {
|
||||
pendingRequests: this.pendingRequests.size,
|
||||
cachedResults: this.requestCache.size
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user