perf: speed up settings dialog + relocate settings entry point

- Parallelize the six celery inspect.*() calls in /library/maintenance/
  worker-status via asyncio.gather + to_thread, and drop per-call
  timeout from 1.0s to 0.5s. Endpoint goes from ~6.1s to ~0.54s — it
  was the sole bottleneck on opening the Settings dialog.
- SettingsDialog now fetches through React Query with enabled:isOpen,
  so reopening shows cached data instantly while a background refetch
  updates. Worker polling moved to refetchInterval. Loading spinners
  only show when there's no cached data yet, so background refetches
  don't keep them spinning.
- Move the Settings entry point from the TopBar to a pinned row at the
  bottom of the LeftSidebar so it sits alongside the other library
  controls. TopBar no longer takes onOpenSettings.
- Remove the "Scan all folders" bottom action from LeftSidebar — the
  same control already lives in Settings → Library → Re-scan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-09 16:31:52 +02:00
parent d6c667ae78
commit e51b93d59e
5 changed files with 131 additions and 116 deletions

View File

@@ -285,16 +285,31 @@ async def get_worker_status(db: AsyncSession = Depends(get_db)):
import redis as _redis
# ----- Celery inspect (workers + active tasks) -------------------------
# Each inspect.* call is a separate broadcast-and-wait with its own
# timeout, so running them serially multiplies the wait. Fan them out
# to threads and gather, collapsing 6 × timeout into ~1 × timeout.
# Timeout dropped to 0.5s — a responsive worker answers within a few
# ms; anything past that is effectively "not responding" for the
# purposes of a settings dashboard.
import asyncio
workers: list[dict] = []
inspect_error: Optional[str] = None
try:
inspect = celery_app.control.inspect(timeout=1.0)
ping = inspect.ping() or {}
active = inspect.active() or {}
reserved = inspect.reserved() or {}
scheduled = inspect.scheduled() or {}
stats = inspect.stats() or {}
active_queues = inspect.active_queues() or {}
inspect = celery_app.control.inspect(timeout=0.5)
ping, active, reserved, scheduled, stats, active_queues = await asyncio.gather(
asyncio.to_thread(inspect.ping),
asyncio.to_thread(inspect.active),
asyncio.to_thread(inspect.reserved),
asyncio.to_thread(inspect.scheduled),
asyncio.to_thread(inspect.stats),
asyncio.to_thread(inspect.active_queues),
)
ping = ping or {}
active = active or {}
reserved = reserved or {}
scheduled = scheduled or {}
stats = stats or {}
active_queues = active_queues or {}
worker_names = set(ping) | set(active) | set(stats)
for name in sorted(worker_names):