Public Access
feat(meals): enforce three lower-calorie dinners with media
This commit is contained in:
+27
-4
@@ -1,3 +1,4 @@
|
||||
from contextlib import asynccontextmanager
|
||||
from fastapi import FastAPI, Depends, HTTPException, Request
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
@@ -11,10 +12,34 @@ import logging
|
||||
logging.basicConfig(level=settings.LOG_LEVEL)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Auto-migrate on boot. Idempotent: alembic upgrade head is a no-op
|
||||
# when the schema is already at head. Catches the recurring failure
|
||||
# where the DB is at revision N but the image expects N+1 (e.g. a
|
||||
# new column like denial_expires_at), which would otherwise 500 the
|
||||
# first request that touches the new column. Skip when SKIP_AUTO_MIGRATE
|
||||
# is set (tests / read-only replicas).
|
||||
import os
|
||||
if not os.getenv("SKIP_AUTO_MIGRATE"):
|
||||
try:
|
||||
from alembic.config import Config
|
||||
from alembic import command
|
||||
cfg = Config("alembic.ini")
|
||||
command.upgrade(cfg, "head")
|
||||
logger.info("auto-migrate: alembic upgrade head OK")
|
||||
except Exception as e:
|
||||
# Don't crash boot — log loud so it's visible in `docker logs`.
|
||||
logger.error(f"auto-migrate FAILED: {e!r}")
|
||||
yield
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title="MealPlanner",
|
||||
description="Self-hosted meal planning system",
|
||||
version="0.1.0",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
# Serve generated recipe images from local filesystem.
|
||||
@@ -77,10 +102,8 @@ app.include_router(shopping_list.router, prefix="/api/shopping-list", tags=["sho
|
||||
app.include_router(pantry.router, prefix="/api/pantry", tags=["pantry"])
|
||||
app.include_router(admin.router, prefix="/api/admin", tags=["admin"])
|
||||
app.include_router(orchestrate_api.router, prefix="/api/orchestrate", tags=["orchestrate"])
|
||||
# Sprint 12: external recipe search (Spoonacular) + import.
|
||||
# Mounted BEFORE recipes_api.public_router so /search and /import are
|
||||
# not shadowed by the WIP's GET /{recipe_id} (which would 422 on a
|
||||
# non-UUID "search" path segment). See sprint15-verification.md.
|
||||
# Retired external search/import routes stay mounted before /{recipe_id}
|
||||
# so legacy clients receive 410 rather than UUID validation errors.
|
||||
app.include_router(recipe_search_api.router, prefix="/api/recipes", tags=["recipes"])
|
||||
app.include_router(ingredients_api.public_router)
|
||||
app.include_router(ingredients_api.admin_router)
|
||||
|
||||
Reference in New Issue
Block a user