You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/repositories/interface.py
+56-1Lines changed: 56 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -35,6 +35,19 @@ def __init__(self):
35
35
36
36
37
37
defrepository_exception_handler(method):
38
+
"""
39
+
Decorator that standardizes error handling and logging for repository coroutine methods.
40
+
41
+
Parameters:
42
+
method (Callable): The asynchronous repository method to wrap.
43
+
44
+
Returns:
45
+
wrapper (Callable): An async wrapper that:
46
+
- re-raises PyMongoError after logging the exception,
47
+
- re-raises RepositoryNotInitializedException after logging the exception,
48
+
- logs any other exception and raises an HTTPException with status 500 and detail 'Unexpected error ocurred',
49
+
- always logs completion of the repository method call with the repository name, method name, and kwargs.
50
+
"""
38
51
@functools.wraps(method)
39
52
asyncdefwrapper(self, *args, **kwargs):
40
53
try:
@@ -81,13 +94,31 @@ class RepositoryInterface:
81
94
_global_thread_lock=threading.Lock()
82
95
83
96
def__new__(cls, *args, **kwargs):
97
+
"""
98
+
Ensure a single thread-safe instance exists for the subclass.
99
+
100
+
Creates and returns the singleton instance for this subclass, creating it if absent while holding a global thread lock to prevent concurrent instantiation.
Initialize the repository instance for a specific API model and configure its connection pool.
114
+
115
+
Parameters:
116
+
model (ApiBaseModel): The API model used for validation and to determine the repository's collection.
117
+
max_pool_size (int, optional): Maximum size of the MongoDB connection pool. Defaults to 3.
118
+
119
+
Notes:
120
+
If the instance is already initialized, this constructor will not reconfigure it. Initialization of the underlying connection is started asynchronously.
Perform idempotent, retry-safe asynchronous initialization of the repository instance.
132
+
133
+
Ensures a per-instance asyncio.Lock exists and acquires it to run initialization exactly once; on success it marks the instance as initialized and sets the internal _initialized_event so awaiters can proceed. If initialization fails, the original exception from _initialize_connection is propagated after logging.
134
+
"""
99
135
ifgetattr(self, '_initialized', False):
100
136
return
101
137
@@ -117,6 +153,11 @@ async def _async_init(self):
117
153
self._initialized_event.set()
118
154
119
155
def_initialize(self):
156
+
"""
157
+
Ensure the repository's asynchronous initializer is executed: run it immediately if no event loop is active, otherwise schedule it on the running loop.
158
+
159
+
If there is no running asyncio event loop, this method runs self._async_init() to completion on the current thread, blocking until it finishes. If an event loop is running, it schedules self._async_init() as a background task on that loop and returns immediately.
160
+
"""
120
161
try:
121
162
loop=asyncio.get_running_loop()
122
163
exceptRuntimeError:
@@ -125,13 +166,27 @@ def _initialize(self):
125
166
loop.create_task(self._async_init())
126
167
127
168
asyncdef__aenter__(self):
169
+
"""
170
+
Waits for repository initialization to complete and returns the repository instance.
171
+
172
+
Returns:
173
+
RepositoryInterface: The initialized repository instance.
174
+
"""
128
175
awaitself._initialized_event.wait() # Ensure initialization is complete
Initialize the MongoDB async client, store the connection string, and bind the collection for this repository instance.
184
+
185
+
This method fetches the MongoDB connection string from secrets, creates an AsyncMongoClient configured with pool and timeout settings, and sets self._collection to the repository's collection named by the model. On success it logs the initialized client; on failure it raises a ConnectionError.
186
+
187
+
Raises:
188
+
ConnectionError: If the client or collection cannot be initialized.
Copy file name to clipboardExpand all lines: tests/unit/test_mcp/test_mcp_server.py
+6-1Lines changed: 6 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,11 @@
12
12
13
13
@pytest.fixture(autouse=True)
14
14
defreset_mcp_state():
15
+
"""
16
+
Ensure the FastAPI app has no lingering MCP state before and after a test.
17
+
18
+
This fixture deletes app.state.mcp if it exists, yields control to the test, and then deletes app.state.mcp again to guarantee the MCP state is cleared between tests.
0 commit comments