diff --git a/tools/soak/appworld.py b/tools/soak/appworld.py index a381540..2bc1346 100644 --- a/tools/soak/appworld.py +++ b/tools/soak/appworld.py @@ -796,8 +796,21 @@ async def _post_json( path: str, body: Mapping[str, Any], ) -> Any: - """打一个 POST,检查状态码,剥掉 environment server 统一的 output 包装。""" - response = await client.post(f"{base_url}{path}", json=dict(body)) + """打一个 POST,检查状态码,剥掉 environment server 统一的 output 包装。 + + **传输层的失败也要翻成 `AppWorldError`。** 连不上、读超时、连接中途断掉,httpx 抛的是 + 它自己的异常类型,而上层的动作执行接缝只认 `AppWorldError`——不翻的话,容器挂掉会让整 + 次运行以一个未捕获的第三方异常炸出去,而正确的行为是记成环境故障、由库合成一段观察、 + 以 `env_error` 收尾。这个缺口是压测里真把容器 `docker kill` 掉之后才暴露的:在那之前 + 「连不上」这一档只写在上面那个 docstring 里,没有实现。 + + `asyncio.CancelledError` 不在 `httpx.HTTPError` 的范围内(它继承 `BaseException`), + 所以取消照旧原样穿过去。 + """ + try: + response = await client.post(f"{base_url}{path}", json=dict(body)) + except httpx.HTTPError as exc: + raise AppWorldError(f"{path} 的请求没能完成:{type(exc).__name__}: {exc}") from exc if response.is_error: raise AppWorldError(f"{path} 返回 HTTP {response.status_code}:{response.text[:2000]}") payload = response.json()