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:
@@ -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 fastapi.responses import Response
|
||||||
from sqlalchemy.orm import Session, joinedload, selectinload
|
from sqlalchemy.orm import Session, joinedload, selectinload
|
||||||
|
|
||||||
from ..crud import product_to_out, product_tracking, products_to_out_bulk
|
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 ..deps import get_current_user, require_admin
|
||||||
from ..models import (
|
from ..models import (
|
||||||
Barcode,
|
Barcode,
|
||||||
@@ -339,9 +339,23 @@ def delete_product_image(
|
|||||||
db.commit()
|
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)
|
@router.post("", response_model=ProductOut, status_code=status.HTTP_201_CREATED)
|
||||||
def create_product(
|
def create_product(
|
||||||
payload: ProductCreate,
|
payload: ProductCreate,
|
||||||
|
background_tasks: BackgroundTasks,
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
_: User = Depends(require_admin),
|
_: User = Depends(require_admin),
|
||||||
) -> ProductOut:
|
) -> ProductOut:
|
||||||
@@ -388,12 +402,13 @@ def create_product(
|
|||||||
apply_field_values(db, product, payload.field_values)
|
apply_field_values(db, product, payload.field_values)
|
||||||
except FieldError as exc:
|
except FieldError as exc:
|
||||||
raise HTTPException(status.HTTP_400_BAD_REQUEST, str(exc)) from 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.commit()
|
||||||
db.refresh(product)
|
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)
|
return product_to_out(db, product)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user