meldestelle/docs/database/DATABASE_DIAGNOSTIC_REPORT.md
2025-07-25 23:16:16 +02:00

5.1 KiB

Database Diagnostic Report - Exposed Framework Initialization

Diagnose Ergebnisse

Database.connect() Aufrufe identifiziert

Zentrale Implementierung:

  • DatabaseFactory.kt (Zeile 66): Database.connect(dataSource!!)
    • Verwendet HikariCP Connection Pooling
    • Singleton-Pattern mit proper Konfiguration
    • Unterstützt Verbindungsvalidierung und Leak-Detection

Service-spezifische Konfigurationen:

  • Events Service: EventsDatabaseConfiguration.kt - verwendet DatabaseFactory.init()
  • Horses Service: DatabaseConfiguration.kt - verwendet DatabaseFactory.init()
  • Members Service: MembersDatabaseConfiguration.kt - verwendet DatabaseFactory.init()
  • Masterdata Service: MasterdataDatabaseConfiguration.kt - verwendet DatabaseFactory.init()

⚠️ PROBLEM IDENTIFIZIERT - Gateway Konfiguration:

  • Gateway: DatabaseConfig.kt (Zeile 25-30) - direkter Database.connect() Aufruf
    Database.connect(
        url = databaseUrl,
        driver = "org.postgresql.Driver",
        user = databaseUser,
        password = databasePassword
    )
    

Exposed-Operationen (Transaktionen, Queries) lokalisiert

Schema-Initialisierung (in @PostConstruct):

  • Alle Services: transaction { SchemaUtils.createMissingTablesAndColumns(...) }
  • Gateway: transaction { SchemaUtils.createMissingTablesAndColumns(...) } für alle Kontexte

Business Logic Transaktionen:

  • TransactionalCreateHorseUseCase: Verwendet DatabaseFactory.dbQuery { ... }
  • DatabaseMigrator: Verwendet transaction { ... } für Migrationen

Test-Transaktionen:

  • SimpleDatabaseTest.kt: Direkte transaction { ... } Aufrufe in Tests

Initialisierungsreihenfolge analysiert

Korrekte Reihenfolge in Services:

  1. @PostConstructDatabaseFactory.init(config)Database.connect()
  2. Sofort danach: transaction { SchemaUtils.createMissingTablesAndColumns(...) }
  3. Business Logic: DatabaseFactory.dbQuery { ... } für Transaktionen

⚠️ PROBLEM - Gateway Initialisierung:

  1. Ktor Application.configureDatabase() → direkter Database.connect()
  2. Sofort danach: transaction { ... } für alle Service-Schemas

🚨 Identifizierte Probleme

1. Inkonsistente Database.connect() Implementierung

  • Services: Verwenden zentralen DatabaseFactory mit Connection Pooling
  • Gateway: Direkter Database.connect() ohne Connection Pooling
  • Risiko: Unterschiedliche Verbindungsqualität und -management

2. Potentielle Race Conditions

  • Gateway und Services initialisieren unabhängig voneinander
  • Beide versuchen, Schemas für dieselben Tabellen zu erstellen
  • Risiko: Konflikte bei paralleler Initialisierung

3. Verletzung der Separation of Concerns

  • Gateway verwaltet Schemas für alle Services
  • Services verwalten ihre eigenen Schemas
  • Risiko: Doppelte Schema-Initialisierung

4. Fehlende Initialisierungsreihenfolge-Garantien

  • Keine explizite Abhängigkeitsreihenfolge zwischen Gateway und Services
  • Risiko: Exposed-Operationen vor Database.connect()

Empfehlungen

1. Gateway auf DatabaseFactory umstellen

// Statt direktem Database.connect():
fun Application.configureDatabase() {
    val config = DatabaseConfig.fromEnv() // oder aus Ktor Config
    DatabaseFactory.init(config)
    // Schema-Initialisierung entfernen oder koordinieren
}

2. Schema-Initialisierung koordinieren

Option A: Nur Services verwalten ihre Schemas (empfohlen)

// Gateway: Nur Verbindung, keine Schema-Initialisierung
fun Application.configureDatabase() {
    DatabaseFactory.init(DatabaseConfig.fromEnv())
}

Option B: Zentralisierte Schema-Verwaltung

// Separater DatabaseSchemaInitializer mit @Order Annotation
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
class DatabaseSchemaInitializer {
    @PostConstruct
    fun initializeAllSchemas() {
        // Schema initialization logic
    }
}

3. Startup-Reihenfolge sicherstellen

// Services mit @DependsOn
@Configuration
@DependsOn("databaseInitializer")
class HorsesDatabaseConfiguration {
    // Configuration logic
}

4. Einheitliche Konfiguration

// Alle Komponenten verwenden DatabaseFactory
class SomeService {
    suspend fun doSomething() {
        DatabaseFactory.dbQuery {
            // Exposed operations
        }
    }
}

📋 Zusammenfassung

Korrekt implementiert:

  • Alle Services verwenden proper @PostConstruct → Database.connect() → Exposed operations Reihenfolge
  • DatabaseFactory bietet robuste Connection Pool Konfiguration
  • Business Logic verwendet korrekte Transaktionsmuster

⚠️ Zu beheben:

  • Gateway Database.connect() Inkonsistenz
  • Potentielle Race Conditions bei Schema-Initialisierung
  • Fehlende Startup-Reihenfolge-Koordination

🎯 Priorität:

  1. Hoch: Gateway auf DatabaseFactory umstellen
  2. Mittel: Schema-Initialisierung koordinieren
  3. Niedrig: Startup-Reihenfolge explizit definieren

Die Reihenfolge der Initialisierung ist grundsätzlich korrekt, aber die Inkonsistenz zwischen Gateway und Services sollte behoben werden, um potentielle Probleme zu vermeiden.