diff --git a/backend/src/media_library_viewer_api/routers/media.py b/backend/src/media_library_viewer_api/routers/media.py index eda060e..e4174c1 100644 --- a/backend/src/media_library_viewer_api/routers/media.py +++ b/backend/src/media_library_viewer_api/routers/media.py @@ -133,20 +133,27 @@ def get_index_status(index: MediaIndex = Depends(get_media_index)) -> dict[str, @router.post("/build", status_code=status.HTTP_202_ACCEPTED) def post_build_index( - client: JellyfinClient = Depends(get_jellyfin_client), - user_id: str = Depends(get_user_id), jellyfin_service_id: str | None = None, index: MediaIndex = Depends(get_media_index), ) -> dict[str, Any]: - """Start a media index build in a subprocess worker.""" + """Start a media index build in a subprocess worker. + + The worker resolves its own Jellyfin connection from the settings store. + We do NOT use Depends(get_jellyfin_client) here because the worker runs + in a separate process and needs to resolve the client itself. Validating + the connection here would fail if Jellyfin is briefly unreachable, even + though the build just needs to start the worker process. + """ with _build_lock: current_status = _clean_stale_build_state(index) if current_status.build_running and _pid_is_alive(current_status.build_pid): logger.warning("Media build already running pid=%s", current_status.build_pid) raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Media index build already in progress") - libraries = client.libraries(user_id) - logger.info("Starting media index build user_id=%s libraries=%s", user_id, len(libraries)) + logger.info( + "Starting media index build service_id=%s", + jellyfin_service_id or "", + ) process = _start_worker(index, jellyfin_service_id or "") _set_build_metadata( index, @@ -159,7 +166,7 @@ def post_build_index( "build_items_total": 0, "build_current_library": "", "build_library_index": 0, - "build_libraries_total": len(libraries), + "build_libraries_total": 0, "build_library_progress": None, "build_library_items_processed": 0, "build_library_items_total": 0, diff --git a/backend/tests/test_api.py b/backend/tests/test_api.py index ba29134..42fde98 100644 --- a/backend/tests/test_api.py +++ b/backend/tests/test_api.py @@ -363,7 +363,7 @@ class TestMediaIndexApi: assert data["status"] == "started" assert data["build_running"] is True assert data["build_stage"] == "queued" - assert data["build_libraries_total"] == len(mock_jellyfin.libraries.return_value) + assert data["build_libraries_total"] == 0 assert data["build_pid"] == 4321 start_worker.assert_called_once() finally: diff --git a/frontend/src/components/WidgetConfigDialog.tsx b/frontend/src/components/WidgetConfigDialog.tsx index 90b8a66..ef341a4 100644 --- a/frontend/src/components/WidgetConfigDialog.tsx +++ b/frontend/src/components/WidgetConfigDialog.tsx @@ -237,8 +237,9 @@ export function WidgetConfigDialog({ useEffect(() => { if (open && editWidgetId) { // Search both owned widgets and referenced widgets. - const target = instances.find((w) => w.id === editWidgetId) - ?? references.find((r) => r.widget.id === editWidgetId)?.widget; + const target = + instances.find((w) => w.id === editWidgetId) ?? + references.find((r) => r.widget.id === editWidgetId)?.widget; if (target) { startEdit(target); } diff --git a/frontend/src/hooks/useMedia.ts b/frontend/src/hooks/useMedia.ts index 2b89d7a..5a9577f 100644 --- a/frontend/src/hooks/useMedia.ts +++ b/frontend/src/hooks/useMedia.ts @@ -54,6 +54,10 @@ export function useBuildIndex(jellyfinServiceId?: string) { onSuccess: () => { invalidateMedia(queryClient); }, + onError: () => { + // Invalidate status so the UI reflects the current (non-building) state. + invalidateMedia(queryClient); + }, }); } diff --git a/frontend/src/pages/service-tabs/MediaTab.tsx b/frontend/src/pages/service-tabs/MediaTab.tsx index 74097a7..3c972d9 100644 --- a/frontend/src/pages/service-tabs/MediaTab.tsx +++ b/frontend/src/pages/service-tabs/MediaTab.tsx @@ -352,6 +352,11 @@ export function MediaTab({ instance }: { instance: ServiceInstance }) { > {buildIndex.isPending || buildRunning ? "Building..." : "Build index"} + {buildIndex.isError ? ( + + Build failed: {buildIndex.error instanceof Error ? buildIndex.error.message : "Unknown error"} + + ) : null} {buildRunning && ( <>