strat-gameplay-webapp/backend/app/database/CLAUDE.md
Cal Corum 9546d2a370 CLAUDE: Extract database schema to reference document
- Created backend/.claude/DATABASE_SCHEMA.md with full table details
- Updated database/CLAUDE.md to reference the new schema doc
- Preserves valuable reference material while keeping CLAUDE.md concise

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 16:27:27 -06:00

132 lines
3.3 KiB
Markdown

# Database Module - Async PostgreSQL Persistence
## Purpose
Async PostgreSQL persistence layer using SQLAlchemy 2.0. Handles all database operations with connection pooling and proper transaction management.
## Structure
```
app/database/
├── __init__.py # Package exports
├── session.py # Async session management, Base declarative
└── operations.py # DatabaseOperations class
```
## Session Management
### Async Session Pattern
```python
from app.database.session import get_session
async def some_function():
async with get_session() as session:
result = await session.execute(query)
# Auto-commits on success, rolls back on exception
```
### Connection Pool
- **Driver**: asyncpg
- **Pool**: SQLAlchemy async pool
- Configurable pool size via env vars
## DatabaseOperations
Singleton class with all database operations.
### Game Operations
```python
from app.database.operations import DatabaseOperations
db_ops = DatabaseOperations()
await db_ops.create_game(game_id, league_id, home_team_id, away_team_id, ...)
await db_ops.update_game_state(game_id, inning, half, home_score, away_score)
game_data = await db_ops.load_game_state(game_id)
```
### Play Operations
```python
play_id = await db_ops.save_play(game_id, play_data, stats_data)
plays = await db_ops.get_plays(game_id, limit=100)
```
### Lineup Operations
```python
lineup_id = await db_ops.add_pd_lineup_card(game_id, team_id, card_id, position, batting_order)
lineup_id = await db_ops.add_sba_lineup_player(game_id, team_id, player_id, position, batting_order)
lineup = await db_ops.get_active_lineup(game_id, team_id)
await db_ops.deactivate_lineup_player(lineup_id)
```
### Roster Operations
```python
await db_ops.add_pd_roster_card(game_id, card_id, team_id)
await db_ops.add_sba_roster_player(game_id, player_id, team_id)
roster = await db_ops.get_pd_roster(game_id, team_id)
```
### Session Operations
```python
await db_ops.create_game_session(game_id)
await db_ops.update_session_snapshot(game_id, state_snapshot)
```
## Common Patterns
### Transaction Handling
```python
async with AsyncSessionLocal() as session:
try:
# Multiple operations
await session.commit()
except Exception:
await session.rollback()
raise
```
### Efficient Queries
```python
# Use joinedload for relationships needed immediately
from sqlalchemy.orm import joinedload
query = select(Play).options(
joinedload(Play.batter),
joinedload(Play.pitcher)
)
```
### Direct UPDATE
```python
# More efficient than SELECT + modify + commit
stmt = update(Game).where(Game.id == game_id).values(inning=5)
await session.execute(stmt)
```
## Database Schema
See `../models/CLAUDE.md` for model details.
| Table | Purpose |
|-------|---------|
| games | Game container, scores, status |
| plays | At-bat records with 25+ stats |
| lineups | Player assignments, substitutions |
| game_sessions | WebSocket state |
| roster_links | Eligible cards/players |
## Environment
```bash
DATABASE_URL=postgresql+asyncpg://user:pass@10.10.0.42:5432/paperdynasty_dev
```
## References
- **Database Schema**: See `../../.claude/DATABASE_SCHEMA.md` for complete table details
- **Models**: See `../models/CLAUDE.md`
- **State Recovery**: See `../core/state_manager.py`
---
**Tests**: `tests/integration/database/` | **Updated**: 2025-01-19