mirror of
https://github.com/ZhuLinsen/daily_stock_analysis
synced 2026-09-20 10:53:33 +08:00
feat: 自建 SearXNG 搜索超时可配置(SEARXNG_TIMEOUT_SECONDS) (#2249)
* feat: make self-hosted SearXNG search timeout configurable SEARXNG_TIMEOUT_SECONDS (default 10s, min 1) now controls the per-search timeout for self-hosted SearXNG instances, threaded through all three SearchService construction sites. Public-instance timeout stays fixed. * fix: thread SEARXNG_TIMEOUT_SECONDS through subprocess rebuild and Actions - persist searxng_timeout_seconds in _constructor_kwargs so the bounded topic-news subprocess rebuild no longer silently falls back to 10s - map SEARXNG_TIMEOUT_SECONDS (vars||secrets) in 00-daily-analysis.yml - document the variable in full-guide/full-guide_EN data-source tables, add CHANGELOG entry, and add regression tests for both paths * fix: document SearXNG timeout environment contract * fix: register SearXNG timeout setting * fix: keep SearXNG timeout env-only --------- Co-authored-by: zhulinsen <42829555+ZhuLinsen@users.noreply.github.com> Co-authored-by: zhulinsen <zhuls97@163.com>
This commit is contained in:
@@ -983,6 +983,7 @@ class Config:
|
||||
serpapi_keys: List[str] = field(default_factory=list) # SerpAPI Keys
|
||||
searxng_base_urls: List[str] = field(default_factory=list) # SearXNG instance URLs (self-hosted, no quota)
|
||||
searxng_public_instances_enabled: bool = False # Opt in to public discovery when base URLs are absent
|
||||
searxng_timeout_seconds: int = 10 # 自建 SearXNG 单次搜索超时(秒)
|
||||
|
||||
# === Social Sentiment (US stocks only, api.adanos.org) ===
|
||||
social_sentiment_api_key: Optional[str] = None
|
||||
@@ -1880,6 +1881,9 @@ class Config:
|
||||
serpapi_keys=serpapi_keys,
|
||||
searxng_base_urls=searxng_base_urls,
|
||||
searxng_public_instances_enabled=searxng_public_instances_enabled,
|
||||
searxng_timeout_seconds=parse_env_int(
|
||||
os.getenv('SEARXNG_TIMEOUT_SECONDS'), 10, field_name='SEARXNG_TIMEOUT_SECONDS', minimum=1
|
||||
),
|
||||
social_sentiment_api_key=os.getenv('SOCIAL_SENTIMENT_API_KEY') or None,
|
||||
social_sentiment_api_url=os.getenv('SOCIAL_SENTIMENT_API_URL', 'https://api.adanos.org').rstrip('/'),
|
||||
news_max_age_days=parse_env_int(os.getenv('NEWS_MAX_AGE_DAYS'), 3, field_name='NEWS_MAX_AGE_DAYS', minimum=1),
|
||||
|
||||
@@ -79,6 +79,7 @@ WEB_SETTINGS_HIDDEN_FROM_UI = {
|
||||
"USE_PROXY",
|
||||
"PROXY_HOST",
|
||||
"PROXY_PORT",
|
||||
"SEARXNG_TIMEOUT_SECONDS",
|
||||
}
|
||||
|
||||
_FIELD_DEFINITIONS: Dict[str, Dict[str, Any]] = {
|
||||
|
||||
@@ -105,6 +105,7 @@ def build_market_review_runtime(
|
||||
"searxng_public_instances_enabled",
|
||||
False,
|
||||
),
|
||||
searxng_timeout_seconds=getattr(config, "searxng_timeout_seconds", None),
|
||||
news_max_age_days=getattr(config, "news_max_age_days", 3),
|
||||
news_strategy_profile=getattr(config, "news_strategy_profile", "short"),
|
||||
)
|
||||
|
||||
@@ -309,6 +309,7 @@ class StockAnalysisPipeline:
|
||||
minimax_keys=self.config.minimax_api_keys,
|
||||
searxng_base_urls=self.config.searxng_base_urls,
|
||||
searxng_public_instances_enabled=self.config.searxng_public_instances_enabled,
|
||||
searxng_timeout_seconds=getattr(self.config, "searxng_timeout_seconds", None),
|
||||
news_max_age_days=self.config.news_max_age_days,
|
||||
news_strategy_profile=getattr(self.config, "news_strategy_profile", "short"),
|
||||
)
|
||||
|
||||
@@ -1843,10 +1843,20 @@ class SearXNGSearchProvider(BaseSearchProvider):
|
||||
_public_instances_stale_retry_after: float = 0.0
|
||||
_public_instances_lock = threading.Lock()
|
||||
|
||||
def __init__(self, base_urls: Optional[List[str]] = None, *, use_public_instances: bool = False):
|
||||
def __init__(
|
||||
self,
|
||||
base_urls: Optional[List[str]] = None,
|
||||
*,
|
||||
use_public_instances: bool = False,
|
||||
self_hosted_timeout_seconds: Optional[int] = None,
|
||||
):
|
||||
normalized_base_urls = [url.rstrip("/") for url in (base_urls or []) if url.strip()]
|
||||
super().__init__(normalized_base_urls, "SearXNG")
|
||||
self._base_urls = normalized_base_urls
|
||||
if self_hosted_timeout_seconds and int(self_hosted_timeout_seconds) > 0:
|
||||
self._self_hosted_timeout_seconds = int(self_hosted_timeout_seconds)
|
||||
else:
|
||||
self._self_hosted_timeout_seconds = self.SELF_HOSTED_TIMEOUT_SECONDS
|
||||
self._use_public_instances = bool(use_public_instances and not self._base_urls)
|
||||
self._cursor = 0
|
||||
self._cursor_lock = threading.Lock()
|
||||
@@ -2157,7 +2167,7 @@ class SearXNGSearchProvider(BaseSearchProvider):
|
||||
max_attempts=len(self._base_urls),
|
||||
)
|
||||
retry_enabled = True
|
||||
timeout = self.SELF_HOSTED_TIMEOUT_SECONDS
|
||||
timeout = self._self_hosted_timeout_seconds
|
||||
empty_error = "SearXNG 未配置可用实例"
|
||||
elif self._use_public_instances:
|
||||
public_instances = self._get_public_instances()
|
||||
@@ -2390,6 +2400,7 @@ class SearchService:
|
||||
minimax_keys: Optional[List[str]] = None,
|
||||
searxng_base_urls: Optional[List[str]] = None,
|
||||
searxng_public_instances_enabled: bool = False,
|
||||
searxng_timeout_seconds: Optional[int] = None,
|
||||
news_max_age_days: int = 3,
|
||||
news_strategy_profile: str = "short",
|
||||
):
|
||||
@@ -2417,6 +2428,7 @@ class SearchService:
|
||||
"minimax_keys": list(minimax_keys or []),
|
||||
"searxng_base_urls": list(searxng_base_urls or []),
|
||||
"searxng_public_instances_enabled": bool(searxng_public_instances_enabled),
|
||||
"searxng_timeout_seconds": searxng_timeout_seconds,
|
||||
"news_max_age_days": int(news_max_age_days),
|
||||
"news_strategy_profile": news_strategy_profile,
|
||||
}
|
||||
@@ -2468,6 +2480,7 @@ class SearchService:
|
||||
searxng_provider = SearXNGSearchProvider(
|
||||
searxng_base_urls,
|
||||
use_public_instances=bool(searxng_public_instances_enabled and not searxng_base_urls),
|
||||
self_hosted_timeout_seconds=searxng_timeout_seconds,
|
||||
)
|
||||
if searxng_provider.is_available:
|
||||
self._providers.append(searxng_provider)
|
||||
@@ -4890,6 +4903,7 @@ def get_search_service() -> SearchService:
|
||||
minimax_keys=config.minimax_api_keys,
|
||||
searxng_base_urls=config.searxng_base_urls,
|
||||
searxng_public_instances_enabled=config.searxng_public_instances_enabled,
|
||||
searxng_timeout_seconds=getattr(config, "searxng_timeout_seconds", None),
|
||||
news_max_age_days=config.news_max_age_days,
|
||||
news_strategy_profile=getattr(config, "news_strategy_profile", "short"),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user