fix: retry dictionary downloads on network-switch errors

Downloads killed by WiFi/mobile transitions failed with the generic
"Dictionary download failed" message because UnknownHostException,
ConnectException, unexpected end of stream, and closed-socket errors
were not classified as network errors and were never retried.
Classify them by exception type and message so the retry loop
engages and exhaustion reports the network-specific message.

Bump OkHttp 5.4.0 to 5.5.0: a throwing system proxy selector now
falls back to a direct connection instead of failing the call,
complementing the download resilience fix.
This commit is contained in:
2026-08-30 00:39:04 +08:00
parent d4e6302274
commit bab03b6c73
2 changed files with 11 additions and 2 deletions
@@ -40,6 +40,10 @@ fun Throwable.isNetworkError(): Boolean {
if (isSslHandshakeError()) return true
return when (this) {
is java.net.UnknownHostException,
is java.net.ConnectException,
is java.net.NoRouteToHostException,
is java.net.BindException -> true
is java.io.IOException -> {
val message = message ?: ""
message.contains("connection", ignoreCase = true) ||
@@ -49,9 +53,14 @@ fun Throwable.isNetworkError(): Boolean {
message.contains("unreachable", ignoreCase = true) ||
message.contains("no route", ignoreCase = true) ||
message.contains("broken pipe", ignoreCase = true) ||
message.contains("resolve host", ignoreCase = true) ||
message.contains("unexpected end of stream", ignoreCase = true) ||
message.contains("socket closed", ignoreCase = true) ||
message.contains("ECONNRESET", ignoreCase = true) ||
message.contains("ECONNREFUSED", ignoreCase = true) ||
message.contains("ENETUNREACH", ignoreCase = true)
message.contains("ECONNABORTED", ignoreCase = true) ||
message.contains("ENETUNREACH", ignoreCase = true) ||
message.contains("EHOSTUNREACH", ignoreCase = true)
}
else -> false
}