Move slug fetch to background thread to prevent UI freeze

_fetch_my_slug() was making a synchronous HTTP request on the main thread
during tool selection, which froze the UI if the server was slow or
unreachable. Moved the /me call into StatusSyncWorker which already runs
in a background thread on page load. The slug is delivered via a
slug_fetched signal and the rate button re-evaluates when it arrives.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rob 2026-01-30 03:11:49 -04:00
parent fe5b2047a9
commit 58e270746d
1 changed files with 16 additions and 25 deletions

View File

@ -26,6 +26,7 @@ class StatusSyncWorker(QThread):
"""Background worker to sync tool statuses from registry using hash-based batch lookup."""
finished = Signal()
tool_updated = Signal(str) # Emits tool name when status changes
slug_fetched = Signal(str) # Emits current user's slug
def __init__(self, tool_names: list):
super().__init__()
@ -44,6 +45,15 @@ class StatusSyncWorker(QThread):
client = RegistryClient()
client.token = config.registry.token
# Fetch current user slug (needed for rating ownership checks)
try:
me = client.get_me()
slug = me.get("slug")
if slug:
self.slug_fetched.emit(slug)
except Exception:
pass
# Collect all tools that have a registry_hash
# Multiple tools can share the same hash (copies/forks)
tools_dir = get_tools_dir()
@ -600,6 +610,7 @@ class ToolsPage(QWidget):
# Start new sync
self._sync_worker = StatusSyncWorker(published_tools)
self._sync_worker.tool_updated.connect(self._on_tool_status_updated)
self._sync_worker.slug_fetched.connect(self._on_slug_fetched)
self._sync_worker.finished.connect(self._on_sync_finished)
self._syncing = True
self._sync_worker.start()
@ -819,10 +830,6 @@ class ToolsPage(QWidget):
self.info_text.setHtml("\n".join(lines))
# Ensure slug is available for own published tools (fallback owner).
if not self._my_slug_fetched:
self._fetch_my_slug()
# Update rating bar below the detail text
self._update_rating_bar(qname)
@ -1004,31 +1011,15 @@ class ToolsPage(QWidget):
else:
self.btn_rate.setText("Rate Tool")
def _fetch_my_slug(self):
"""Fetch and cache the current user's slug."""
if self._my_slug_fetched:
return
def _on_slug_fetched(self, slug: str):
"""Handle slug fetched from background sync."""
self._my_slug = slug
self._my_slug_fetched = True
config = load_config()
if not config.registry.token:
return
try:
from ...registry_client import RegistryClient, RegistryError
client = RegistryClient()
client.token = config.registry.token
me = client.get_me()
self._my_slug = me.get("slug")
except Exception:
pass
# Re-evaluate the rate button now that we know the owner
self._update_rate_button()
def _fetch_rating_if_needed(self, tool_name: str):
"""Fetch rating data for a registry tool if not cached."""
# Ensure we have the user slug (non-blocking first time; runs in main thread once)
if not self._my_slug_fetched:
self._fetch_my_slug()
registry_info = get_tool_registry_info(tool_name, self._my_slug)
if not registry_info:
return