修复: 连接池收敛与传输错误分类重试
- 连接池空闲十五秒,陈旧连接复用致重置根治 - 流式发送错误改谓词分类,openai 路径不再裸奔 - decode 类失败纳入重试,正文中断可自愈 - 状态分类合并响应体,激活休眠词表分支 - 手动压缩失败降级兜底,不再弹红卡
This commit is contained in:
@@ -600,7 +600,9 @@ impl LlmProvider for AnthropicCompatProvider {
|
||||
source = ?std::error::Error::source(&e),
|
||||
"Anthropic 同步 send 失败"
|
||||
);
|
||||
if is_reqwest_error_retryable(&e) {
|
||||
// is_decode 补可重试:body 中途断连在 reqwest 归 decode 类,complete 重发
|
||||
// 幂等安全(受 3 次/30s 预算约束,真正格式错重试同败,预算内止损)。
|
||||
if is_reqwest_error_retryable(&e) || e.is_decode() {
|
||||
return AttemptOutcome::Retryable(format!("请求失败(可重试): {}", e));
|
||||
}
|
||||
return AttemptOutcome::Fatal(format!(
|
||||
@@ -626,7 +628,13 @@ impl LlmProvider for AnthropicCompatProvider {
|
||||
}
|
||||
let resp: AnthropicResponse = match resp.json().await {
|
||||
Ok(r) => r,
|
||||
Err(e) => return AttemptOutcome::Fatal(format!("响应解析失败: {}", e)),
|
||||
// serde 结构错属 Fatal(重试同败);body 读取中途断连同归 is_decode,可重试。
|
||||
Err(e) => {
|
||||
if e.is_decode() {
|
||||
return AttemptOutcome::Retryable(format!("响应解码失败(可重试): {}", e));
|
||||
}
|
||||
return AttemptOutcome::Fatal(format!("响应解析失败: {}", e));
|
||||
}
|
||||
};
|
||||
// content 块中拼接 text,收集 tool_use
|
||||
let mut text = String::new();
|
||||
@@ -714,17 +722,24 @@ impl LlmProvider for AnthropicCompatProvider {
|
||||
let resp = match tokio::time::timeout(Duration::from_secs(60), send_future).await {
|
||||
Ok(Ok(r)) => r,
|
||||
Ok(Err(e)) => {
|
||||
// 谓词结构化分类(对齐 openai 路径,共用 crate::send_error_class)。原 bail 串
|
||||
// [timeout={} connect={}=...] 的字面词让一切错误(含 builder 错)侥幸可重试。
|
||||
// 类词改由谓词决定置串首;谓词转储缩写为 t/c/b/r 防误触分类词表,source 链
|
||||
// 保留真实传输词(reset/broken pipe 等)作串兜底。
|
||||
let class = crate::send_error_class(crate::SendErrPreds::of(&e));
|
||||
tracing::error!(
|
||||
is_timeout = e.is_timeout(),
|
||||
is_connect = e.is_connect(),
|
||||
is_body = e.is_body(),
|
||||
is_request = e.is_request(),
|
||||
class = class,
|
||||
url = %self.messages_url(),
|
||||
source = ?std::error::Error::source(&e),
|
||||
"Anthropic 流式 send 失败"
|
||||
);
|
||||
anyhow::bail!(
|
||||
"send 失败: {} [timeout={} connect={} body={} request={} src={:?}]",
|
||||
"send 失败({}): {} [t={} c={} b={} r={} src={:?}]",
|
||||
class,
|
||||
e,
|
||||
e.is_timeout(),
|
||||
e.is_connect(),
|
||||
|
||||
Reference in New Issue
Block a user