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>
109 lines
3.6 KiB
Markdown
109 lines
3.6 KiB
Markdown
# Services Directory
|
|
|
|
This directory contains the **business logic layer** of the Model/Service Architecture. Services are the core of the application architecture, containing all business rules and logic separated from HTTP concerns and database details.
|
|
|
|
## Architecture Pattern
|
|
|
|
### Service Responsibilities
|
|
- **Business Logic**: Core application logic and rules
|
|
- **Data Validation**: Input validation and business rule enforcement
|
|
- **Service Orchestration**: Coordination between multiple services
|
|
- **Error Handling**: Business-appropriate error handling and logging
|
|
|
|
### Design Principles
|
|
- **Single Responsibility**: Each service has one clear purpose
|
|
- **Dependency Injection**: Services receive dependencies via constructor
|
|
- **Stateless**: Services don't maintain instance state between calls
|
|
- **Testable**: Services can be unit tested with mocked dependencies
|
|
- **Pure Business Logic**: No HTTP, database, or UI concerns
|
|
|
|
## Current Files
|
|
|
|
### `base_service.py`
|
|
Abstract base class providing common functionality:
|
|
- **Standardized logging**: `self._log_operation()` and `self._log_error()`
|
|
- **Session management**: SQLModel database session handling
|
|
- **Validation helpers**: Common validation patterns
|
|
|
|
### `service_container.py`
|
|
Dependency injection container:
|
|
- **Database sessions**: Session lifecycle management
|
|
- **Service dependencies**: FastAPI `Depends()` integration
|
|
- **Type annotations**: Service dependency type aliases
|
|
|
|
## Planned Services
|
|
|
|
### Core Game Services
|
|
- **GameService**: Game creation, management, queries
|
|
- **GameplayService**: Core gameplay simulation & flow
|
|
- **AIService**: AI decision making and automation
|
|
|
|
### Supporting Services
|
|
- **UserService**: User sessions, preferences
|
|
- **AuthService**: Discord OAuth, session management
|
|
- **NotificationService**: Web notifications and real-time updates
|
|
|
|
## Service Pattern Example
|
|
|
|
```python
|
|
from app.services.base_service import BaseService
|
|
from app.services.service_container import SessionDep
|
|
|
|
class GameService(BaseService):
|
|
def __init__(self, session: Session):
|
|
super().__init__(session)
|
|
|
|
async def create_game(self, away_team_id: int, home_team_id: int) -> Game:
|
|
self._log_operation("create_game", f"Teams: {away_team_id} vs {home_team_id}")
|
|
|
|
# Business logic here
|
|
game = Game(away_team_id=away_team_id, home_team_id=home_team_id)
|
|
|
|
# Database persistence
|
|
self.session.add(game)
|
|
self.session.commit()
|
|
|
|
return game
|
|
```
|
|
|
|
## Dependency Injection
|
|
|
|
Services are injected into routes using FastAPI's `Depends()`:
|
|
|
|
```python
|
|
from app.services.service_container import GameServiceDep
|
|
|
|
@router.post("/games/start")
|
|
async def start_game(game_service: GameServiceDep):
|
|
# Service contains business logic, route handles HTTP concerns
|
|
return await game_service.create_game(away_team_id=1, home_team_id=2)
|
|
```
|
|
|
|
## Testing Services
|
|
|
|
Services should be unit tested independently:
|
|
|
|
```python
|
|
@pytest.fixture
|
|
def mock_session():
|
|
return Mock(spec=Session)
|
|
|
|
@pytest.fixture
|
|
def game_service(mock_session):
|
|
return GameService(mock_session)
|
|
|
|
async def test_create_game(game_service):
|
|
# Test business logic without database
|
|
result = await game_service.create_game(1, 2)
|
|
assert result.away_team_id == 1
|
|
```
|
|
|
|
## Migration from Discord App
|
|
|
|
When migrating from `../discord-app/`:
|
|
|
|
1. **Extract business logic** from Discord command handlers
|
|
2. **Remove Discord dependencies** (discord.py, interaction objects)
|
|
3. **Create service methods** with pure business logic
|
|
4. **Add comprehensive unit tests** for service methods
|
|
5. **Create thin route handlers** that delegate to services |