paper-dynasty-gameplay-webapp/app/services/service_container.py
Cal Corum c09f9d1302 CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture
Establishes foundation for migrating baseball simulation from Discord bot to web application using service-oriented architecture pattern.

Key components:
- FastAPI application structure with dependency injection
- Service layer foundation with base classes and container
- Comprehensive directory documentation with README files
- PostgreSQL containerization with Docker Compose
- Testing structure for unit/integration/e2e tests
- Migration planning documentation
- Rotating log configuration per user requirements

Architecture follows Model/Service/Controller pattern to improve testability, maintainability, and scalability over original monolithic Discord app.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-27 21:44:12 -05:00

90 lines
2.5 KiB
Python

"""
Dependency injection container for services.
Manages service lifecycles and dependencies using FastAPI's dependency injection.
"""
import logging
from functools import lru_cache
from typing import Annotated
from fastapi import Depends
from sqlmodel import Session, SQLModel, create_engine
from sqlalchemy.pool import StaticPool
from app.config.constants import settings
logger = logging.getLogger(f'{__name__}.service_container')
# Database setup
engine = create_engine(
settings.DATABASE_URL,
echo=settings.DEBUG,
poolclass=StaticPool if "sqlite" in settings.DATABASE_URL else None,
connect_args={"check_same_thread": False} if "sqlite" in settings.DATABASE_URL else {}
)
def create_db_and_tables():
"""Create database tables."""
SQLModel.metadata.create_all(engine)
def get_session() -> Session:
"""
Dependency to get database session.
Each request gets its own session that's automatically closed.
"""
with Session(engine) as session:
try:
yield session
except Exception as e:
logger.error(f"Database session error: {str(e)}")
session.rollback()
raise
finally:
session.close()
# Type aliases for dependency injection
SessionDep = Annotated[Session, Depends(get_session)]
# Service dependencies - these will be implemented as services are created
def get_game_service(session: SessionDep):
"""Get GameService instance."""
from app.services.game_service import GameService
return GameService(session)
def get_user_service(session: SessionDep):
"""Get UserService instance."""
from app.services.user_service import UserService
return UserService(session)
def get_auth_service(session: SessionDep):
"""Get AuthService instance."""
from app.services.auth_service import AuthService
return AuthService(session)
def get_gameplay_service(session: SessionDep):
"""Get GameplayService instance."""
from app.services.gameplay_service import GameplayService
return GameplayService(session)
def get_ai_service(session: SessionDep):
"""Get AIService instance."""
from app.services.ai_service import AIService
return AIService(session)
# Type aliases for service dependencies
GameServiceDep = Annotated[object, Depends(get_game_service)]
UserServiceDep = Annotated[object, Depends(get_user_service)]
AuthServiceDep = Annotated[object, Depends(get_auth_service)]
GameplayServiceDep = Annotated[object, Depends(get_gameplay_service)]
AIServiceDep = Annotated[object, Depends(get_ai_service)]