@@ -253,3 +253,94 @@ async def test_deliver_registers_resolver_for_request_messages(
253253
254254 assert "inner-req-1" in handler ._pending_requests
255255 assert handler ._pending_requests ["inner-req-1" ] is resolver
256+
257+
258+ @pytest .mark .anyio
259+ async def test_deliver_skips_resolver_registration_when_no_original_id (
260+ store : InMemoryTaskStore , queue : InMemoryTaskMessageQueue , handler : TaskResultHandler
261+ ) -> None :
262+ """Test that _deliver_queued_messages skips resolver registration when original_request_id is None."""
263+ task = await store .create_task (TaskMetadata (ttl = 60000 ), task_id = "test-task" )
264+
265+ resolver : Resolver [dict [str , Any ]] = Resolver ()
266+ queued_msg = QueuedMessage (
267+ type = "request" ,
268+ message = JSONRPCRequest (
269+ jsonrpc = "2.0" ,
270+ id = "inner-req-1" ,
271+ method = "elicitation/create" ,
272+ params = {},
273+ ),
274+ resolver = resolver ,
275+ original_request_id = None , # No original request ID
276+ )
277+ await queue .enqueue (task .taskId , queued_msg )
278+
279+ mock_session = Mock ()
280+ mock_session .send_message = AsyncMock ()
281+
282+ await handler ._deliver_queued_messages (task .taskId , mock_session , "outer-req-1" )
283+
284+ # Resolver should NOT be registered since original_request_id is None
285+ assert len (handler ._pending_requests ) == 0
286+ # But the message should still be sent
287+ mock_session .send_message .assert_called_once ()
288+
289+
290+ @pytest .mark .anyio
291+ async def test_wait_for_task_update_handles_store_exception (
292+ store : InMemoryTaskStore , queue : InMemoryTaskMessageQueue , handler : TaskResultHandler
293+ ) -> None :
294+ """Test that _wait_for_task_update handles store exception gracefully."""
295+ task = await store .create_task (TaskMetadata (ttl = 60000 ), task_id = "test-task" )
296+
297+ # Make wait_for_update raise an exception
298+ async def failing_wait (task_id : str ) -> None :
299+ raise RuntimeError ("Store error" )
300+
301+ store .wait_for_update = failing_wait # type: ignore[method-assign]
302+
303+ # Queue a message to unblock the race via the queue path
304+ async def enqueue_later () -> None :
305+ await anyio .sleep (0.01 )
306+ await queue .enqueue (
307+ task .taskId ,
308+ QueuedMessage (
309+ type = "notification" ,
310+ message = JSONRPCRequest (
311+ jsonrpc = "2.0" ,
312+ id = "notif-1" ,
313+ method = "test/notification" ,
314+ params = {},
315+ ),
316+ ),
317+ )
318+
319+ async with anyio .create_task_group () as tg :
320+ tg .start_soon (enqueue_later )
321+ # This should complete via the queue path even though store raises
322+ await handler ._wait_for_task_update (task .taskId )
323+
324+
325+ @pytest .mark .anyio
326+ async def test_wait_for_task_update_handles_queue_exception (
327+ store : InMemoryTaskStore , queue : InMemoryTaskMessageQueue , handler : TaskResultHandler
328+ ) -> None :
329+ """Test that _wait_for_task_update handles queue exception gracefully."""
330+ task = await store .create_task (TaskMetadata (ttl = 60000 ), task_id = "test-task" )
331+
332+ # Make wait_for_message raise an exception
333+ async def failing_wait (task_id : str ) -> None :
334+ raise RuntimeError ("Queue error" )
335+
336+ queue .wait_for_message = failing_wait # type: ignore[method-assign]
337+
338+ # Update the store to unblock the race via the store path
339+ async def update_later () -> None :
340+ await anyio .sleep (0.01 )
341+ await store .update_task (task .taskId , status = "completed" )
342+
343+ async with anyio .create_task_group () as tg :
344+ tg .start_soon (update_later )
345+ # This should complete via the store path even though queue raises
346+ await handler ._wait_for_task_update (task .taskId )
0 commit comments