More dead code removal after desktop app removal
This commit is contained in:
parent
a17e1030d3
commit
64d9db57ea
3 changed files with 24 additions and 480 deletions
|
|
@ -1,35 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Conditional PyQt6 import for backward compatibility with GUI version
|
||||
try:
|
||||
from PyQt6.QtCore import QThread, pyqtSignal
|
||||
QT_AVAILABLE = True
|
||||
except ImportError:
|
||||
QT_AVAILABLE = False
|
||||
# Define dummy classes for headless operation
|
||||
class QThread:
|
||||
def __init__(self):
|
||||
self.callbacks = {}
|
||||
def start(self):
|
||||
import threading
|
||||
self.thread = threading.Thread(target=self.run)
|
||||
self.thread.daemon = True
|
||||
self.thread.start()
|
||||
def wait(self):
|
||||
if hasattr(self, 'thread'):
|
||||
self.thread.join()
|
||||
def emit_signal(self, signal_name, *args):
|
||||
if signal_name in self.callbacks:
|
||||
for callback in self.callbacks[signal_name]:
|
||||
try:
|
||||
callback(*args)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in callback for {signal_name}: {e}")
|
||||
def connect_signal(self, signal_name, callback):
|
||||
if signal_name not in self.callbacks:
|
||||
self.callbacks[signal_name] = []
|
||||
self.callbacks[signal_name].append(callback)
|
||||
|
||||
import threading
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from typing import Optional, List, Callable
|
||||
|
|
@ -42,32 +12,19 @@ from config.settings import config_manager
|
|||
|
||||
logger = get_logger("database_update_worker")
|
||||
|
||||
class DatabaseUpdateWorker(QThread):
|
||||
"""Worker thread for updating SoulSync database with media server library data (Plex or Jellyfin)"""
|
||||
|
||||
# Qt signals (only available when PyQt6 is installed)
|
||||
if QT_AVAILABLE:
|
||||
progress_updated = pyqtSignal(str, int, int, float) # current_item, processed, total, percentage
|
||||
artist_processed = pyqtSignal(str, bool, str, int, int) # artist_name, success, details, albums_count, tracks_count
|
||||
finished = pyqtSignal(int, int, int, int, int) # total_artists, total_albums, total_tracks, successful, failed
|
||||
error = pyqtSignal(str) # error_message
|
||||
phase_changed = pyqtSignal(str) # current_phase (artists, albums, tracks)
|
||||
class DatabaseUpdateWorker:
|
||||
"""Worker for updating SoulSync database with media server library data."""
|
||||
|
||||
def __init__(self, media_client, database_path: str = "database/music_library.db", full_refresh: bool = False, server_type: str = "plex", force_sequential: bool = False):
|
||||
super().__init__()
|
||||
|
||||
# Force sequential processing for web server mode to avoid threading issues
|
||||
self.force_sequential = force_sequential
|
||||
|
||||
# Initialize signal callbacks for headless mode
|
||||
if not QT_AVAILABLE:
|
||||
self.callbacks = {
|
||||
'progress_updated': [],
|
||||
'artist_processed': [],
|
||||
'finished': [],
|
||||
'error': [],
|
||||
'phase_changed': []
|
||||
}
|
||||
self.callbacks = {
|
||||
'progress_updated': [],
|
||||
'artist_processed': [],
|
||||
'finished': [],
|
||||
'error': [],
|
||||
'phase_changed': [],
|
||||
}
|
||||
|
||||
# Support both old plex_client parameter and new media_client parameter for backward compatibility
|
||||
if hasattr(media_client, '__class__') and 'plex' in media_client.__class__.__name__.lower():
|
||||
|
|
@ -116,19 +73,16 @@ class DatabaseUpdateWorker(QThread):
|
|||
self.database: Optional[MusicDatabase] = None
|
||||
|
||||
def _emit_signal(self, signal_name: str, *args):
|
||||
"""Emit a signal in both Qt and headless modes"""
|
||||
if QT_AVAILABLE and hasattr(self, signal_name):
|
||||
# Qt mode - use actual signal
|
||||
getattr(self, signal_name).emit(*args)
|
||||
elif not QT_AVAILABLE:
|
||||
# Headless mode - use callback system
|
||||
self.emit_signal(signal_name, *args)
|
||||
"""Emit a signal through the callback registry."""
|
||||
for callback in self.callbacks.get(signal_name, []):
|
||||
try:
|
||||
callback(*args)
|
||||
except Exception as e:
|
||||
logger.error(f"Error in callback for {signal_name}: {e}")
|
||||
|
||||
def connect_callback(self, signal_name: str, callback: Callable):
|
||||
"""Connect a callback for headless mode"""
|
||||
if not QT_AVAILABLE:
|
||||
self.connect_signal(signal_name, callback)
|
||||
# In Qt mode, use the normal signal.connect() method
|
||||
"""Connect a callback for progress notifications."""
|
||||
self.callbacks.setdefault(signal_name, []).append(callback)
|
||||
|
||||
def stop(self):
|
||||
"""Stop the database update process"""
|
||||
|
|
@ -1261,8 +1215,8 @@ class DatabaseUpdateWorker(QThread):
|
|||
logger.error(f"Error processing artist {getattr(artist, 'title', 'Unknown')}: {e}")
|
||||
return (getattr(artist, 'title', 'Unknown'), False, f"Error: {str(e)}", 0, 0)
|
||||
|
||||
# Process artists - use sequential processing in web server mode to avoid threading issues
|
||||
if not QT_AVAILABLE or self.force_sequential:
|
||||
# Process artists sequentially when requested (the web server uses this path).
|
||||
if self.force_sequential:
|
||||
# Sequential processing for web server mode
|
||||
for i, artist in enumerate(artists):
|
||||
if self.should_stop:
|
||||
|
|
@ -1277,7 +1231,7 @@ class DatabaseUpdateWorker(QThread):
|
|||
# Emit progress signal
|
||||
self._emit_signal('artist_processed', artist_name, success, details, album_count, track_count)
|
||||
else:
|
||||
# Process artists in parallel using ThreadPoolExecutor (Qt mode only)
|
||||
# Parallel processing for local/manual runs
|
||||
with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
|
||||
# Submit all tasks
|
||||
future_to_artist = {executor.submit(process_single_artist, artist): artist
|
||||
|
|
@ -1409,71 +1363,3 @@ class DatabaseUpdateWorker(QThread):
|
|||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in run_with_callback: {e}")
|
||||
|
||||
class DatabaseStatsWorker(QThread):
|
||||
"""Simple worker for getting database statistics without blocking UI"""
|
||||
|
||||
# Qt signals (only available when PyQt6 is installed)
|
||||
if QT_AVAILABLE:
|
||||
stats_updated = pyqtSignal(dict) # Database statistics
|
||||
|
||||
def __init__(self, database_path: str = "database/music_library.db"):
|
||||
super().__init__()
|
||||
self.database_path = database_path
|
||||
self.should_stop = False
|
||||
|
||||
# Initialize signal callbacks for headless mode
|
||||
if not QT_AVAILABLE:
|
||||
self.callbacks = {
|
||||
'stats_updated': []
|
||||
}
|
||||
|
||||
def stop(self):
|
||||
"""Stop the worker"""
|
||||
self.should_stop = True
|
||||
|
||||
def _emit_signal(self, signal_name: str, *args):
|
||||
"""Emit a signal in both Qt and headless modes"""
|
||||
if QT_AVAILABLE and hasattr(self, signal_name):
|
||||
# Qt mode - use actual signal
|
||||
getattr(self, signal_name).emit(*args)
|
||||
elif not QT_AVAILABLE:
|
||||
# Headless mode - use callback system
|
||||
self.emit_signal(signal_name, *args)
|
||||
|
||||
def connect_callback(self, signal_name: str, callback: Callable):
|
||||
"""Connect a callback for headless mode"""
|
||||
if not QT_AVAILABLE:
|
||||
self.connect_signal(signal_name, callback)
|
||||
# In Qt mode, use the normal signal.connect() method
|
||||
|
||||
def run(self):
|
||||
"""Get database statistics and full info including last refresh"""
|
||||
try:
|
||||
if self.should_stop:
|
||||
return
|
||||
|
||||
database = get_database(self.database_path)
|
||||
if self.should_stop:
|
||||
return
|
||||
|
||||
# Get database info for active server (server-aware statistics)
|
||||
info = database.get_database_info_for_server()
|
||||
if not self.should_stop:
|
||||
self._emit_signal('stats_updated', info)
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting database stats: {e}")
|
||||
if not self.should_stop:
|
||||
# Import here to avoid circular imports
|
||||
from config.settings import config_manager
|
||||
active_server = config_manager.get_active_media_server()
|
||||
|
||||
self._emit_signal('stats_updated', {
|
||||
'artists': 0,
|
||||
'albums': 0,
|
||||
'tracks': 0,
|
||||
'database_size_mb': 0.0,
|
||||
'last_update': None,
|
||||
'last_full_refresh': None,
|
||||
'server_source': active_server
|
||||
})
|
||||
|
|
@ -1,342 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import threading
|
||||
import time
|
||||
from utils.logging_config import get_logger
|
||||
|
||||
logger = get_logger("plex_scan_manager")
|
||||
|
||||
class PlexScanManager:
|
||||
"""
|
||||
Smart Plex library scan manager with debouncing and scan-aware follow-up logic.
|
||||
|
||||
Features:
|
||||
- Debounces multiple scan requests to prevent spam
|
||||
- Tracks downloads that happen during active scans
|
||||
- Automatically triggers follow-up scans when needed
|
||||
- Thread-safe operation
|
||||
"""
|
||||
|
||||
def __init__(self, plex_client, delay_seconds: int = 60):
|
||||
"""
|
||||
Initialize the scan manager.
|
||||
|
||||
Args:
|
||||
plex_client: PlexClient instance with trigger_library_scan method
|
||||
delay_seconds: Debounce delay in seconds (default 60s)
|
||||
"""
|
||||
self.plex_client = plex_client
|
||||
self.delay = delay_seconds
|
||||
self._timer = None
|
||||
self._scan_in_progress = False
|
||||
self._downloads_during_scan = False
|
||||
self._lock = threading.Lock()
|
||||
self._scan_completion_callbacks = [] # List of callback functions to call when scan completes
|
||||
self._scan_start_time = None # Track when scan started for timeout
|
||||
self._max_scan_time = 1800 # Maximum scan time in seconds (30 minutes)
|
||||
|
||||
# New periodic update system
|
||||
self._periodic_update_timer = None # Timer for 5-minute periodic updates
|
||||
self._periodic_update_interval = 300 # 5 minutes in seconds
|
||||
self._is_doing_periodic_updates = False # Track if we're in periodic update mode
|
||||
self._shutting_down = False
|
||||
|
||||
logger.info(f"PlexScanManager initialized with {delay_seconds}s debounce delay")
|
||||
|
||||
def request_scan(self, reason: str = "Download completed"):
|
||||
"""
|
||||
Request a library scan with smart debouncing logic.
|
||||
|
||||
Args:
|
||||
reason: Optional reason for the scan request (for logging)
|
||||
"""
|
||||
logger.info(f"DEBUG: Plex scan requested - reason: {reason}")
|
||||
with self._lock:
|
||||
if self._shutting_down:
|
||||
logger.debug("Plex scan request ignored during shutdown")
|
||||
return
|
||||
if self._scan_in_progress:
|
||||
# Plex is currently scanning - mark that we need another scan later
|
||||
self._downloads_during_scan = True
|
||||
logger.info(f"Plex scan in progress - queueing follow-up scan ({reason})")
|
||||
return
|
||||
|
||||
# Cancel any existing timer and start a new one
|
||||
if self._timer:
|
||||
self._timer.cancel()
|
||||
logger.debug(f"Resetting scan timer ({reason})")
|
||||
else:
|
||||
logger.info(f"Plex scan queued - will execute in {self.delay}s ({reason})")
|
||||
|
||||
# Start the debounce timer
|
||||
self._timer = threading.Timer(self.delay, self._execute_scan)
|
||||
self._timer.daemon = True
|
||||
self._timer.start()
|
||||
|
||||
def add_scan_completion_callback(self, callback):
|
||||
"""
|
||||
Add a callback function to be called when scan completes.
|
||||
|
||||
Args:
|
||||
callback: Function to call when scan completes (no arguments)
|
||||
"""
|
||||
with self._lock:
|
||||
if callback not in self._scan_completion_callbacks:
|
||||
self._scan_completion_callbacks.append(callback)
|
||||
logger.info(f"DEBUG: Added scan completion callback: {callback.__name__}")
|
||||
logger.info(f"DEBUG: Total callbacks registered: {len(self._scan_completion_callbacks)}")
|
||||
|
||||
def remove_scan_completion_callback(self, callback):
|
||||
"""
|
||||
Remove a previously registered callback.
|
||||
|
||||
Args:
|
||||
callback: Function to remove from callbacks
|
||||
"""
|
||||
with self._lock:
|
||||
if callback in self._scan_completion_callbacks:
|
||||
self._scan_completion_callbacks.remove(callback)
|
||||
logger.debug(f"Removed scan completion callback: {callback.__name__}")
|
||||
|
||||
def _execute_scan(self):
|
||||
"""Execute the actual Plex library scan"""
|
||||
with self._lock:
|
||||
if self._shutting_down:
|
||||
logger.debug("Plex scan execution skipped during shutdown")
|
||||
return
|
||||
if self._scan_in_progress:
|
||||
logger.warning("Scan already in progress - skipping duplicate execution")
|
||||
return
|
||||
|
||||
self._scan_in_progress = True
|
||||
self._downloads_during_scan = False
|
||||
self._timer = None
|
||||
self._scan_start_time = time.time()
|
||||
|
||||
logger.info("Starting Plex library scan...")
|
||||
|
||||
try:
|
||||
success = self.plex_client.trigger_library_scan()
|
||||
|
||||
if success:
|
||||
logger.info("Plex library scan initiated successfully")
|
||||
# Start new periodic update system instead of completion detection
|
||||
self._start_periodic_updates()
|
||||
else:
|
||||
logger.error("Failed to initiate Plex library scan")
|
||||
self._reset_scan_state()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Exception during Plex library scan: {e}")
|
||||
self._reset_scan_state()
|
||||
|
||||
def _start_periodic_updates(self):
|
||||
"""Start periodic database updates while Plex is scanning"""
|
||||
try:
|
||||
with self._lock:
|
||||
if self._is_doing_periodic_updates:
|
||||
logger.debug("Periodic updates already in progress")
|
||||
return
|
||||
|
||||
self._is_doing_periodic_updates = True
|
||||
|
||||
logger.info(f"Starting periodic database updates - will check/update every {self._periodic_update_interval//60} minutes")
|
||||
|
||||
# Schedule first periodic update after 5 minutes
|
||||
self._periodic_update_timer = threading.Timer(self._periodic_update_interval, self._do_periodic_update)
|
||||
self._periodic_update_timer.daemon = True
|
||||
self._periodic_update_timer.start()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error starting periodic updates: {e}")
|
||||
self._reset_scan_state()
|
||||
|
||||
def _do_periodic_update(self):
|
||||
"""Execute periodic database update and check if scanning continues"""
|
||||
try:
|
||||
with self._lock:
|
||||
if not self._scan_in_progress:
|
||||
logger.debug("Scan no longer in progress, stopping periodic updates")
|
||||
return
|
||||
|
||||
# Check for timeout
|
||||
if self._scan_start_time and (time.time() - self._scan_start_time) > self._max_scan_time:
|
||||
logger.warning(f"Plex scan timeout reached ({self._max_scan_time}s), stopping periodic updates")
|
||||
self._stop_periodic_updates()
|
||||
return
|
||||
|
||||
# Check if Plex is still scanning
|
||||
is_scanning = self.plex_client.is_library_scanning("Music")
|
||||
elapsed_time = time.time() - self._scan_start_time if self._scan_start_time else 0
|
||||
|
||||
logger.info(f"PERIODIC UPDATE: After {elapsed_time//60:.0f} minutes - Plex scanning: {is_scanning}")
|
||||
|
||||
if is_scanning:
|
||||
# Still scanning - trigger database update and continue periodic updates
|
||||
logger.info("Plex still scanning - triggering database update")
|
||||
if self._shutting_down:
|
||||
return
|
||||
self._call_completion_callbacks()
|
||||
|
||||
# Schedule next periodic update
|
||||
if self._shutting_down:
|
||||
return
|
||||
logger.info(f"Scheduling next periodic update in {self._periodic_update_interval//60} minutes")
|
||||
self._periodic_update_timer = threading.Timer(self._periodic_update_interval, self._do_periodic_update)
|
||||
self._periodic_update_timer.daemon = True
|
||||
self._periodic_update_timer.start()
|
||||
else:
|
||||
# Scanning stopped - final update and cleanup
|
||||
logger.info("Plex scanning completed - doing final database update")
|
||||
if self._shutting_down:
|
||||
return
|
||||
self._call_completion_callbacks()
|
||||
self._stop_periodic_updates()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error during periodic update: {e}")
|
||||
self._stop_periodic_updates()
|
||||
|
||||
def _stop_periodic_updates(self):
|
||||
"""Stop periodic updates and clean up"""
|
||||
try:
|
||||
with self._lock:
|
||||
self._is_doing_periodic_updates = False
|
||||
|
||||
if self._periodic_update_timer:
|
||||
self._periodic_update_timer.cancel()
|
||||
self._periodic_update_timer = None
|
||||
|
||||
logger.info("Stopped periodic database updates")
|
||||
self._scan_completed()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error stopping periodic updates: {e}")
|
||||
|
||||
def _poll_scan_status(self):
|
||||
"""Poll Plex to check if library scan is still running"""
|
||||
try:
|
||||
with self._lock:
|
||||
if not self._scan_in_progress:
|
||||
logger.debug("Scan no longer in progress, stopping polling")
|
||||
return
|
||||
|
||||
# Check for timeout
|
||||
if self._scan_start_time and (time.time() - self._scan_start_time) > self._max_scan_time:
|
||||
logger.warning(f"Plex scan timeout reached ({self._max_scan_time}s), assuming completion")
|
||||
self._scan_completed()
|
||||
return
|
||||
|
||||
# Check if Plex is still scanning
|
||||
is_scanning = self.plex_client.is_library_scanning("Music")
|
||||
logger.info(f"DEBUG: Plex scan status check - is_scanning: {is_scanning}")
|
||||
|
||||
if is_scanning:
|
||||
# Still scanning, poll again in 30 seconds
|
||||
logger.info("DEBUG: Plex library still scanning, will check again in 30 seconds")
|
||||
timer = threading.Timer(30, self._poll_scan_status)
|
||||
timer.daemon = True
|
||||
timer.start()
|
||||
else:
|
||||
# Scan completed!
|
||||
elapsed_time = time.time() - self._scan_start_time if self._scan_start_time else 0
|
||||
logger.info(f"Plex library scan detected as completed (took {elapsed_time:.1f} seconds)")
|
||||
self._scan_completed()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error polling scan status: {e}")
|
||||
# Fallback to assuming completion after error
|
||||
self._scan_completed()
|
||||
|
||||
def _scan_completed(self):
|
||||
"""Called when we assume the scan has completed"""
|
||||
with self._lock:
|
||||
was_in_progress = self._scan_in_progress
|
||||
downloads_during_scan = self._downloads_during_scan
|
||||
|
||||
# Reset scan state
|
||||
self._scan_in_progress = False
|
||||
|
||||
if not was_in_progress:
|
||||
logger.debug("Scan completion callback called but scan was not in progress")
|
||||
return
|
||||
|
||||
logger.info("Plex library scan completed")
|
||||
|
||||
# Call registered completion callbacks
|
||||
self._call_completion_callbacks()
|
||||
|
||||
# Check if we need a follow-up scan
|
||||
if downloads_during_scan:
|
||||
logger.info("Downloads occurred during scan - triggering follow-up scan")
|
||||
self.request_scan("Follow-up scan for downloads during previous scan")
|
||||
else:
|
||||
logger.info("No downloads during scan - scan cycle complete")
|
||||
|
||||
def _call_completion_callbacks(self):
|
||||
"""Call all registered scan completion callbacks"""
|
||||
with self._lock:
|
||||
callbacks = self._scan_completion_callbacks.copy() # Copy to avoid lock issues
|
||||
|
||||
logger.info(f"DEBUG: Calling {len(callbacks)} scan completion callbacks")
|
||||
for callback in callbacks:
|
||||
try:
|
||||
logger.info(f"DEBUG: Executing callback: {callback.__name__}")
|
||||
callback()
|
||||
logger.info(f"DEBUG: Callback {callback.__name__} completed successfully")
|
||||
except Exception as e:
|
||||
logger.error(f"Error in scan completion callback {callback.__name__}: {e}")
|
||||
|
||||
def _reset_scan_state(self):
|
||||
"""Reset scan state after an error"""
|
||||
with self._lock:
|
||||
self._scan_in_progress = False
|
||||
self._scan_start_time = None
|
||||
|
||||
# Cancel periodic updates if running
|
||||
if self._periodic_update_timer:
|
||||
self._periodic_update_timer.cancel()
|
||||
self._periodic_update_timer = None
|
||||
self._is_doing_periodic_updates = False
|
||||
|
||||
def force_scan(self):
|
||||
"""
|
||||
Force an immediate scan, bypassing debouncing.
|
||||
Use sparingly - mainly for manual/administrative triggers.
|
||||
"""
|
||||
with self._lock:
|
||||
if self._timer:
|
||||
self._timer.cancel()
|
||||
self._timer = None
|
||||
|
||||
if self._scan_in_progress:
|
||||
logger.warning("Force scan requested but scan already in progress")
|
||||
return
|
||||
|
||||
logger.info("Force scan requested - executing immediately")
|
||||
self._execute_scan()
|
||||
|
||||
def get_status(self) -> dict:
|
||||
"""Get current status of the scan manager"""
|
||||
with self._lock:
|
||||
return {
|
||||
'scan_in_progress': self._scan_in_progress,
|
||||
'downloads_during_scan': self._downloads_during_scan,
|
||||
'timer_active': self._timer is not None,
|
||||
'delay_seconds': self.delay
|
||||
}
|
||||
|
||||
def shutdown(self):
|
||||
"""Clean shutdown - cancel any pending timers"""
|
||||
with self._lock:
|
||||
self._shutting_down = True
|
||||
if self._timer:
|
||||
self._timer.cancel()
|
||||
self._timer = None
|
||||
|
||||
if self._periodic_update_timer:
|
||||
self._periodic_update_timer.cancel()
|
||||
self._periodic_update_timer = None
|
||||
|
||||
self._is_doing_periodic_updates = False
|
||||
logger.info("PlexScanManager shutdown - cancelled all pending timers")
|
||||
|
|
@ -68,7 +68,7 @@ from core.soulseek_client import SoulseekClient
|
|||
from core.download_orchestrator import DownloadOrchestrator
|
||||
from core.tidal_client import TidalClient # Added import for Tidal
|
||||
from core.matching_engine import MusicMatchingEngine
|
||||
from core.database_update_worker import DatabaseUpdateWorker, DatabaseStatsWorker
|
||||
from core.database_update_worker import DatabaseUpdateWorker
|
||||
from core.web_scan_manager import WebScanManager
|
||||
from core.lyrics_client import lyrics_client
|
||||
from core.metadata_cache import get_metadata_cache
|
||||
|
|
@ -4066,7 +4066,7 @@ def _find_downloaded_file(download_path, track_data):
|
|||
return None
|
||||
|
||||
# --- Refactored Logic from GUI Threads ---
|
||||
# This logic is extracted from your QThread classes to be used directly by Flask.
|
||||
# This logic is extracted from the database update worker to be used directly by Flask.
|
||||
|
||||
def run_service_test(service, test_config):
|
||||
"""
|
||||
|
|
@ -24219,7 +24219,7 @@ def _run_db_update_task(full_refresh, server_type):
|
|||
db_update_worker.connect_callback('finished', _db_update_finished_callback)
|
||||
db_update_worker.connect_callback('error', _db_update_error_callback)
|
||||
|
||||
# This is a blocking call that runs the QThread's logic
|
||||
# This is a blocking call that runs the worker logic
|
||||
db_update_worker.run()
|
||||
|
||||
|
||||
|
|
@ -24270,7 +24270,7 @@ def _run_deep_scan_task(server_type):
|
|||
def get_database_stats():
|
||||
"""Endpoint to get current database statistics."""
|
||||
try:
|
||||
# This logic is adapted from DatabaseStatsWorker
|
||||
# This endpoint returns the same stats shape the UI expects.
|
||||
db = get_database()
|
||||
stats = db.get_database_info_for_server()
|
||||
return jsonify(stats)
|
||||
|
|
|
|||
Loading…
Reference in a new issue