153 lines
4.9 KiB
Markdown
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*
|