-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Labels
Description
Manager Infrastructure Coupling
Problem
DownloadManager.__aenter__() currently has too much knowledge about infrastructure concerns that aren't related to download orchestration:
- HTTP Client Creation - SSL context, certifi certificates, TCPConnector configuration
- Filesystem Operations - Creating directories with aiofiles
This makes the manager harder to:
- Test in isolation (need to mock SSL, certifi, aiofiles)
- Understand (infrastructure mixed with orchestration)
- Maintain (changes to SSL/filesystem affect manager)
- Reuse (client creation logic trapped in manager)
Current Code
async def __aenter__(self) -> "DownloadManager":
# Filesystem concern
await aiofiles.os.makedirs(self.download_dir, exist_ok=True)
if self._client is None:
# SSL/HTTP concern
ssl_context = ssl.create_default_context(cafile=certifi.where())
connector = aiohttp.TCPConnector(ssl=ssl_context)
self._client = await aiohttp.ClientSession(connector=connector).__aenter__()
self._owns_client = True
await self.start_workers()
return selfProposed Solution
1. Extract HTTP Client Creation
Create src/rheo/infrastructure/http/__init__.py:
"""HTTP client utilities for secure HTTPS connections."""
import ssl
import aiohttp
import certifi
async def create_default_client() -> aiohttp.ClientSession:
"""Create ClientSession with secure defaults for all platforms.
Configures SSL using certifi's certificate bundle to ensure
proper HTTPS verification on all platforms (including macOS
with Python 3.14+ where system certs may not be used by default).
Returns:
Configured ClientSession ready for HTTPS requests
"""
ssl_context = ssl.create_default_context(cafile=certifi.where())
connector = aiohttp.TCPConnector(ssl=ssl_context)
return aiohttp.ClientSession(connector=connector)Or consider creating a client factory class, as we will most likely want to support proxy support, auth helpers, custom timeout configuration etc..
2. Extract Filesystem Utilities
Create src/rheo/infrastructure/filesystem.py:
"""Filesystem utilities for async file operations."""
from pathlib import Path
import aiofiles.os
async def ensure_directory_exists(path: Path) -> None:
"""Ensure directory exists, creating it if necessary.
Args:
path: Directory path to create
"""
await aiofiles.os.makedirs(path, exist_ok=True)Or evaluate if attaching to settings class is appropriate as we will be injecting these in the manager in the future.
3. Simplify Manager
from ..infrastructure.http import create_default_client
from ..infrastructure.filesystem import ensure_directory_exists
class DownloadManager:
async def __aenter__(self) -> "DownloadManager":
"""Enter async context manager."""
await ensure_directory_exists(self.download_dir)
if self._client is None:
self._client = await create_default_client()
await self._client.__aenter__()
self._owns_client = True
await self.start_workers()
return selfReferences
- Current code:
src/rheo/downloads/manager.pylines 132-154 - Related pattern: WorkerPool abstraction (already successfully extracted)
Reactions are currently unavailable