ZhuLinsen/daily_stock_analysis · warning · RuntimeError

题材新闻搜索并发已满,请稍后重试

Error message

题材新闻搜索并发已满,请稍后重试

What it means

RuntimeError from _call_topic_news_in_subprocess when the module-level _SEARCH_TIMEOUT_WORKER_SLOTS semaphore is exhausted before a new topic-news subprocess can start. It is an admission-control failure: concurrent topic-news searches are capped process-wide, and non-blocking acquire failing means the cap is already busy. Backpressure, not a data error.

Source

Thrown at src/search_service.py:106

            except BaseException:
                pass
    finally:
        conn.close()


def _call_topic_news_in_subprocess(
    *,
    constructor_kwargs: Dict[str, Any],
    topic: str,
    max_results: int,
    focus_keywords: Optional[List[str]],
    timeout_seconds: float,
    deadline: Optional[float] = None,
) -> "SearchResponse":
    """Execute a topic-news provider chain with a hard, process-level deadline."""
    wait_seconds = max(0.01, float(timeout_seconds))
    if not _SEARCH_TIMEOUT_WORKER_SLOTS.acquire(blocking=False):
        raise RuntimeError("题材新闻搜索并发已满,请稍后重试")

    process: Any = None
    process_started = False
    parent_conn: Any = None
    child_conn: Any = None
    try:
        try:
            multiprocessing.freeze_support()
            ctx = multiprocessing.get_context(_SEARCH_TIMEOUT_PROCESS_START_METHOD)
            parent_conn, child_conn = ctx.Pipe(duplex=False)
            process = ctx.Process(
                target=_search_topic_news_process_worker,
                args=(
                    child_conn,
                    constructor_kwargs,
                    topic,
                    max_results,
                    focus_keywords,

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Retry after a short delay — slots free up as in-flight searches finish or time out
  2. Reduce client-side concurrency (limit parallel topic searches to the slot count)
  3. Tune the search timeout down so stuck subprocesses release slots sooner
  4. If this recurs at steady load, raise the slot cap in configuration or scale horizontally
Defensive patterns

Strategy: retry

Validate before calling

from src.search_service import _SEARCH_TIMEOUT_WORKER_SLOTS

def search_slot_available() -> bool:
    return _SEARCH_TIMEOUT_WORKER_SLOTS._value > 0  # advisory only, racy by nature

Try / catch

for attempt in range(3):
    try:
        resp = search_topic_news(topic)
        break
    except RuntimeError as exc:
        if "并发已满" in str(exc) and attempt < 2:
            time.sleep(0.5 * (attempt + 1))
            continue
        raise

Prevention

When it happens

Trigger: Issuing more concurrent topic/sector news searches than the configured slot count (acquire(blocking=False) fails), e.g. a burst of market-review requests each spawning a topic-news subprocess while earlier ones are still within their timeout window.

Common situations: Batch analysis of many topics in parallel; long provider timeouts keeping slots occupied; a previous search subprocess hung near its deadline; load tests or schedulers overlapping with user-triggered searches.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/09e41f7a66eb75a1. Report an issue: GitHub.