Files
meldestelle/docs/database/DATABASE_DIAGNOSTIC_REPORT.md
T
2025-10-15 12:48:00 +02:00

153 lines
4.9 KiB
Markdown

# Database Diagnostic Report - Exposed Framework Initialization
## Diagnostic Results
### ✅ Database.connect() Calls Identified
**Central Implementation:**
- **DatabaseFactory.kt** (Line 66): `Database.connect(dataSource!!)`
- Uses HikariCP Connection Pooling
- Singleton pattern with proper configuration
- Supports connection validation and leak detection
**Service-specific Configurations:**
- **Events Service**: EventsDatabaseConfiguration.kt - uses DatabaseFactory.init()
- **Horses Service**: DatabaseConfiguration.kt - uses DatabaseFactory.init()
- **Members Service**: MembersDatabaseConfiguration.kt - uses DatabaseFactory.init()
- **Masterdata Service**: MasterdataDatabaseConfiguration.kt - uses DatabaseFactory.init()
**⚠️ PROBLEM IDENTIFIED - Gateway Configuration:**
- **Gateway**: DatabaseConfig.kt (Lines 25-30) - **direct Database.connect() call**
```kotlin
Database.connect(
url = databaseUrl,
driver = "org.postgresql.Driver",
user = databaseUser,
password = databasePassword
)
```
### ✅ Exposed Operations (Transactions, Queries) Located
**Schema Initialization (in @PostConstruct):**
- All Services: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }`
- Gateway: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }` for all contexts
**Business Logic Transactions:**
- **TransactionalCreateHorseUseCase**: Uses `DatabaseFactory.dbQuery { ... }`
- **DatabaseMigrator**: Uses `transaction { ... }` for migrations
**Test Transactions:**
- SimpleDatabaseTest.kt: Direct `transaction { ... }` calls in tests
### ✅ Initialization Order Analyzed
**Correct Order in Services:**
1. `@PostConstruct` → `DatabaseFactory.init(config)` → `Database.connect()`
2. Immediately after: `transaction { SchemaUtils.createMissingTablesAndColumns(...) }`
3. Business Logic: `DatabaseFactory.dbQuery { ... }` for transactions
**⚠️ PROBLEM - Gateway Initialization:**
1. Ktor Application.configureDatabase() → direct `Database.connect()`
2. Immediately after: `transaction { ... }` for all service schemas
## 🚨 Identified Problems
### 1. **Inconsistent Database.connect() Implementation**
- **Services**: Use central DatabaseFactory with Connection Pooling
- **Gateway**: Direct Database.connect() without Connection Pooling
- **Risk**: Different connection quality and management
### 2. **Potential Race Conditions**
- Gateway and services initialize independently
- Both attempt to create schemas for the same tables
- **Risk**: Conflicts during parallel initialization
### 3. **Violation of Separation of Concerns**
- Gateway manages schemas for all services
- Services manage their own schemas
- **Risk**: Duplicate schema initialization
### 4. **Missing Initialization Order Guarantees**
- No explicit dependency order between Gateway and Services
- **Risk**: Exposed operations before Database.connect()
## ✅ Recommendations
### 1. **Switch Gateway to DatabaseFactory**
```kotlin
// Instead of direct Database.connect():
fun Application.configureDatabase() {
val config = DatabaseConfig.fromEnv() // or from Ktor Config
DatabaseFactory.init(config)
// Remove or coordinate schema initialization
}
```
### 2. **Coordinate Schema Initialization**
**Option A**: Only services manage their schemas (recommended)
```kotlin
// Gateway: Only connection, no schema initialization
fun Application.configureDatabase() {
DatabaseFactory.init(DatabaseConfig.fromEnv())
}
```
**Option B**: Centralized schema management
```kotlin
// Separate DatabaseSchemaInitializer with @Order annotation
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
class DatabaseSchemaInitializer {
@PostConstruct
fun initializeAllSchemas() {
// Schema initialization logic
}
}
```
### 3. **Ensure Startup Order**
```kotlin
// Services with @DependsOn
@Configuration
@DependsOn("databaseInitializer")
class HorsesDatabaseConfiguration {
// Configuration logic
}
```
### 4. **Unified Configuration**
```kotlin
// All components use DatabaseFactory
class SomeService {
suspend fun doSomething() {
DatabaseFactory.dbQuery {
// Exposed operations
}
}
}
```
## 📋 Summary
**✅ Correctly implemented:**
- All services use proper @PostConstruct → Database.connect() → Exposed operations sequence
- DatabaseFactory provides robust Connection Pool configuration
- Business logic uses correct transaction patterns
**⚠️ To be fixed:**
- Gateway Database.connect() inconsistency
- Potential race conditions in schema initialization
- Missing startup order coordination
**🎯 Priority:**
1. **High**: Switch Gateway to DatabaseFactory
2. **Medium**: Coordinate schema initialization
3. **Low**: Explicitly define startup order
The initialization sequence is fundamentally correct, but the inconsistency between Gateway and Services should be resolved to avoid potential problems.
---
*Last updated: July 25, 2025*