Gestion des Timeouts - Aaperture
Ce document décrit le système de gestion des timeouts centralisé dans Aaperture.
📋 Vue d'ensemble
Le système de gestion des timeouts permet de configurer des délais d'expiration pour toutes les opérations longues dans l'application, garantissant que les requêtes ne restent pas bloquées indéfiniment.
⚙️ Configuration
📝 Important : Ajoutez ces variables à votre fichier
.envpour configurer les timeouts.
Voir ENV_VARIABLES_TIMEOUT.md pour la liste complète et les exemples de configuration.
Tous les timeouts sont configurables via des variables d'environnement avec des valeurs par défaut sensées.
Variables d'environnement disponibles
# Database timeouts (milliseconds)
DB_QUERY_TIMEOUT=30000 # Timeout pour requêtes DB individuelles (défaut: 30s)
DB_CONNECTION_TIMEOUT=10000 # Timeout pour connexions DB (défaut: 10s)
DB_IDLE_TIMEOUT=30000 # Timeout pour connexions idle (défaut: 30s)
# External API timeouts (milliseconds)
GOOGLE_CALENDAR_TIMEOUT=10000 # Timeout pour Google Calendar API (défaut: 10s)
GMAIL_API_TIMEOUT=10000 # Timeout pour Gmail API (défaut: 10s)
GOOGLE_OAUTH_TIMEOUT=10000 # Timeout pour Google OAuth (défaut: 10s)
OPENAI_API_TIMEOUT=30000 # Timeout pour OpenAI API (défaut: 30s)
# Job timeouts (milliseconds)
CRON_JOB_TIMEOUT=300000 # Timeout max pour jobs cron (défaut: 5 minutes)
# HTTP timeouts (milliseconds)
HTTP_REQUEST_TIMEOUT=30000 # Timeout global pour requêtes HTTP (défaut: 30s)
# Infrastructure timeouts (seconds for shell scripts)
MIGRATION_TIMEOUT=600 # Timeout pour migrations (défaut: 10 minutes)
BACKUP_TIMEOUT=1800 # Timeout pour backups (défaut: 30 minutes)
# Other timeouts (milliseconds)
EMAIL_TIMEOUT=30000 # Timeout pour SMTP (défaut: 30s)
WEBSOCKET_TIMEOUT=60000 # Timeout pour WebSocket (défaut: 60s)
🏗️ Architecture
Module de configuration
Le module TimeoutConfig centralise toutes les configurations de timeout :
import { TimeoutConfig } from "../common/timeout.config.js";
constructor(private readonly timeoutConfig: TimeoutConfig) {}
// Utilisation
const timeout = this.timeoutConfig.openaiTimeout; // 30000ms par défaut
Utilitaires
Des fonctions utilitaires sont disponibles pour faciliter l'utilisation des timeouts :
import {
withTimeout,
executeWithTimeoutAndRetry,
} from "../common/timeout.utils.js";
// Timeout simple
const result = await withTimeout(myPromise, 30000, "Operation timed out");
// Timeout avec retry
const result = await executeWithTimeoutAndRetry(
() => myAsyncFunction(),
30000,
3, // max retries
1000, // delay between retries
"Operation timed out"
);
Middleware HTTP
Statut : ✅ Appliqué globalement
Un middleware global applique un timeout à toutes les requêtes HTTP :
// Automatiquement appliqué dans main.ts
// Retourne 408 Request Timeout si le timeout est dépassé
Le middleware TimeoutMiddleware est appliqué dans backend/src/main.ts et utilise HTTP_REQUEST_TIMEOUT (défaut: 30s).
📍 Utilisation par composant
Base de données
Les timeouts de base de données sont configurés dans DbService :
- Pool connection timeout :
DB_CONNECTION_TIMEOUT(défaut: 10s) - ✅ Appliqué - Pool idle timeout :
DB_IDLE_TIMEOUT(défaut: 30s) - ✅ Appliqué - Query timeout :
DB_QUERY_TIMEOUT(défaut: 30s) - ✅ Appliqué automatiquement aux requêtes viaquery()
APIs externes
OpenAI
Statut : ✅ Complètement implémenté
Les timeouts sont configurés via OPENAI_API_TIMEOUT (défaut: 30s) et sont appliqués dans les services suivants :
- ✅
backend/src/agent/agent-chat.service.ts- Timeouts appliqués sur streaming et non-streaming - ✅
backend/src/agent/agent-actions-generation.service.ts- Timeout appliqué - ✅
backend/src/search/ai-search.service.ts- Timeouts appliqués sur les 3 appels API (processQuery, generateFilters, answerQuestion) - ✅
backend/src/search/ai-chat.service.ts- Timeout appliqué - ✅
backend/src/search/ai-actions.service.ts- Timeout appliqué - ✅
backend/src/extraction/services/llm.service.ts- Timeout appliqué sur extraction - ✅
backend/src/openai/openai.service.ts- Timeouts appliqués sur vérification de connexion
Exemple d'implémentation :
import { TimeoutConfig } from "../common/timeout.config.js";
import { withTimeout } from "../common/timeout.utils.js";
@Injectable()
export class MyService {
constructor(private readonly timeoutConfig: TimeoutConfig) {}
async callOpenAI() {
const timeout = this.timeoutConfig.openaiTimeout;
const response = await withTimeout(
openai.chat.completions.create({ ... }),
timeout,
"OpenAI API call timed out"
);
}
}
Google Calendar / Gmail
Statut : ✅ Complètement implémenté
Les timeouts sont configurés via GOOGLE_CALENDAR_TIMEOUT et GMAIL_API_TIMEOUT (défaut: 10s) et sont appliqués dans les services suivants :
- ✅
backend/src/google-calendar/google-calendar.service.ts- HelperwithCalendarTimeoututilisé pour tous les appels API (calendars.get/insert/delete, events.list/insert/update/patch/delete/get/instances) - ✅
backend/src/quotes-invoices/gmail.service.ts- Timeouts appliqués surusers.getProfileetusers.messages.send
Exemple d'implémentation :
import { TimeoutConfig } from "../common/timeout.config.js";
import { withTimeout } from "../common/timeout.utils.js";
@Injectable()
export class MyService {
constructor(private readonly timeoutConfig: TimeoutConfig) {}
async callGoogleCalendar() {
const timeout = this.timeoutConfig.googleCalendarTimeout;
const response = await withTimeout(
calendar.events.list({ ... }),
timeout,
"Google Calendar API call timed out"
);
}
}
Jobs Cron
Statut : ✅ Complètement implémenté
Les jobs cron respectent CRON_JOB_TIMEOUT (défaut: 5 minutes). Les schedulers suivants ont été mis à jour :
- ✅
backend/src/audit/audit.scheduler.ts-cleanupOldAuditLogswrappé avecexecuteWithTimeoutAndRetry - ✅
backend/src/sessions/recurring-sessions.scheduler.ts-handleRecurringSessionsGenerationwrappé - ✅
backend/src/workflow-tasks/workflow-tasks.scheduler.ts-handleWorkflowTasksExecutionwrappé - ✅
backend/src/backup/backup.scheduler.ts-createAutomaticBackupwrappé - ✅
backend/src/scheduled-emails/scheduled-emails.scheduler.ts-handleScheduledEmailsExecutionwrappé - ✅
backend/src/google-calendar/google-calendar-sync.scheduler.ts-syncCalendarToSessionswrappé - ✅
backend/src/migrations/migrations.scheduler.ts-checkFailedMigrationswrappé
Exemple d'implémentation :
import { TimeoutConfig } from "../common/timeout.config.js";
import { executeWithTimeoutAndRetry } from "../common/timeout.utils.js";
@Injectable()
export class MyScheduler {
constructor(private readonly timeoutConfig: TimeoutConfig) {}
@Cron(CronExpression.EVERY_DAY_AT_2AM)
async myCronJob() {
await executeWithTimeoutAndRetry(
() => this.doWork(),
this.timeoutConfig.cronJobTimeout,
0, // no retries for cron jobs
0,
"Cron job timed out"
);
}
}
Scripts shell
Migrations
Le script migrate-improved.sh utilise MIGRATION_TIMEOUT :
# Timeout configurable (défaut: 10 minutes)
MIGRATION_TIMEOUT="${MIGRATION_TIMEOUT:-600}"
timeout "${MIGRATION_TIMEOUT}" docker run ...
Backups
Le script backup-db.sh utilise BACKUP_TIMEOUT :
# Timeout configurable (défaut: 30 minutes)
BACKUP_TIMEOUT="${BACKUP_TIMEOUT:-1800}"
timeout "${BACKUP_TIMEOUT}" pg_dump ...
🔍 Monitoring
Les timeouts sont loggés dans les logs de l'application :
- Timeouts DB : Loggés avec le message "Query timeout after Xms"
- Timeouts HTTP : Retournent une réponse 408 avec message d'erreur
- Timeouts scripts : Affichent un message d'erreur et exit avec code 1
🎯 Bonnes pratiques
- Utiliser les valeurs par défaut : Les valeurs par défaut sont choisies pour être raisonnables pour la plupart des cas d'usage
- Ajuster selon l'environnement : Augmenter les timeouts en production si nécessaire
- Surveiller les timeouts : Surveiller les logs pour détecter les timeouts fréquents
- Retry avec backoff : Utiliser
executeWithTimeoutAndRetrypour les opérations critiques - Timeouts spécifiques : Utiliser des timeouts plus courts pour les opérations rapides, plus longs pour les opérations lourdes
- Toujours utiliser TimeoutConfig : Ne jamais hardcoder les valeurs de timeout, toujours utiliser
TimeoutConfigpour la configuration centralisée
✅ État d'implémentation
✅ Complètement implémenté
- Base de données : Timeouts pool et requêtes appliqués dans
DbService - HTTP : Middleware global appliqué dans
main.ts - Scripts shell : Timeouts appliqués dans
migrate-improved.shetbackup-db.sh - APIs externes : Timeouts appliqués dans tous les services :
- ✅ Services OpenAI (
agent-chat.service.ts,ai-search.service.ts,llm.service.ts,openai.service.ts, etc.) - Tous les appels API wrappés avecwithTimeout - ✅ Services Google Calendar (
google-calendar.service.ts) - HelperwithCalendarTimeoututilisé pour tous les appels API - ✅ Services Gmail (
gmail.service.ts) - Timeouts appliqués surusers.getProfileetusers.messages.send
- ✅ Services OpenAI (
- Jobs cron : Timeouts appliqués dans tous les schedulers :
- ✅
audit.scheduler.ts-cleanupOldAuditLogswrappé avecexecuteWithTimeoutAndRetry - ✅
recurring-sessions.scheduler.ts-handleRecurringSessionsGenerationwrappé - ✅
workflow-tasks.scheduler.ts-handleWorkflowTasksExecutionwrappé - ✅
backup.scheduler.ts-createAutomaticBackupwrappé - ✅
scheduled-emails.scheduler.ts-handleScheduledEmailsExecutionwrappé - ✅
google-calendar-sync.scheduler.ts-syncCalendarToSessionswrappé - ✅
migrations.scheduler.ts-checkFailedMigrationswrappé
- ✅
Statut : ✅ Tous les timeouts sont maintenant appliqués dans l'application
📚 Références
- ENV_VARIABLES_TIMEOUT.md - Liste complète des variables d'environnement pour les timeouts
- PLAN_AMELIORATIONS_CRM.md - Section "Infrastructure & Robustesse"
- AGENTS_BACKEND.md (documentation interne) - Guidelines backend
- MIGRATION_PROCESS.md - Processus de migration
- DISASTER_RECOVERY.md - Plan de disaster recovery