uvicorn startup

This commit is contained in:
John Lancaster
2026-07-30 21:09:51 -05:00
parent d2b793ea69
commit 1cc2f319d5
3 changed files with 47 additions and 13 deletions
+20
View File
@@ -0,0 +1,20 @@
import uvicorn
from .config import LOGGING_CONFIG
from .config import get_settings
def main() -> None:
settings = get_settings()
uvicorn.run(
"transcription.app:create_app",
factory=True,
host=settings.server.host,
port=settings.server.port,
log_level=LOGGING_CONFIG.get("root", {}).get("level", "info").lower(),
reload=settings.server.reload,
)
if __name__ == "__main__":
main()
+9 -4
View File
@@ -16,6 +16,7 @@ from fastapi.staticfiles import StaticFiles
from .api.errors import register_error_handlers
from .api.health import router as health_router
from .config import Settings
from .config import configure_logging
from .config import get_settings
from .db import create_all
@@ -73,14 +74,14 @@ async def _recover_stale_processing_jobs(app: FastAPI) -> None:
logger.warning("Recovered %s stale processing job(s) at startup", recovered)
def create_app() -> FastAPI:
def create_app(settings: Settings | None = None) -> FastAPI:
"""Create and configure the FastAPI application."""
app = FastAPI(title="Transcription", lifespan=_lifespan)
settings = get_settings()
app.state.settings = settings
active_settings = settings or get_settings()
app.state.settings = active_settings
app.mount(
"/uploads",
StaticFiles(directory=settings.upload_dir, check_dir=False),
StaticFiles(directory=active_settings.upload_dir, check_dir=False),
name="uploads",
)
@@ -92,6 +93,10 @@ def create_app() -> FastAPI:
async def ui_redirect() -> RedirectResponse:
return RedirectResponse(url="/ui/upload", status_code=status.HTTP_307_TEMPORARY_REDIRECT)
@app.get("/healthz")
def health() -> dict[str, str]:
return {"status": "ok"}
register_error_handlers(app)
register_pages(app)
app.include_router(health_router)
+18 -9
View File
@@ -6,11 +6,13 @@ are resolved by the provider adapters, not here.
"""
import logging.config
from contextvars import ContextVar
from enum import StrEnum
from functools import cache
from pathlib import Path
from typing import Literal
from pydantic import BaseModel
from pydantic import ConfigDict
from pydantic import Field
from pydantic_settings import BaseSettings
from pydantic_settings import SettingsConfigDict
@@ -22,13 +24,26 @@ class Provider(StrEnum):
OPENROUTER = "openrouter"
class ServerSettings(BaseModel):
model_config = ConfigDict(frozen=True)
host: str = "0.0.0.0"
port: int = 8000
log_level: Literal["critical", "error", "warning", "info", "debug", "trace"] = "info"
reload: bool = False
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
cli_parse_args=True,
)
# --- NiceGUI Server ---
server: ServerSettings = Field(default_factory=ServerSettings)
# --- AI provider ---
provider: Provider = Provider.OPENROUTER
openrouter_api_key: str
@@ -64,15 +79,9 @@ class Settings(BaseSettings):
return self.environment in {"development", "test"}
_settings: ContextVar[Settings | None] = ContextVar("settings", default=None)
@cache
def get_settings(**kwargs) -> Settings:
settings = _settings.get()
if settings is None:
settings = Settings(**kwargs) # pyright: ignore[reportCallIssue]
_settings.set(settings)
return settings
return Settings(**kwargs)
LOGGING_CONFIG: dict[str, object] = {