fix(network): add offline cooldown guard for remote metadata requests

This commit is contained in:
pixelpaws
2026-04-20 15:04:04 +08:00
parent 0ced53c059
commit 5a7f4dc88b
8 changed files with 364 additions and 14 deletions

View File

@@ -20,6 +20,10 @@ from datetime import datetime, timedelta
from email.utils import parsedate_to_datetime
from typing import Optional, Dict, Tuple, Callable, Union, Awaitable
from ..services.settings_manager import get_settings_manager
from .connectivity_guard import (
OFFLINE_COOLDOWN_ERROR,
ConnectivityGuard,
)
from .errors import RateLimitError
logger = logging.getLogger(__name__)
@@ -797,6 +801,10 @@ class Downloader:
Returns:
Tuple[bool, Union[bytes, str], Optional[Dict]]: (success, content or error message, response headers if requested)
"""
guard = await ConnectivityGuard.get_instance()
if guard.should_block_request():
return False, OFFLINE_COOLDOWN_ERROR, None
try:
session = await self.session
# Debug log for proxy mode at request time
@@ -819,6 +827,7 @@ class Downloader:
) as response:
if response.status == 200:
content = await response.read()
guard.register_success()
if return_headers:
return True, content, dict(response.headers)
else:
@@ -837,6 +846,12 @@ class Downloader:
return False, error_msg, None
except Exception as e:
if guard.is_network_unreachable_error(e):
guard.register_network_failure(e)
if guard.should_block_request():
return False, OFFLINE_COOLDOWN_ERROR, None
logger.debug("Network unavailable during memory download: %s", e)
return False, str(e), None
logger.error(f"Error downloading to memory from {url}: {e}")
return False, str(e), None
@@ -857,6 +872,10 @@ class Downloader:
Returns:
Tuple[bool, Union[Dict, str]]: (success, headers dict or error message)
"""
guard = await ConnectivityGuard.get_instance()
if guard.should_block_request():
return False, OFFLINE_COOLDOWN_ERROR
try:
session = await self.session
# Debug log for proxy mode at request time
@@ -878,11 +897,18 @@ class Downloader:
url, headers=headers, proxy=self.proxy_url
) as response:
if response.status == 200:
guard.register_success()
return True, dict(response.headers)
else:
return False, f"Head request failed with status {response.status}"
except Exception as e:
if guard.is_network_unreachable_error(e):
guard.register_network_failure(e)
if guard.should_block_request():
return False, OFFLINE_COOLDOWN_ERROR
logger.debug("Network unavailable during header probe: %s", e)
return False, str(e)
logger.error(f"Error getting headers from {url}: {e}")
return False, str(e)
@@ -907,6 +933,10 @@ class Downloader:
Returns:
Tuple[bool, Union[Dict, str]]: (success, response data or error message)
"""
guard = await ConnectivityGuard.get_instance()
if guard.should_block_request():
return False, OFFLINE_COOLDOWN_ERROR
try:
session = await self.session
# Debug log for proxy mode at request time
@@ -930,6 +960,7 @@ class Downloader:
method, url, headers=headers, **kwargs
) as response:
if response.status == 200:
guard.register_success()
# Try to parse as JSON, fall back to text
try:
data = await response.json()
@@ -960,6 +991,12 @@ class Downloader:
return False, f"Request failed with status {response.status}"
except Exception as e:
if guard.is_network_unreachable_error(e):
guard.register_network_failure(e)
if guard.should_block_request():
return False, OFFLINE_COOLDOWN_ERROR
logger.debug("Network unavailable for %s %s: %s", method, url, e)
return False, str(e)
logger.error(f"Error making {method} request to {url}: {e}")
return False, str(e)