From b03073c5e5fb970836b738c3fe3327a7ed513eb4 Mon Sep 17 00:00:00 2001 From: MSCodeBase Agent Date: Tue, 25 Aug 2026 20:40:23 +0300 Subject: [PATCH] fix(search): fast-fail during reindex instead of hanging requests - Live repro 2026-08-25: full reindex blocked every MCP call ~7.5 min (timeouts incl. debug_runtime_passport); search is the primary victim. - Searcher.hybrid_search_async checks db_manager.is_reindexing() at entry -> instant 'busy, retry in seconds' instead of waiting minutes. Guard methods already exist in LanceDBManager; only the query path missed the check. - Strict 'is True' check: MagicMock-truthy trap (incident 2026-08-13) broke 6 hybrid-cache/searcher tests on first attempt; fixed + verified 9/9. --- src/core/search/engine.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/core/search/engine.py b/src/core/search/engine.py index 07727d4..3773a1c 100644 --- a/src/core/search/engine.py +++ b/src/core/search/engine.py @@ -535,6 +535,23 @@ async def hybrid_search_async( Все синхронные LanceDB/BM25 вызовы оборачиваются в asyncio.to_thread, чтобы не блокировать event loop при параллельных MCP-запросах. """ + # Fast-fail (2026-08-25, живое воспроизведение): пока идёт переиндексация + # (`db_manager.is_reindexing()`), чтение LanceDB небезопасно/долго — вместо + # зависания отвечаем мгновенным статусом, а не молчим минуты. + # ⚠️ строго `is True`: в тестах db_manager — MagicMock, его is_reindexing() + # truthy (та же ловушка MagicMock-truthy, инцидент 2026-08-13). + _dbm = getattr(self.indexer, "db_manager", None) + if _dbm is not None and callable(getattr(_dbm, "is_reindexing", None)): + try: + _busy = _dbm.is_reindexing() + except Exception: # noqa: BLE001 — ломаный мок не роняет поиск + _busy = False + if _busy is True: + raise RuntimeError( + "⏳ Индекс перестраивается (reindex в процессе) — " + "повторите поисковый запрос через несколько секунд." + ) + if not query or not query.strip(): return []