# Corrections Appliquées pour la Production Ce document liste les corrections critiques appliquées suite à l'analyse de performance et de préparation à la production. ## ✅ Corrections Appliquées ### 1. Utilitaire fetchWithTimeout **Fichier créé:** `lib/utils/fetch-with-timeout.ts` **Problème résolu:** Requêtes HTTP sans timeout pouvant bloquer indéfiniment. **Utilisation:** ```typescript import { fetchWithTimeout, fetchJsonWithTimeout } from '@/lib/utils/fetch-with-timeout'; // Exemple 1: Fetch simple avec timeout const response = await fetchWithTimeout('https://api.example.com/data', { method: 'GET', timeout: 10000, // 10 secondes headers: { 'Authorization': 'Bearer token' } }); // Exemple 2: Fetch avec parsing JSON automatique const data = await fetchJsonWithTimeout('https://api.example.com/data', { method: 'POST', timeout: 30000, // 30 secondes headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); ``` **Migration recommandée:** Remplacer tous les `fetch()` dans: - `lib/services/n8n-service.ts` - `app/api/missions/[missionId]/generate-plan/route.ts` - `app/api/users/[userId]/route.ts` - `app/api/leantime/tasks/route.ts` - `app/api/rocket-chat/messages/route.ts` ### 2. Correction Dockerfile **Fichier modifié:** `Dockerfile` **Problème résolu:** Utilisation de `migrate dev` en production (créerait de nouvelles migrations). **Changement:** ```dockerfile # ❌ AVANT RUN npx prisma migrate dev --name init # ✅ APRÈS # NOTE: Migrations should be run separately before deployment # DO NOT use 'migrate dev' in production # Use 'prisma migrate deploy' instead, run separately before container start ``` **Action requise:** Utiliser `Dockerfile.prod` pour la production, qui est déjà correctement configuré. ### 3. Script de Validation d'Environnement **Fichier créé:** `scripts/validate-env.ts` **Problème résolu:** Variables d'environnement manquantes non détectées avant déploiement. **Utilisation:** ```bash # Valider les variables d'environnement npm run validate:env # Ou directement ts-node scripts/validate-env.ts ``` **Fonctionnalités:** - ✅ Vérifie toutes les variables requises - ✅ Valide le format des URLs - ✅ Vérifie la force de NEXTAUTH_SECRET - ✅ Recommande les paramètres de pool DB - ✅ Affiche des warnings pour les variables optionnelles **Ajouté dans package.json:** ```json "validate:env": "ts-node scripts/validate-env.ts" ``` ## 🔄 Migrations à Effectuer ### Priorité 1 - CRITIQUE #### 1. Remplacer fetch() par fetchWithTimeout() **Fichiers à modifier:** 1. **lib/services/n8n-service.ts** ```typescript // ❌ AVANT const response = await fetch(this.webhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': this.apiKey }, body: JSON.stringify(cleanData), }); // ✅ APRÈS import { fetchWithTimeout } from '@/lib/utils/fetch-with-timeout'; const response = await fetchWithTimeout(this.webhookUrl, { method: 'POST', timeout: 30000, // 30 secondes headers: { 'Content-Type': 'application/json', 'x-api-key': this.apiKey }, body: JSON.stringify(cleanData), }); ``` 2. **app/api/missions/[missionId]/generate-plan/route.ts** ```typescript // ❌ AVANT const response = await fetch(webhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify(webhookData), }); // ✅ APRÈS import { fetchWithTimeout } from '@/lib/utils/fetch-with-timeout'; const response = await fetchWithTimeout(webhookUrl, { method: 'POST', timeout: 30000, headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey }, body: JSON.stringify(webhookData), }); ``` 3. **app/api/users/[userId]/route.ts** (getLeantimeUserId) ```typescript // ❌ AVANT const userResponse = await fetch('https://agilite.slm-lab.net/api/jsonrpc', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.LEANTIME_TOKEN || '' }, body: JSON.stringify({ ... }), }); // ✅ APRÈS import { fetchJsonWithTimeout } from '@/lib/utils/fetch-with-timeout'; const userData = await fetchJsonWithTimeout('https://agilite.slm-lab.net/api/jsonrpc', { method: 'POST', timeout: 10000, // 10 secondes headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.LEANTIME_TOKEN || '' }, body: JSON.stringify({ ... }), }); ``` #### 2. Configurer le Pool de Connexions Prisma **Action:** Modifier `DATABASE_URL` dans les variables d'environnement: ```bash # ❌ AVANT DATABASE_URL=postgresql://user:pass@host:5432/db # ✅ APRÈS DATABASE_URL=postgresql://user:pass@host:5432/db?connection_limit=10&pool_timeout=20&connect_timeout=10 ``` **Paramètres recommandés:** - `connection_limit=10` - Limite le nombre de connexions simultanées - `pool_timeout=20` - Timeout pour obtenir une connexion du pool (secondes) - `connect_timeout=10` - Timeout pour établir une connexion (secondes) **Note:** Ajuster `connection_limit` selon la charge attendue et les limites du serveur PostgreSQL. #### 3. Remplacer console.log par logger **Script de migration:** ```bash # Créer scripts/migrate-console-logs.sh #!/bin/bash find lib/services app/api -name "*.ts" -type f | while read file; do # Sauvegarder d'abord cp "$file" "$file.bak" # Remplacer sed -i '' 's/console\.log(/logger.debug(/g' "$file" sed -i '' 's/console\.error(/logger.error(/g' "$file" sed -i '' 's/console\.warn(/logger.warn(/g' "$file" sed -i '' 's/console\.debug(/logger.debug(/g' "$file" # Vérifier que logger est importé if ! grep -q "import.*logger" "$file" && grep -q "logger\." "$file"; then # Ajouter l'import en haut du fichier sed -i '' '1i\ import { logger } from '\''@/lib/logger'\''; ' "$file" fi done echo "✅ Console logs migrated to logger" echo "⚠️ Review changes and remove .bak files after verification" ``` **Fichiers prioritaires:** - `lib/services/rocketchat-call-listener.ts` (35 occurrences) - `lib/services/refresh-manager.ts` (19 occurrences) - `lib/services/prefetch-service.ts` (17 occurrences) ### Priorité 2 - HAUTE #### 4. Activer l'Optimisation d'Images Next.js **Fichier:** `next.config.mjs` ```javascript // ❌ AVANT images: { unoptimized: true, }, // ✅ APRÈS images: { unoptimized: false, formats: ['image/avif', 'image/webp'], deviceSizes: [640, 750, 828, 1080, 1200], imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], }, ``` #### 5. Implémenter Circuit Breaker Créer `lib/utils/circuit-breaker.ts` (voir exemple dans `PERFORMANCE_AND_PRODUCTION_ANALYSIS.md`). **Services à protéger:** - N8N webhooks - Leantime API - RocketChat API ## 📋 Checklist de Migration - [ ] Remplacer tous les `fetch()` par `fetchWithTimeout()` dans les fichiers listés - [ ] Configurer `DATABASE_URL` avec les paramètres de pool - [ ] Exécuter le script de migration console.log - [ ] Vérifier que tous les fichiers utilisent `logger` au lieu de `console` - [ ] Activer l'optimisation d'images dans `next.config.mjs` - [ ] Tester toutes les fonctionnalités après les changements - [ ] Valider l'environnement avec `npm run validate:env` - [ ] Déployer en staging et tester - [ ] Monitorer les performances après déploiement ## 🧪 Tests Recommandés ### Test de Timeout ```typescript // Test que les timeouts fonctionnent const start = Date.now(); try { await fetchWithTimeout('https://httpstat.us/200?sleep=5000', { timeout: 2000, // 2 secondes }); } catch (error) { const duration = Date.now() - start; console.assert(duration < 3000, 'Timeout should occur before 3 seconds'); console.assert(error.message.includes('timeout'), 'Error should mention timeout'); } ``` ### Test de Validation d'Environnement ```bash # Tester avec variables manquantes unset DATABASE_URL npm run validate:env # Devrait échouer avec message clair # Tester avec toutes les variables # Devrait réussir npm run validate:env ``` ## 📚 Documentation Voir `PERFORMANCE_AND_PRODUCTION_ANALYSIS.md` pour: - Analyse complète des problèmes - Recommandations détaillées - Métriques de succès - Checklist complète de mise en production --- **Dernière mise à jour:** $(date)