8f1fc458f6
- Run now (jobs and playlists), dedup scan, genre preview/apply, and manual import now dispatch via BackgroundTasks and redirect immediately, instead of awaiting a job that can run for the better part of an hour and hang the browser or reverse proxy. Progress shows in the Jobs runs table (which already polls); if the pipeline is busy the run records skipped_lock there. - Fix the import banner, which claimed work was ongoing after the request had actually blocked to completion; it now reflects the backgrounded start. - Add confirmation prompts to the dedup per-row and bulk delete and to "Fix genres now", matching the existing confirms on library and playlist deletes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
2.1 KiB
Python
61 lines
2.1 KiB
Python
from fastapi import APIRouter, BackgroundTasks, Depends, Form, Request, UploadFile
|
|
from fastapi.responses import RedirectResponse
|
|
from fastapi.templating import Jinja2Templates
|
|
|
|
from app.db import SessionLocal, get_db
|
|
from app.models import Playlist
|
|
from app.security.deps import require_auth
|
|
from app.services import manual_import
|
|
|
|
|
|
async def _run_import_bg(source: str | None, playlist_name: str | None, imported_by: str) -> None:
|
|
"""Import in the background with its own DB session. The request's session
|
|
is closed once the response is sent, so we cannot reuse it here."""
|
|
db = SessionLocal()
|
|
try:
|
|
await manual_import.import_track(db, source, playlist_name, imported_by)
|
|
finally:
|
|
db.close()
|
|
|
|
router = APIRouter(prefix="/import", tags=["import"])
|
|
templates = Jinja2Templates(directory="app/templates")
|
|
|
|
|
|
@router.get("")
|
|
async def import_index(request: Request, user: dict = Depends(require_auth), db=Depends(get_db)):
|
|
from sqlalchemy import select
|
|
|
|
contents = manual_import.list_import_me_contents()
|
|
playlists = list(db.execute(select(Playlist).order_by(Playlist.name)).scalars())
|
|
return templates.TemplateResponse(
|
|
request,
|
|
"import/index.html",
|
|
{"contents": contents, "playlists": playlists},
|
|
)
|
|
|
|
|
|
@router.post("/upload")
|
|
async def upload(
|
|
request: Request,
|
|
file: UploadFile,
|
|
user: dict = Depends(require_auth),
|
|
):
|
|
content = await file.read()
|
|
manual_import.save_uploaded_file(file.filename, content)
|
|
return RedirectResponse(url="/import", status_code=303)
|
|
|
|
|
|
@router.post("/run")
|
|
async def run_import(
|
|
background: BackgroundTasks,
|
|
source: str = Form(""),
|
|
playlist_name: str = Form(""),
|
|
user: dict = Depends(require_auth),
|
|
):
|
|
# Importing (tag, prep, beets import, rescan) can take a while, so run it in
|
|
# the background and redirect immediately. Progress and the outcome show up
|
|
# under Settings then Jobs.
|
|
imported_by = user.get("email") or user.get("sub", "unknown")
|
|
background.add_task(_run_import_bg, source or None, playlist_name or None, imported_by)
|
|
return RedirectResponse(url="/import?started=1", status_code=303)
|