diff --git a/kjvstudy_org/routes/about.py b/kjvstudy_org/routes/about.py index 4686272..854e2e0 100644 --- a/kjvstudy_org/routes/about.py +++ b/kjvstudy_org/routes/about.py @@ -1,4 +1,5 @@ """About routes - stats, cross-references index, and about page.""" +import asyncio import json import re from collections import defaultdict @@ -22,12 +23,11 @@ def init_templates(t: Jinja2Templates): # ============================================================================= -# Routes +# Helper Functions (run in thread pool) # ============================================================================= -@router.get("/about/stats", response_class=HTMLResponse) -async def stats(request: Request): - """Hidden statistics page - comprehensive site metrics""" +def _compute_stats() -> dict: + """Compute all statistics - runs in thread pool to avoid blocking.""" data_dir = Path(__file__).parent.parent / "data" # Bible statistics @@ -148,7 +148,7 @@ async def stats(request: Request): total_hebrew_entries = 0 total_greek_entries = 0 - stats_data = { + return { 'bible': { 'total_verses': total_verses, 'total_books': total_books, @@ -207,27 +207,9 @@ async def stats(request: Request): } } - books = bible.get_books() - breadcrumbs = [ - {"text": "Home", "url": "/"}, - {"text": "About", "url": "/about"}, - {"text": "Statistics", "url": None} - ] - return templates.TemplateResponse( - "stats.html", - { - "request": request, - "books": books, - "stats": stats_data, - "breadcrumbs": breadcrumbs, - } - ) - - -@router.get("/about/cross-references", response_class=HTMLResponse) -async def cross_references_index(request: Request): - """Cross-references index - list all verses with cross-references""" +def _compute_crossref_index() -> tuple: + """Compute cross-reference index - runs in thread pool.""" data_dir = Path(__file__).parent.parent / "data" / "cross_references" # Build index of all verses with cross-references, grouped by book @@ -273,6 +255,43 @@ async def cross_references_index(request: Request): for verses in chapters.values() ) + return crossref_index, total_books, total_verses, total_refs + + +# ============================================================================= +# Routes +# ============================================================================= + +@router.get("/about/stats", response_class=HTMLResponse) +async def stats(request: Request): + """Hidden statistics page - comprehensive site metrics""" + # Run heavy computation in thread pool + stats_data = await asyncio.to_thread(_compute_stats) + + books = bible.get_books() + breadcrumbs = [ + {"text": "Home", "url": "/"}, + {"text": "About", "url": "/about"}, + {"text": "Statistics", "url": None} + ] + + return templates.TemplateResponse( + "stats.html", + { + "request": request, + "books": books, + "stats": stats_data, + "breadcrumbs": breadcrumbs, + } + ) + + +@router.get("/about/cross-references", response_class=HTMLResponse) +async def cross_references_index(request: Request): + """Cross-references index - list all verses with cross-references""" + # Run heavy I/O in thread pool + crossref_index, total_books, total_verses, total_refs = await asyncio.to_thread(_compute_crossref_index) + books = bible.get_books() breadcrumbs = [ {"text": "Home", "url": "/"}, diff --git a/kjvstudy_org/routes/commentary.py b/kjvstudy_org/routes/commentary.py index 467719c..ef22966 100644 --- a/kjvstudy_org/routes/commentary.py +++ b/kjvstudy_org/routes/commentary.py @@ -5,8 +5,10 @@ This module contains the commentary generation system including: - Helper functions for generating theological commentary - Book summaries, chapter overviews, and verse analysis """ +import asyncio import json import random +from collections import defaultdict from functools import lru_cache from pathlib import Path from fastapi import APIRouter, Request, HTTPException @@ -20,10 +22,8 @@ router = APIRouter(tags=["Commentary"]) templates = None -@router.get("/about/commentary", response_class=HTMLResponse) -async def commentary_index(request: Request): - """Commentary index - list all verses with commentary""" - from collections import defaultdict +def _compute_commentary_index() -> tuple: + """Compute commentary index - runs in thread pool.""" from ..utils.books import OT_BOOKS, NT_BOOKS data_dir = Path(__file__).parent.parent / "data" / "verse_commentary" @@ -58,6 +58,15 @@ async def commentary_index(request: Request): for verses in chapters.values() ) + return commentary_index, total_books, total_verses + + +@router.get("/about/commentary", response_class=HTMLResponse) +async def commentary_index(request: Request): + """Commentary index - list all verses with commentary""" + # Run heavy I/O in thread pool + commentary_idx, total_books, total_verses = await asyncio.to_thread(_compute_commentary_index) + breadcrumbs = [ {"text": "Home", "url": "/"}, {"text": "About", "url": "/about"}, @@ -73,7 +82,7 @@ async def commentary_index(request: Request): { "request": request, "books": books, - "commentary_index": commentary_index, + "commentary_index": commentary_idx, "total_books": total_books, "total_verses": total_verses, "breadcrumbs": breadcrumbs, diff --git a/kjvstudy_org/routes/misc.py b/kjvstudy_org/routes/misc.py index e17e1c9..37ada55 100644 --- a/kjvstudy_org/routes/misc.py +++ b/kjvstudy_org/routes/misc.py @@ -413,7 +413,8 @@ async def og_image_verse( # Return default image if verse not found from pathlib import Path as PathLib default_path = PathLib(__file__).parent.parent / "static" / "og-image.png" - return Response(content=default_path.read_bytes(), media_type="image/png") + content = await asyncio.to_thread(default_path.read_bytes) + return Response(content=content, media_type="image/png") title = f"{book} {chapter}:{verse}" cache_key = f"verse:{book}:{chapter}:{verse}"