better shutdown
This commit is contained in:
parent
1ca105f330
commit
34019b7e65
@ -1,25 +1,5 @@
|
|||||||
{
|
{
|
||||||
"pending": [
|
"pending": [
|
||||||
{
|
|
||||||
"id": "1c4ade94-0a9f-4b75-8ed7-ceb8995c6865",
|
|
||||||
"serie_id": "highschool-dxd",
|
|
||||||
"serie_folder": "Highschool DxD",
|
|
||||||
"serie_name": "Highschool DxD",
|
|
||||||
"episode": {
|
|
||||||
"season": 1,
|
|
||||||
"episode": 2,
|
|
||||||
"title": null
|
|
||||||
},
|
|
||||||
"status": "pending",
|
|
||||||
"priority": "NORMAL",
|
|
||||||
"added_at": "2025-11-20T17:12:34.485183Z",
|
|
||||||
"started_at": null,
|
|
||||||
"completed_at": null,
|
|
||||||
"progress": null,
|
|
||||||
"error": null,
|
|
||||||
"retry_count": 0,
|
|
||||||
"source_url": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "c4bb6196-7a58-4338-8747-100970fd3834",
|
"id": "c4bb6196-7a58-4338-8747-100970fd3834",
|
||||||
"serie_id": "highschool-dxd",
|
"serie_id": "highschool-dxd",
|
||||||
@ -30,11 +10,11 @@
|
|||||||
"episode": 3,
|
"episode": 3,
|
||||||
"title": null
|
"title": null
|
||||||
},
|
},
|
||||||
"status": "pending",
|
"status": "cancelled",
|
||||||
"priority": "NORMAL",
|
"priority": "NORMAL",
|
||||||
"added_at": "2025-11-20T17:12:34.485225Z",
|
"added_at": "2025-11-20T17:12:34.485225Z",
|
||||||
"started_at": null,
|
"started_at": "2025-11-20T18:09:04.527701Z",
|
||||||
"completed_at": null,
|
"completed_at": "2025-11-20T18:09:27.852314Z",
|
||||||
"progress": null,
|
"progress": null,
|
||||||
"error": null,
|
"error": null,
|
||||||
"retry_count": 0,
|
"retry_count": 0,
|
||||||
@ -963,5 +943,5 @@
|
|||||||
],
|
],
|
||||||
"active": [],
|
"active": [],
|
||||||
"failed": [],
|
"failed": [],
|
||||||
"timestamp": "2025-11-20T17:54:12.722000+00:00"
|
"timestamp": "2025-11-20T18:09:27.852598+00:00"
|
||||||
}
|
}
|
||||||
@ -77,10 +77,14 @@ class DownloadService:
|
|||||||
|
|
||||||
# Control flags
|
# Control flags
|
||||||
self._is_stopped = True # Queue processing is stopped by default
|
self._is_stopped = True # Queue processing is stopped by default
|
||||||
|
self._is_shutting_down = False # Flag to indicate shutdown
|
||||||
|
|
||||||
# Executor for blocking operations
|
# Executor for blocking operations
|
||||||
self._executor = ThreadPoolExecutor(max_workers=1)
|
self._executor = ThreadPoolExecutor(max_workers=1)
|
||||||
|
|
||||||
|
# Track active download task for cancellation
|
||||||
|
self._active_download_task: Optional[asyncio.Task] = None
|
||||||
|
|
||||||
# Statistics tracking
|
# Statistics tracking
|
||||||
self._total_downloaded_mb: float = 0.0
|
self._total_downloaded_mb: float = 0.0
|
||||||
self._download_speeds: deque[float] = deque(maxlen=10)
|
self._download_speeds: deque[float] = deque(maxlen=10)
|
||||||
@ -500,7 +504,11 @@ class DownloadService:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Process the download (this will wait until complete)
|
# Process the download (this will wait until complete)
|
||||||
await self._process_download(item)
|
self._active_download_task = asyncio.create_task(
|
||||||
|
self._process_download(item)
|
||||||
|
)
|
||||||
|
await self._active_download_task
|
||||||
|
self._active_download_task = None
|
||||||
|
|
||||||
# Small delay between downloads
|
# Small delay between downloads
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
@ -771,6 +779,11 @@ class DownloadService:
|
|||||||
item: Download item to process
|
item: Download item to process
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
# Check if shutting down
|
||||||
|
if self._is_shutting_down:
|
||||||
|
logger.info("Skipping download due to shutdown")
|
||||||
|
return
|
||||||
|
|
||||||
# Update status
|
# Update status
|
||||||
item.status = DownloadStatus.DOWNLOADING
|
item.status = DownloadStatus.DOWNLOADING
|
||||||
item.started_at = datetime.now(timezone.utc)
|
item.started_at = datetime.now(timezone.utc)
|
||||||
@ -814,6 +827,19 @@ class DownloadService:
|
|||||||
else:
|
else:
|
||||||
raise AnimeServiceError("Download returned False")
|
raise AnimeServiceError("Download returned False")
|
||||||
|
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
# Handle task cancellation during shutdown
|
||||||
|
logger.info(
|
||||||
|
"Download cancelled during shutdown",
|
||||||
|
item_id=item.id,
|
||||||
|
)
|
||||||
|
item.status = DownloadStatus.CANCELLED
|
||||||
|
item.completed_at = datetime.now(timezone.utc)
|
||||||
|
# Return item to pending queue if not shutting down
|
||||||
|
if not self._is_shutting_down:
|
||||||
|
self._add_to_pending_queue(item, front=True)
|
||||||
|
raise # Re-raise to properly cancel the task
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Handle failure
|
# Handle failure
|
||||||
item.status = DownloadStatus.FAILED
|
item.status = DownloadStatus.FAILED
|
||||||
@ -845,27 +871,31 @@ class DownloadService:
|
|||||||
logger.info("Download queue service initialized")
|
logger.info("Download queue service initialized")
|
||||||
|
|
||||||
async def stop(self) -> None:
|
async def stop(self) -> None:
|
||||||
"""Stop the download queue service and wait for active download.
|
"""Stop the download queue service and cancel active downloads.
|
||||||
|
|
||||||
Note: This waits for the current download to complete.
|
Cancels any active download and shuts down the thread pool immediately.
|
||||||
"""
|
"""
|
||||||
logger.info("Stopping download queue service...")
|
logger.info("Stopping download queue service...")
|
||||||
|
|
||||||
# Wait for active download to complete (with timeout)
|
# Set shutdown flag
|
||||||
timeout = 30 # seconds
|
self._is_shutting_down = True
|
||||||
start_time = asyncio.get_event_loop().time()
|
self._is_stopped = True
|
||||||
|
|
||||||
while (
|
# Cancel active download task if running
|
||||||
self._active_download
|
if self._active_download_task and not self._active_download_task.done():
|
||||||
and (asyncio.get_event_loop().time() - start_time) < timeout
|
logger.info("Cancelling active download task...")
|
||||||
):
|
self._active_download_task.cancel()
|
||||||
await asyncio.sleep(1)
|
try:
|
||||||
|
await self._active_download_task
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
logger.info("Active download task cancelled")
|
||||||
|
|
||||||
# Save final state
|
# Save final state
|
||||||
self._save_queue()
|
self._save_queue()
|
||||||
|
|
||||||
# Shutdown executor
|
# Shutdown executor immediately, don't wait for tasks
|
||||||
self._executor.shutdown(wait=True)
|
logger.info("Shutting down thread pool executor...")
|
||||||
|
self._executor.shutdown(wait=False, cancel_futures=True)
|
||||||
|
|
||||||
logger.info("Download queue service stopped")
|
logger.info("Download queue service stopped")
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user