Sincroniza el scaffold canónico desde templates/web-backend-python/ del repo IDP. Reemplaza el placeholder mínimo previo (.gitea/workflows/ci.yaml, README.md, .gitignore, catalog-info.yaml) por el scaffold completo documentado en ADR-053 §3: - code/ — FastAPI app con /health (db check), /metrics, /demo estático, middleware correlation_id, settings Pydantic, db.py con SQLAlchemy - code/alembic/ — migración inicial vacía + env.py usando MIGRATION_DATABASE_URL - code/tests/ — pytest + httpx TestClient (test_health, test_demo) - helm/APP_NAME/ — chart con Deployment, Service, IngressRoute Traefik, NetworkPolicy, ServiceMonitor, Job alembic-upgrade como hook pre-upgrade,pre-install (backoffLimit: 0) - coralware-shape.yaml — manifiesto v1alpha1 del contrato del shape - claim-mariadb.yaml — AddonClaim declarativo (uso futuro ADR-052) - catalog-info.yaml — entidad Backstage actualizada - .gitea/workflows/APP_NAME-build.yaml — invoca reusable workflow ADR-038 + job helm-deploy con KUBECONFIG_TENANT_B64 Placeholders __APP_NAME__, __TIER__, __TENANT_ID__, __TENANT_ID_NODASHES__ serán sustituidos server-side por repo-provisioner cuando materialice el template para un tenant (pendiente — ADR-053 §11.5). El openspec/ del golden path NO se sincroniza al repo Gitea (gobernanza interna de Coralware). Refs: ADR-052, ADR-053, poc-nexobms.md (PoC NexoBMS Demetrio).
41 lines
982 B
Python
41 lines
982 B
Python
"""
|
|
Capa de conexión SQLAlchemy.
|
|
- engine único por proceso, configurado al startup
|
|
- sesiones por request (dependency injection FastAPI)
|
|
- ping ligero para /health
|
|
"""
|
|
|
|
from collections.abc import Iterator
|
|
|
|
from sqlalchemy import create_engine, text
|
|
from sqlalchemy.orm import Session, sessionmaker
|
|
|
|
from app.settings import settings
|
|
|
|
engine = create_engine(
|
|
settings.DATABASE_URL,
|
|
pool_pre_ping=True,
|
|
pool_recycle=3600,
|
|
)
|
|
|
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
|
|
|
|
def get_session() -> Iterator[Session]:
|
|
"""Dependency FastAPI: una sesión por request, cierre garantizado."""
|
|
db = SessionLocal()
|
|
try:
|
|
yield db
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
def db_alive() -> bool:
|
|
"""Ping de conexión usado por /health. Retorna False ante cualquier excepción."""
|
|
try:
|
|
with engine.connect() as conn:
|
|
conn.execute(text("SELECT 1"))
|
|
return True
|
|
except Exception:
|
|
return False
|