Task to read responses from the socket and set results on futures.
(self)
| 336 | continue |
| 337 | |
| 338 | async def _response_reader(self): |
| 339 | """Task to read responses from the socket and set results on futures.""" |
| 340 | logger_debug("[client] Response reader started") |
| 341 | self._reader_asyncio_task = asyncio.current_task() |
| 342 | |
| 343 | try: |
| 344 | # Add initial delay to ensure socket is fully connected |
| 345 | # This helps prevent race conditions during initialization |
| 346 | await asyncio.sleep(0.1) |
| 347 | logger_debug("[client] Response reader ready to process messages") |
| 348 | |
| 349 | with customized_gc_thresholds(10000): |
| 350 | last_alive_log = time.time() |
| 351 | while not self._closed: |
| 352 | # Periodic alive logging for debugging |
| 353 | if time.time() - last_alive_log > 5.0: |
| 354 | logger_debug( |
| 355 | "[client] Response reader is alive and waiting for responses" |
| 356 | ) |
| 357 | last_alive_log = time.time() |
| 358 | |
| 359 | with nvtx_range_debug("response_reader", |
| 360 | color="cyan", |
| 361 | category="RPC"): |
| 362 | try: |
| 363 | response = await self._wait_for_response() |
| 364 | logger_debug( |
| 365 | f"[client] [{datetime.now().isoformat()}] Received response: {response}" |
| 366 | ) |
| 367 | |
| 368 | nvtx_mark_debug( |
| 369 | f"RPC.response.{'streaming' if response.is_streaming else 'sync'}", |
| 370 | color="black", |
| 371 | category="RPC") |
| 372 | |
| 373 | # Optimize: Check debug flag before expensive string operations |
| 374 | # This avoids holding GIL for f-string evaluation when debug is disabled |
| 375 | if enable_llmapi_debug() or logger.level == 'debug': |
| 376 | logger_debug( |
| 377 | f"[client] [{datetime.now().isoformat()}] RPC Client received response: request_id={response.request_id}, " |
| 378 | f"is_streaming={response.is_streaming}, " |
| 379 | f"pending_futures={len(self._pending_futures)}" |
| 380 | ) |
| 381 | |
| 382 | with nvtx_range_debug("handle_response", |
| 383 | color="purple", |
| 384 | category="RPC"): |
| 385 | if response.is_streaming: |
| 386 | self._handle_streaming_response(response) |
| 387 | else: |
| 388 | self._handle_regular_response(response) |
| 389 | |
| 390 | except asyncio.CancelledError: |
| 391 | # Re-raise cancellation to exit cleanly |
| 392 | raise |
| 393 | except Exception as e: |
| 394 | # Log the error but continue reading unless it's a critical error |
| 395 | logger.error(f"Error processing response: {e}", |
no test coverage detected