Skip to content

Commit 3203a0a

Browse files
fastapi-sqlalchemy-pg-catalog/app: clearer DATABASE_URL error + async-safe create_all
Two nits from the Copilot review: * DATABASE_URL: `os.environ["DATABASE_URL"]` raised a bare KeyError at import time, which surfaces as a noisy traceback in container logs with no hint about what's missing. Switched to os.getenv with an explicit RuntimeError that names the env var and gives a sample URL format. * lifespan: `Base.metadata.create_all(engine)` is synchronous psycopg2 I/O running inside an async lifespan, blocking uvicorn's event loop until pg_class probe + any CREATE TABLE round-trips complete. Switched to `await asyncio.to_thread(...)` so the loop stays responsive. For this minimal repro the difference is small, but the pattern is the right FastAPI shape for any startup that touches a sync DB driver. Signed-off-by: Akash Kumar <meakash7902@gmail.com>
1 parent ec3174e commit 3203a0a

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

  • fastapi-sqlalchemy-pg-catalog/app

fastapi-sqlalchemy-pg-catalog/app/main.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
(simple-query path, ``dispatchBySQLHash``).
1717
"""
1818

19+
import asyncio
1920
import logging
2021
import os
2122
import sys
@@ -32,7 +33,12 @@
3233
)
3334
log = logging.getLogger("repro")
3435

35-
DATABASE_URL = os.environ["DATABASE_URL"]
36+
DATABASE_URL = os.getenv("DATABASE_URL")
37+
if not DATABASE_URL:
38+
raise RuntimeError(
39+
"DATABASE_URL is required (e.g. postgresql+psycopg2://user:pass@host:5432/db). "
40+
"Set it in docker-compose env or in the host shell before launching uvicorn."
41+
)
3642
# SQL echo is INTENTIONALLY on by default — this is a sample for
3743
# demonstrating the dispatcher's simple-Query catalog path, and seeing
3844
# the actual SQLAlchemy queries (pg_catalog.version, pg_class probe,
@@ -59,7 +65,13 @@ class Project(Base):
5965
@asynccontextmanager
6066
async def lifespan(_: FastAPI):
6167
log.info("startup: running Base.metadata.create_all (pg_class probe expected)")
62-
Base.metadata.create_all(engine)
68+
# create_all does synchronous psycopg2 I/O. Offload to a thread so
69+
# uvicorn's event loop stays responsive (otherwise any other
70+
# async work scheduled on startup would block until the pg_class
71+
# probe + any CREATE TABLE round-trips complete). For this minimal
72+
# repro the difference is small, but the pattern is the right
73+
# FastAPI shape for any startup that touches a sync DB driver.
74+
await asyncio.to_thread(Base.metadata.create_all, engine)
6375
log.info("startup: create_all complete")
6476
yield
6577

0 commit comments

Comments
 (0)