fix: Rezeptverlauf-Bilder lokal speichern und Windows-Subprocess-Fix

- Bilder beim Extrahieren lokal cachen (data/images/{id}.ext) und über GET /api/history/{id}/image ausliefern; Löschen bei Verlaufseintrag-Entfernung
- history.db in ./data/ Volume verschoben, damit sie Container-Rebuilds überlebt
- yt-dlp Subprocess-Aufrufe auf Windows gefixt: run_in_executor statt asyncio.create_subprocess_exec (SelectorEventLoop-Kompatibilität)
- ./data:/app/data Docker-Volume für persistente Datenhaltung hinzugefügt
This commit is contained in:
Andre
2026-04-14 17:17:03 +02:00
parent 4de67f0192
commit c7582dafbb
13 changed files with 125 additions and 33 deletions
+16 -1
View File
@@ -1,6 +1,8 @@
"""GET /api/history, DELETE /api/history/{id}"""
"""GET /api/history, DELETE /api/history/{id}, GET /api/history/{id}/image"""
from fastapi import APIRouter, HTTPException
from fastapi.responses import FileResponse
from app.services.history_service import get_all, delete_recipe
from app.services import image_service
router = APIRouter()
@@ -13,8 +15,21 @@ async def get_history():
raise HTTPException(status_code=500, detail=str(e))
@router.get("/history/{history_id}/image")
async def get_history_image(history_id: int):
path = image_service.find_cached_image(history_id)
if path is None:
raise HTTPException(status_code=404, detail="No cached image")
ext_to_mime = {v: k for k, v in image_service.MIME_TO_EXT.items()}
media_type = ext_to_mime.get(path.suffix.lstrip("."), "image/jpeg")
return FileResponse(path, media_type=media_type)
@router.delete("/history/{history_id}")
async def delete_history_entry(history_id: int):
cached = image_service.find_cached_image(history_id)
if cached:
cached.unlink(missing_ok=True)
try:
delete_recipe(history_id)
return {"status": "ok"}