From 92fafa8785936bcfee25775fab7b7a7dd38e4e23 Mon Sep 17 00:00:00 2001 From: jay Date: Mon, 1 Jun 2026 02:19:14 +0000 Subject: [PATCH] Make the API read-only (healthz no longer runs init_db) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lets the API run as a read-only replica against a shared DB owned by the ingestion CLI — needed for the production split (Caddy-proxied API container reading the host-written database). Co-Authored-By: Claude Opus 4.8 (1M context) --- goodnews/api.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/goodnews/api.py b/goodnews/api.py index 35a1145..81c149f 100644 --- a/goodnews/api.py +++ b/goodnews/api.py @@ -28,7 +28,7 @@ from fastapi.staticfiles import StaticFiles from pydantic import BaseModel from . import feeds, queries -from .db import connect, init_db +from .db import connect from .filters import filter_articles, prefs_from_json from .hero import safe_to_lead from .llm import LocalModelClient @@ -218,9 +218,13 @@ def create_app() -> FastAPI: @app.get("/healthz") def healthz() -> dict: - with get_conn() as conn: - init_db(conn) - scored = conn.execute("SELECT COUNT(*) FROM article_scores").fetchone()[0] + # Read-only: the schema is owned by the ingestion CLI, so the API never + # writes (it can run as a read-only replica against a shared DB). + try: + with get_conn() as conn: + scored = conn.execute("SELECT COUNT(*) FROM article_scores").fetchone()[0] + except sqlite3.Error: + scored = 0 return {"status": "ok", "scored_articles": scored} @app.get("/api/categories", response_model=CategoriesResponse)