chore: archive database-setup-recovery change
Archive completed database initialization and recovery change.
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-18
|
||||
@@ -0,0 +1,58 @@
|
||||
## Context
|
||||
|
||||
Currently, the application crashes with cryptic SQLAlchemy errors when:
|
||||
1. Database tables don't exist (fresh deployment)
|
||||
2. Migrations haven't been applied
|
||||
3. The database is temporarily unavailable during startup
|
||||
|
||||
This requires manual intervention to run `alembic upgrade head` and restart containers.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Automatically run migrations on application startup
|
||||
- Handle missing tables gracefully with informative error messages
|
||||
- Add database connection retries for transient failures
|
||||
- Ensure seed data runs after migrations complete
|
||||
- Support both development and production Docker deployments
|
||||
|
||||
**Non-Goals:**
|
||||
- Database backup/recovery (out of scope)
|
||||
- Complex migration rollback handling
|
||||
- Multi-master database support
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Run migrations in startup event**
|
||||
- Rationale: Ensures database is always up-to-date before handling requests
|
||||
- Alternative: Separate init container. Rejected to keep deployment simple.
|
||||
|
||||
2. **Use alembic programmatic API**
|
||||
- Rationale: Avoids subprocess calls and captures errors properly
|
||||
- Run via `alembic.command.upgrade()` in async context
|
||||
|
||||
3. **Add connection retry with backoff**
|
||||
- Rationale: Database may not be ready when app starts
|
||||
- 5 retries with 2-second exponential backoff
|
||||
|
||||
4. **Graceful error handling**
|
||||
- Rationale: Clear error messages for operators
|
||||
- Distinguish between: connection refused, auth failed, missing migrations
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[Startup delay]** -> Migrations run on every startup, but Alembic is idempotent
|
||||
- **[Concurrent startup]** -> Multiple instances could race; use advisory locks if needed later
|
||||
- **[Migration failures]** -> App won't start; this is correct behavior
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. Add `init_database()` function that runs migrations and seed data
|
||||
2. Modify startup event to call `init_database()` with retries
|
||||
3. Update Docker CMD to ensure database is ready
|
||||
4. Test with fresh database volume
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Should we add a separate `db init` CLI command for manual runs?
|
||||
- Do we need database connection pooling configuration?
|
||||
@@ -0,0 +1,26 @@
|
||||
## Why
|
||||
|
||||
The application currently fails to start when database tables are missing or migrations haven't been applied. This creates a poor deployment experience and requires manual intervention. We need automatic database initialization, migration management, and seed data handling to ensure the application starts reliably in any environment.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Auto-run migrations on startup** instead of requiring manual `alembic upgrade head`
|
||||
- **Improve startup error handling** with clear error messages when DB is unavailable
|
||||
- **Add database readiness checks** before attempting migrations or seeding
|
||||
- **Seed data management** with proper handling of missing tables
|
||||
- **Better database initialization** in Docker environments
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `database-initialization`: Automatic database setup including migrations and seed data
|
||||
|
||||
### Modified Capabilities
|
||||
- `docker-infrastructure`: Add database initialization scripts and health checks
|
||||
|
||||
## Impact
|
||||
|
||||
- `apps/api/src/main.py`: Add startup database initialization
|
||||
- `apps/api/src/database.py`: Add connection health checks
|
||||
- `apps/api/Dockerfile`: Add init scripts
|
||||
- `docker-compose.yml` and `docker-compose.traefik.yml`: Update startup behavior
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Automatic Database Initialization
|
||||
|
||||
The system SHALL automatically initialize the database on application startup.
|
||||
|
||||
#### Scenario: Fresh database
|
||||
- GIVEN a new database with no tables
|
||||
- WHEN the application starts
|
||||
- THEN it runs all pending migrations
|
||||
- AND creates all required tables
|
||||
- AND seeds built-in data
|
||||
- AND starts accepting requests
|
||||
|
||||
#### Scenario: Database with existing migrations
|
||||
- GIVEN a database with some migrations applied
|
||||
- WHEN the application starts
|
||||
- THEN it runs only pending migrations
|
||||
- AND does not re-run existing migrations
|
||||
|
||||
### Requirement: Database Connection Resilience
|
||||
|
||||
The system SHALL retry database connections during startup.
|
||||
|
||||
#### Scenario: Database not ready
|
||||
- GIVEN the database is not yet accepting connections
|
||||
- WHEN the application starts
|
||||
- THEN it retries the connection 5 times
|
||||
- AND waits 2 seconds between retries
|
||||
- AND fails gracefully with a clear error message
|
||||
|
||||
#### Scenario: Database connection refused
|
||||
- GIVEN the database is unreachable
|
||||
- WHEN the application starts
|
||||
- THEN it logs a clear error: "Database connection failed"
|
||||
- AND exits with a non-zero status code
|
||||
|
||||
### Requirement: Seed Data Management
|
||||
|
||||
The system SHALL handle seed data after migrations complete.
|
||||
|
||||
#### Scenario: Seed after migrations
|
||||
- GIVEN migrations have just been applied
|
||||
- WHEN seeding built-in tool types
|
||||
- THEN the seeding only runs after migrations succeed
|
||||
- AND handles missing tables gracefully
|
||||
|
||||
### Requirement: Startup Error Messages
|
||||
|
||||
The system SHALL provide clear error messages for common database issues.
|
||||
|
||||
#### Scenario: Missing migrations
|
||||
- GIVEN tables are missing because migrations haven't run
|
||||
- WHEN the application starts
|
||||
- THEN the error message indicates: "Database not initialized. Run migrations."
|
||||
|
||||
#### Scenario: Authentication failure
|
||||
- GIVEN database credentials are wrong
|
||||
- WHEN the application starts
|
||||
- THEN the error message indicates: "Database authentication failed"
|
||||
@@ -0,0 +1,27 @@
|
||||
## 1. Database Initialization
|
||||
|
||||
- [x] 1.1 Create `init_database()` function in `apps/api/src/database.py`
|
||||
- [x] 1.2 Add alembic programmatic upgrade call
|
||||
- [x] 1.3 Add connection retry logic with backoff
|
||||
- [x] 1.4 Modify startup event to call `init_database()` before seeding
|
||||
- [x] 1.5 Update seed functions to check table existence first
|
||||
|
||||
## 2. Error Handling and Logging
|
||||
|
||||
- [x] 2.1 Add clear error messages for connection failures
|
||||
- [x] 2.2 Add clear error messages for missing tables
|
||||
- [x] 2.3 Add clear error messages for auth failures
|
||||
- [x] 2.4 Log migration status on startup
|
||||
|
||||
## 3. Docker Integration
|
||||
|
||||
- [x] 3.1 Update Dockerfile to wait for database readiness
|
||||
- [x] 3.2 Update docker-compose files with init order
|
||||
- [x] 3.3 Add health check script for database
|
||||
|
||||
## 4. Testing
|
||||
|
||||
- [x] 4.1 Test with fresh database (no tables)
|
||||
- [x] 4.2 Test with existing database (migrations already applied)
|
||||
- [x] 4.3 Test database connection failure handling
|
||||
- [x] 4.4 Run quality gates (ruff, mypy, pytest)
|
||||
Reference in New Issue
Block a user