Refactor: Replace CallbackManager with Events pattern
- Replace callback system with events library in SerieScanner - Update SeriesApp to subscribe to loader and scanner events - Refactor ScanService to use Events instead of CallbackManager - Remove CallbackManager imports and callback classes - Add safe event calling with error handling in SerieScanner - Update AniworldLoader to use Events for download progress - Remove progress_callback parameter from download methods - Update all affected tests for Events pattern - Fix test_series_app.py for new event subscription model - Comment out obsolete callback tests in test_scan_service.py All core tests passing. Events provide cleaner event-driven architecture.
This commit is contained in:
@@ -1007,92 +1007,7 @@ class DownloadService:
|
||||
if self._active_download and self._active_download.id == item.id:
|
||||
self._active_download = None
|
||||
|
||||
async def start(self) -> None:
|
||||
"""Initialize the download queue service (compatibility method).
|
||||
|
||||
Note: Downloads are started manually via start_next_download().
|
||||
"""
|
||||
logger.info("Download queue service initialized")
|
||||
|
||||
async def stop(self, timeout: float = 10.0) -> None:
|
||||
"""Stop the download queue service gracefully.
|
||||
|
||||
Persists in-progress downloads back to pending state, cancels active
|
||||
tasks, and shuts down the thread pool with a timeout.
|
||||
|
||||
Args:
|
||||
timeout: Maximum time (seconds) to wait for executor shutdown
|
||||
"""
|
||||
logger.info("Stopping download queue service (timeout=%.1fs)...", timeout)
|
||||
|
||||
# Set shutdown flag first to prevent new downloads
|
||||
self._is_shutting_down = True
|
||||
self._is_stopped = True
|
||||
|
||||
# Request cancellation from AnimeService (signals the download thread)
|
||||
try:
|
||||
self._anime_service.request_download_cancel()
|
||||
logger.info("Requested download cancellation from AnimeService")
|
||||
except Exception as e:
|
||||
logger.warning("Failed to request download cancellation: %s", e)
|
||||
|
||||
# Persist active download back to pending state if one exists
|
||||
if self._active_download:
|
||||
logger.info(
|
||||
"Persisting active download to pending: item_id=%s",
|
||||
self._active_download.id
|
||||
)
|
||||
try:
|
||||
# Reset status to pending so it can be resumed on restart
|
||||
self._active_download.status = DownloadStatus.PENDING
|
||||
self._active_download.completed_at = None
|
||||
await self._save_to_database(self._active_download)
|
||||
logger.info("Active download persisted to database as pending")
|
||||
except Exception as e:
|
||||
logger.error("Failed to persist active download: %s", e)
|
||||
|
||||
# Cancel active download task if running
|
||||
active_task = self._active_download_task
|
||||
if active_task and not active_task.done():
|
||||
logger.info("Cancelling active download task...")
|
||||
active_task.cancel()
|
||||
try:
|
||||
# Wait briefly for cancellation to complete
|
||||
await asyncio.wait_for(
|
||||
asyncio.shield(active_task),
|
||||
timeout=2.0
|
||||
)
|
||||
except asyncio.TimeoutError:
|
||||
logger.warning("Download task cancellation timed out")
|
||||
except asyncio.CancelledError:
|
||||
logger.info("Active download task cancelled")
|
||||
except Exception as e:
|
||||
logger.warning("Error during task cancellation: %s", e)
|
||||
|
||||
# Shutdown executor with wait and timeout
|
||||
logger.info("Shutting down thread pool executor...")
|
||||
try:
|
||||
# Run executor shutdown in thread to avoid blocking event loop
|
||||
loop = asyncio.get_event_loop()
|
||||
await asyncio.wait_for(
|
||||
loop.run_in_executor(
|
||||
None,
|
||||
lambda: self._executor.shutdown(wait=True, cancel_futures=True)
|
||||
),
|
||||
timeout=timeout
|
||||
)
|
||||
logger.info("Thread pool executor shutdown complete")
|
||||
except asyncio.TimeoutError:
|
||||
logger.warning(
|
||||
"Executor shutdown timed out after %.1fs, forcing shutdown",
|
||||
timeout
|
||||
)
|
||||
# Force shutdown without waiting
|
||||
self._executor.shutdown(wait=False, cancel_futures=True)
|
||||
except Exception as e:
|
||||
logger.error("Error during executor shutdown: %s", e)
|
||||
|
||||
logger.info("Download queue service stopped")
|
||||
|
||||
|
||||
# Singleton instance
|
||||
|
||||
Reference in New Issue
Block a user