Backend: Bild beim Anlegen im Hintergrund holen (Anlegen viel schneller)

create_product holte ein per URL vorgeschlagenes Bild synchron waehrend des
Anlegens (httpx.get) - das blockierte die Antwort um mehrere Sekunden. Der
Abruf laeuft jetzt als BackgroundTask mit eigener Session nach der Antwort; das
Anlegen kehrt sofort zurueck, das Bild erscheint kurz danach.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-29 12:26:43 +02:00
parent 4728a839ea
commit 85ab62359a

View File

@@ -1,9 +1,9 @@
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
from fastapi import APIRouter, BackgroundTasks, Depends, File, HTTPException, UploadFile, status
from fastapi.responses import Response
from sqlalchemy.orm import Session, joinedload, selectinload
from ..crud import product_to_out, product_tracking, products_to_out_bulk
from ..database import get_db
from ..database import SessionLocal, get_db
from ..deps import get_current_user, require_admin
from ..models import (
Barcode,
@@ -339,9 +339,23 @@ def delete_product_image(
db.commit()
def _store_product_image_bg(product_id: int, url: str) -> None:
"""Bild nach dem Anlegen im Hintergrund holen (eigene Session), damit das
Anlegen nicht auf den (langsamen) Netzwerk-Abruf wartet."""
db = SessionLocal()
try:
product = db.get(Product, product_id)
if product is not None:
images.store(db, product, url)
db.commit()
finally:
db.close()
@router.post("", response_model=ProductOut, status_code=status.HTTP_201_CREATED)
def create_product(
payload: ProductCreate,
background_tasks: BackgroundTasks,
db: Session = Depends(get_db),
_: User = Depends(require_admin),
) -> ProductOut:
@@ -388,12 +402,13 @@ def create_product(
apply_field_values(db, product, payload.field_values)
except FieldError as exc:
raise HTTPException(status.HTTP_400_BAD_REQUEST, str(exc)) from exc
if product.image_url:
# Gleich beim Anlegen holen. Schlaegt es fehl, entsteht kein Fehler:
# Ein fehlendes Bild darf das Anlegen eines Artikels nicht verhindern.
images.store(db, product, product.image_url)
db.commit()
db.refresh(product)
if product.image_url:
# Bild erst NACH dem Anlegen im Hintergrund holen der Netzwerk-Abruf
# soll das Anlegen nicht mehrere Sekunden blockieren. Schlägt er fehl,
# bleibt der Artikel trotzdem angelegt (nur ohne Bild).
background_tasks.add_task(_store_product_image_bg, product.id, product.image_url)
return product_to_out(db, product)