Clarify settings and app wiring

This commit is contained in:
2025-11-27 14:32:00 +01:00
parent 3a7208d28d
commit 6b73ae043d
2 changed files with 48 additions and 19 deletions

View File

@@ -1,16 +1,20 @@
"""Environment configuration derived from environment variables."""
from functools import lru_cache
from pydantic import SecretStr # Import SecretStr for sensitive data
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Application settings."""
"""
Application settings class using Pydantic BaseSettings.
Settings are loaded from environment variables and have default values defined here.
"""
service_name: str = "avaaz-backend" # Used as a functional ID
environment: str = "development"
service_name: str = "avaaz-backend" # A unique functional identifier for the microservice
environment: str = "development" # Defines the current deployment stage (e.g., 'development', 'staging', 'production')
title: str = "Avaaz Language Tutoring API"
description: str ="""
description: str = """
# Avaaz Language Tutoring API
This API powers the **avaaz.ai** mobile and web applications, providing the robust backend services for our AI-driven oral language skills tutor. The platform is specifically engineered to help students achieve oral proficiency using adaptive, conversational AI agents.
@@ -22,14 +26,24 @@ class Settings(BaseSettings):
* **Cross-Platform Sync:** Ensures seamless learning continuity and progress synchronization across all user devices.
"""
version: str = "0.1.0"
version: str = "0.1.0" # The current semantic version of the API application
database_url: str = "postgresql+psycopg://postgres:postgres@postgres:5432/avaaz"
model_config = SettingsConfigDict(env_prefix="", case_sensitive=False)
# Use SecretStr to prevent accidental logging of credentials.
# Access the actual value using settings.database_url.get_secret_value()
database_url: SecretStr = SecretStr("postgresql+psycopg://postgres:postgres@postgres:5432/avaaz")
model_config = SettingsConfigDict(
env_prefix="", # Load variables without a specific prefix (e.g., `DATABASE_URL` instead of `APP_DATABASE_URL`)
case_sensitive=False # Environment variable names are treated as case-insensitive during loading
)
@lru_cache(maxsize=1)
def get_settings() -> Settings:
"""Return cached settings instance."""
"""
Return a cached singleton instance of the application settings.
This function leverages functools.lru_cache to ensure that environment variables
are read only once during the application's lifecycle, improving performance
and ensuring consistency across requests.
"""
return Settings()

View File

@@ -1,19 +1,28 @@
"""Application entrypoint and router wiring."""
"""
API Application Entrypoint and Router Wiring.
This module initializes the core FastAPI application instance, loads
configuration, applies middleware, and wires up all defined API routers.
"""
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from typing import List
from api.v1.router import router as api_v1_router
from operations.health.router import router as health_router
from core.config import get_settings, Settings # Import Settings type for clarity
from core.config import get_settings
def create_app(settings: Settings = get_settings()) -> FastAPI:
"""
Create and configure the FastAPI application instance.
def create_app() -> FastAPI:
"""Create and configure the FastAPI application."""
settings = get_settings()
Args:
settings: Configuration object from core.config. Defaults to current settings.
Returns:
A configured FastAPI application instance.
"""
app = FastAPI(
title=settings.title,
description=settings.description,
@@ -23,19 +32,25 @@ def create_app() -> FastAPI:
openapi_url="/openapi.json",
)
# CORS for local dev (frontend on 3000). Tighten/override in prod.
# Define allowed origins dynamically based on local dev environment needs
# In a production setting, this list would typically be sourced from environment variables.
allowed_origins: List[str] = ["http://localhost:3000", "http://127.0.0.1:3000"]
# Configure CORS middleware
# TODO: Tightly restrict origins in production deployment.
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "http://127.0.0.1:3000"],
allow_origins=allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include API routers
app.include_router(health_router)
app.include_router(api_v1_router, prefix="/api/v1")
return app
# Main entry point for services like Uvicorn (e.g., `uvicorn main:app --reload`)
app = create_app()