diff --git a/backend/utils/sequelize.js b/backend/utils/sequelize.js index 69c47c4..3ab1747 100644 --- a/backend/utils/sequelize.js +++ b/backend/utils/sequelize.js @@ -435,12 +435,39 @@ async function updateFalukantUserMoney(falukantUserId, moneyChange, activity, ch } } +// Helper: Sync mit Timeout +const syncModelWithTimeout = async (model, timeoutMs = 60000) => { + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => reject(new Error(`Model sync timeout after ${timeoutMs}ms`)), timeoutMs); + }); + + try { + await Promise.race([ + model.sync({ alter: true, force: false, constraints: false }), + timeoutPromise + ]); + } catch (error) { + if (error.message.includes('timeout')) { + console.warn(` ⚠️ ${model.name} sync timeout nach ${timeoutMs}ms - überspringe...`); + return false; + } + throw error; + } + return true; +}; + // Immer Schema-Updates (für Deployment) const syncModelsAlways = async (models) => { console.log('🔍 Deployment-Modus: Führe immer Schema-Updates durch...'); + const modelArray = Object.values(models); + const totalModels = modelArray.length; + let currentModel = 0; + try { - for (const model of Object.values(models)) { + for (const model of modelArray) { + currentModel++; + console.log(` 🔄 Syncing model ${model.name} (${currentModel}/${totalModels})...`); // Temporarily remove VIRTUAL fields before sync to prevent sync errors const originalAttributes = model.rawAttributes; const virtualFields = {}; @@ -585,7 +612,20 @@ const syncModelsAlways = async (models) => { } } - await model.sync({ alter: true, force: false, constraints: false }); + // Verwende syncModelWithTimeout für große Tabellen + const syncSuccess = await syncModelWithTimeout(model, 60000); + if (!syncSuccess) { + console.warn(` ⚠️ ${model.name} wurde übersprungen aufgrund von Timeout`); + // Restore associations before continuing + if (associationKeys.length > 0) { + model.associations = originalAssociations; + } + // Restore virtual fields + for (const [key, attr] of Object.entries(virtualFields)) { + model.rawAttributes[key] = attr; + } + continue; + } } catch (syncError) { // Wenn Sequelize einen "mehr als eine Zeile" Fehler hat, überspringe das Model // Dies kann durch doppelte pg_description Einträge oder mehrere Tabellen mit demselben Namen verursacht werden