fix(providers): classify transport errors as retriable for fallback chain

Add transport-level connection error patterns to error classifier:
- connection reset by peer
- connection refused
- no route to host
- unexpected eof
- broken pipe
- network is unreachable
- connection closed
- tls handshake errors
- read/write tcp errors

These errors are now classified as FailoverTimeout (retriable), allowing
the fallback chain to continue instead of aborting on unclassified errors.

Fixes #1419 (part 1)
This commit is contained in:
曾文锋0668000834 2026-03-13 09:15:55 +08:00
parent 19835b2f60
commit ca1bde5e18

View file

@ -50,6 +50,20 @@ var (
substr("context deadline exceeded"), substr("context deadline exceeded"),
} }
// Transport-level connection errors that should trigger fallback
transportErrorPatterns = []errorPattern{
substr("connection reset by peer"),
substr("connection refused"),
substr("no route to host"),
substr("unexpected eof"),
substr("broken pipe"),
substr("network is unreachable"),
substr("connection closed"),
substr("tls handshake"),
substr("read tcp"),
substr("write tcp"),
}
billingPatterns = []errorPattern{ billingPatterns = []errorPattern{
rxp(`\b402\b`), rxp(`\b402\b`),
substr("payment required"), substr("payment required"),
@ -195,6 +209,9 @@ func classifyByMessage(msg string) FailoverReason {
if matchesAny(msg, timeoutPatterns) { if matchesAny(msg, timeoutPatterns) {
return FailoverTimeout return FailoverTimeout
} }
if matchesAny(msg, transportErrorPatterns) {
return FailoverTimeout // Transport errors treated as timeout (retriable)
}
if matchesAny(msg, authPatterns) { if matchesAny(msg, authPatterns) {
return FailoverAuth return FailoverAuth
} }