Enhance database connection management by introducing configurable pool settings and implementing a retry mechanism for transient connection issues. Updated Sequelize pool options to use environment variables for better flexibility and added a retry wrapper for initializing settings to handle connection timeouts gracefully.
This commit is contained in:
@@ -38,6 +38,12 @@ if (!dbName || !dbUser || !dbHost) {
|
||||
throw new Error('Missing required database environment variables: DB_NAME, DB_USER, or DB_HOST');
|
||||
}
|
||||
|
||||
const poolMax = Number.parseInt(process.env.DB_POOL_MAX || '5', 10);
|
||||
const poolMin = Number.parseInt(process.env.DB_POOL_MIN || '1', 10);
|
||||
const poolAcquire = Number.parseInt(process.env.DB_POOL_ACQUIRE || '30000', 10);
|
||||
const poolIdle = Number.parseInt(process.env.DB_POOL_IDLE || '10000', 10);
|
||||
const poolEvict = Number.parseInt(process.env.DB_POOL_EVICT || '1000', 10);
|
||||
|
||||
const sequelize = new Sequelize(dbName, dbUser, dbPass, {
|
||||
host: dbHost,
|
||||
dialect: 'postgres',
|
||||
@@ -48,11 +54,11 @@ const sequelize = new Sequelize(dbName, dbUser, dbPass, {
|
||||
benchmark: SQL_BENCHMARK,
|
||||
logging: sqlLogger,
|
||||
pool: {
|
||||
max: 5, // Maximale Anzahl von Verbindungen im Pool (reduziert, um Connection Limit zu vermeiden)
|
||||
min: 1, // Minimale Anzahl von Verbindungen im Pool
|
||||
acquire: 30000, // Maximale Zeit (ms) zum Erwerb einer Verbindung (30 Sekunden)
|
||||
idle: 10000, // Maximale Zeit (ms), die eine Verbindung idle sein kann, bevor sie entfernt wird
|
||||
evict: 1000, // Intervall (ms) zum Prüfen auf idle Verbindungen
|
||||
max: poolMax, // Maximale Anzahl von Verbindungen im Pool
|
||||
min: poolMin, // Minimale Anzahl von Verbindungen im Pool
|
||||
acquire: poolAcquire, // Maximale Zeit (ms) zum Erwerb einer Verbindung
|
||||
idle: poolIdle, // Maximale Zeit (ms), die eine Verbindung idle sein kann, bevor sie entfernt wird
|
||||
evict: poolEvict, // Intervall (ms) zum Prüfen auf idle Verbindungen
|
||||
handleDisconnects: true // Automatisches Reconnect bei Verbindungsverlust
|
||||
},
|
||||
dialectOptions: {
|
||||
|
||||
@@ -23,6 +23,27 @@ const queryWithTimeout = async (query, timeoutMs = 30000, description = 'Query')
|
||||
}
|
||||
};
|
||||
|
||||
// Helper: Retry wrapper for transient pool/connection issues
|
||||
const runWithRetry = async (fn, { retries = 3, delayMs = 2000, description = 'operation' } = {}) => {
|
||||
let lastError;
|
||||
for (let attempt = 1; attempt <= retries; attempt++) {
|
||||
try {
|
||||
return await fn();
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
const isAcquireTimeout = error?.name === 'SequelizeConnectionAcquireTimeoutError'
|
||||
|| error?.message?.includes('ConnectionAcquireTimeoutError')
|
||||
|| error?.message?.includes('Operation timeout');
|
||||
if (!isAcquireTimeout || attempt === retries) {
|
||||
throw error;
|
||||
}
|
||||
console.warn(`⚠️ ${description} fehlgeschlagen (AcquireTimeout). Retry ${attempt}/${retries} in ${delayMs}ms...`);
|
||||
await new Promise(resolve => setTimeout(resolve, delayMs));
|
||||
}
|
||||
}
|
||||
throw lastError;
|
||||
};
|
||||
|
||||
// Helper: Prüft ob Tabelle existiert
|
||||
const tableExists = async (schema, tableName) => {
|
||||
try {
|
||||
@@ -592,7 +613,10 @@ const syncDatabase = async () => {
|
||||
await syncModelsWithUpdates(models);
|
||||
|
||||
console.log("Initializing settings...");
|
||||
await initializeSettings();
|
||||
await runWithRetry(
|
||||
() => initializeSettings(),
|
||||
{ retries: 3, delayMs: 2000, description: 'initializeSettings' }
|
||||
);
|
||||
|
||||
console.log("Initializing types...");
|
||||
await initializeTypes();
|
||||
|
||||
Reference in New Issue
Block a user