66
77from __future__ import annotations
88
9- import logging
9+ import asyncio
1010
1111from typing import TYPE_CHECKING
1212
13+ import structlog
14+
1315from docs2db_mcp .config import CONFIG
1416
1517
1618if TYPE_CHECKING :
1719 from docs2db_api .rag .engine import UniversalRAGEngine
1820
1921
20- logger = logging . getLogger (__name__ )
22+ logger = structlog . get_logger (__name__ )
2123
2224_engine : UniversalRAGEngine | None = None
25+ _engine_lock = asyncio .Lock ()
2326
2427
2528async def get_engine () -> UniversalRAGEngine :
@@ -37,41 +40,39 @@ async def get_engine() -> UniversalRAGEngine:
3740 """
3841 global _engine
3942
40- if _engine is None :
41- from docs2db_api .rag .engine import RAGConfig
42- from docs2db_api .rag .engine import UniversalRAGEngine
43-
44- logger .info ("Initializing UniversalRAGEngine" )
45-
46- # Configure database connection (dict format)
47- db_config = {
48- "host" : CONFIG .db_host ,
49- "port" : str (CONFIG .db_port ),
50- "database" : CONFIG .db_database ,
51- "user" : CONFIG .db_user ,
52- "password" : CONFIG .db_password ,
53- }
54-
55- # Configure RAG (no LLM config - refinement disabled)
56- rag_config = RAGConfig ()
57- rag_config .similarity_threshold = CONFIG .rag_similarity_threshold
58- rag_config .max_chunks = CONFIG .rag_max_chunks
59- rag_config .enable_reranking = CONFIG .rag_enable_reranking
60- rag_config .enable_question_refinement = False # Disabled for tool calling
61-
62- # Create and initialize engine
63- _engine = UniversalRAGEngine (
64- config = rag_config ,
65- db_config = db_config ,
66- )
67-
68- try :
69- await _engine .start ()
70- logger .info ("UniversalRAGEngine initialized successfully" )
71- except Exception as e :
72- logger .error ("Failed to initialize RAG engine: %s" , e )
73- _engine = None
74- raise
43+ async with _engine_lock :
44+ if _engine is None :
45+ from docs2db_api .rag .engine import RAGConfig
46+ from docs2db_api .rag .engine import UniversalRAGEngine
47+
48+ logger .info ("Initializing UniversalRAGEngine" )
49+
50+ db_config = {
51+ "host" : CONFIG .db_host ,
52+ "port" : str (CONFIG .db_port ),
53+ "database" : CONFIG .db_database ,
54+ "user" : CONFIG .db_user ,
55+ "password" : CONFIG .db_password ,
56+ }
57+
58+ rag_config = RAGConfig ()
59+ rag_config .similarity_threshold = CONFIG .rag_similarity_threshold
60+ rag_config .max_chunks = CONFIG .rag_max_chunks
61+ rag_config .enable_reranking = CONFIG .rag_enable_reranking
62+ rag_config .enable_question_refinement = False
63+
64+ _engine = UniversalRAGEngine (
65+ config = rag_config ,
66+ db_config = db_config ,
67+ )
68+
69+ try :
70+ await _engine .start ()
71+ logger .info ("UniversalRAGEngine initialized successfully" )
72+ except Exception as e :
73+ logger .error ("Failed to initialize RAG engine" , error = str (e ))
74+ _engine = None
75+ raise
7576
7677 return _engine
7778
@@ -80,11 +81,13 @@ async def shutdown_engine() -> None:
8081 """Shutdown the RAG engine and cleanup resources."""
8182 global _engine
8283
83- if _engine is not None :
84- logger .info ("Shutting down UniversalRAGEngine" )
85- # UniversalRAGEngine doesn't have a stop() method
86- # Just set to None to allow garbage collection
87- _engine = None
84+ async with _engine_lock :
85+ if _engine is not None :
86+ logger .info ("Shutting down UniversalRAGEngine" )
87+ try :
88+ await _engine .close ()
89+ finally :
90+ _engine = None
8891
8992
9093async def health_check () -> None :
@@ -96,27 +99,23 @@ async def health_check() -> None:
9699 logger .info ("Performing startup health check..." )
97100
98101 try :
99- # Initialize engine and connect to database
100102 engine = await get_engine ()
101103 logger .info ("Database connection established" )
102104
103- # Perform a simple test query to verify the system works
104- test_query = "test"
105105 result = await engine .search_documents (
106- query = test_query ,
106+ query = "test" ,
107107 max_chunks = 1 ,
108108 similarity_threshold = 0.0 ,
109109 enable_reranking = False ,
110110 )
111111
112- # Verify we got a valid response
113112 if result is None :
114113 msg = "Health check query returned None"
115114 raise Exception (msg )
116115
117- logger .info ("Test query successful (returned %d documents) " , len (result .documents ))
116+ logger .info ("Test query successful" , document_count = len (result .documents ))
118117 logger .info ("Health check passed - system is ready" )
119118
120119 except Exception as e :
121- logger .error ("Health check failed: %s " , e , exc_info = True )
120+ logger .error ("Health check failed" , error = str ( e ) , exc_info = True )
122121 raise Exception (f"Startup health check failed - cannot connect to database or perform queries: { e } " ) from e
0 commit comments