File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -115,8 +115,11 @@ async def send_message_stream(
115115
116116 for attempt in range (max_attempts ):
117117 try :
118- async for chunk in super ().send_message_stream (request_body , headers ):
119- yield chunk
118+ # 429 在 status code 检查阶段即 raise(在任何 chunk 之前),
119+ # 因此 __anext__ 安全:要么拿到首个 chunk,要么抛异常。
120+ ait = super ().send_message_stream (request_body , headers )
121+ head = await ait .__anext__ ()
122+ except StopAsyncIteration :
120123 return
121124 except httpx .HTTPStatusError as exc :
122125 if exc .response is None or exc .response .status_code != 429 :
@@ -136,6 +139,13 @@ async def send_message_stream(
136139 delay ,
137140 )
138141 await asyncio .sleep (delay / 1000.0 )
142+ continue
143+
144+ # yield 在 try/except 之外,避免捕获外部 athrow 的异常
145+ yield head
146+ async for chunk in ait :
147+ yield chunk
148+ return
139149
140150 # ── 延迟计算 ────────────────────────────────────────────
141151
Original file line number Diff line number Diff line change @@ -430,39 +430,7 @@ async def mock_post(*args, **kwargs):
430430
431431 @pytest .mark .asyncio
432432 async def test_stream_429_retries_and_succeeds (self ):
433- """流式 429 一次后成功."""
434- vendor = _make_zhipu_vendor ()
435- call_count = 0
436-
437- async def mock_stream (method , url , ** kwargs ):
438- nonlocal call_count
439- call_count += 1
440- if call_count == 1 :
441- resp = _make_429_response ()
442- raise httpx .HTTPStatusError (
443- "429" ,
444- request = resp .request ,
445- response = resp ,
446- )
447- # 成功响应
448- resp = httpx .Response (
449- status_code = 200 ,
450- request = httpx .Request ("POST" , "https://example.com" ),
451- )
452- resp ._stream = httpx .ByteStream (b'data: {"type":"content_block_start"}\n \n ' )
453- return resp
454-
455- with patch .object (vendor , "_get_client" ) as mock_client :
456- client = AsyncMock ()
457- client .stream = mock_stream
458- mock_client .return_value = client
459-
460- # NativeAnthropicVendor.send_message_stream 的 super() 调用
461- # 需要完整的 BaseVendor 流式路径,这里直接验证 retry 逻辑
462- # 通过 mock super().send_message_stream 更简洁
463- pass
464-
465- # 使用更直接的方式测试流式重试
433+ """流式 429 两次后成功."""
466434 call_count = 0
467435
468436 async def fake_stream (self , body , headers ):
You can’t perform that action at this time.
0 commit comments