Skip to content
This repository was archived by the owner on May 2, 2026. It is now read-only.

Commit bb7a3d4

Browse files
authored
Merge pull request #194 from Castrozan/master
fix: move DownloadService to session Context to prevent worker registration crash
2 parents 2cfe616 + 1cb86b0 commit bb7a3d4

2 files changed

Lines changed: 21 additions & 8 deletions

File tree

viu_media/cli/interactive/menu/media/download_episodes.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ def download_episodes(ctx: Context, state: State) -> State | InternalDirective:
88
"""Menu to select and download episodes synchronously."""
99
from viu_media.cli.utils.search import find_best_match_title
1010
from .....core.utils.normalizer import normalize_title
11-
from ....service.download.service import DownloadService
1211

1312
feedback = ctx.feedback
1413
selector = ctx.selector
@@ -71,16 +70,11 @@ def download_episodes(ctx: Context, state: State) -> State | InternalDirective:
7170
feedback.info("No episodes selected for download.")
7271
return InternalDirective.BACK
7372

74-
# Step 3: Download episodes synchronously
75-
# TODO: move to main ctx
76-
download_service = DownloadService(
77-
config, ctx.media_registry, ctx.media_api, ctx.provider
78-
)
79-
73+
# Step 3: Download episodes synchronously using the session-scoped service
8074
feedback.info(
8175
f"Starting download of {len(selected_episodes)} episodes. This may take a while..."
8276
)
83-
download_service.download_episodes_sync(media_item, selected_episodes)
77+
ctx.download.download_episodes_sync(media_item, selected_episodes)
8478

8579
feedback.success(f"Finished downloading {len(selected_episodes)} episodes.")
8680

viu_media/cli/interactive/session.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99

1010
from ...core.config import AppConfig
1111
from ...core.constants import APP_DIR, USER_CONFIG
12+
from ...core.utils.concurrency import thread_manager
1213
from .state import InternalDirective, MenuName, State
1314

1415
if TYPE_CHECKING:
1516
from ...libs.media_api.base import BaseApiClient
1617
from ...libs.provider.anime.base import BaseAnimeProvider
1718
from ...libs.selectors.base import BaseSelector
1819
from ..service.auth import AuthService
20+
from ..service.download.service import DownloadService
1921
from ..service.feedback import FeedbackService
2022
from ..service.player import PlayerService
2123
from ..service.registry import MediaRegistryService
@@ -86,6 +88,7 @@ class Context:
8688
_selector: Optional["BaseSelector"] = None
8789
_media_api: Optional["BaseApiClient"] = None
8890

91+
_download: Optional["DownloadService"] = None
8992
_feedback: Optional["FeedbackService"] = None
9093
_media_registry: Optional["MediaRegistryService"] = None
9194
_watch_history: Optional["WatchHistoryService"] = None
@@ -137,6 +140,16 @@ def media_api(self) -> "BaseApiClient":
137140

138141
return self._media_api
139142

143+
@property
144+
def download(self) -> "DownloadService":
145+
if not self._download:
146+
from ..service.download.service import DownloadService
147+
148+
self._download = DownloadService(
149+
self.config, self.media_registry, self.media_api, self.provider
150+
)
151+
return self._download
152+
140153
@property
141154
def player(self) -> "PlayerService":
142155
if not self._player:
@@ -206,7 +219,12 @@ class Session:
206219
_history: List[State] = []
207220
_menus: dict[MenuName, Menu] = {}
208221

222+
def _shutdown_download_worker(self):
223+
if hasattr(self, "_context") and self._context._download:
224+
thread_manager.shutdown_worker("download_worker", wait=False, timeout=5.0)
225+
209226
def _load_context(self, config: AppConfig):
227+
self._shutdown_download_worker()
210228
self._context = Context(config)
211229
logger.info("Application context reloaded.")
212230

@@ -243,6 +261,7 @@ def run(
243261
self._context.session.create_crash_backup(self._history)
244262
raise
245263
finally:
264+
self._shutdown_download_worker()
246265
# Clean up preview workers when session ends
247266
self._cleanup_preview_workers()
248267
self._context.session.save_session(self._history)

0 commit comments

Comments
 (0)