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:
@@ -40,6 +40,10 @@ fun Throwable.isNetworkError(): Boolean {
|
|||||||
if (isSslHandshakeError()) return true
|
if (isSslHandshakeError()) return true
|
||||||
|
|
||||||
return when (this) {
|
return when (this) {
|
||||||
|
is java.net.UnknownHostException,
|
||||||
|
is java.net.ConnectException,
|
||||||
|
is java.net.NoRouteToHostException,
|
||||||
|
is java.net.BindException -> true
|
||||||
is java.io.IOException -> {
|
is java.io.IOException -> {
|
||||||
val message = message ?: ""
|
val message = message ?: ""
|
||||||
message.contains("connection", ignoreCase = true) ||
|
message.contains("connection", ignoreCase = true) ||
|
||||||
@@ -49,9 +53,14 @@ fun Throwable.isNetworkError(): Boolean {
|
|||||||
message.contains("unreachable", ignoreCase = true) ||
|
message.contains("unreachable", ignoreCase = true) ||
|
||||||
message.contains("no route", ignoreCase = true) ||
|
message.contains("no route", ignoreCase = true) ||
|
||||||
message.contains("broken pipe", 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("ECONNRESET", ignoreCase = true) ||
|
||||||
message.contains("ECONNREFUSED", 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
|
else -> false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ datastore_preferences = "1.2.1"
|
|||||||
documentfile = "1.1.0"
|
documentfile = "1.1.0"
|
||||||
kotlin = "2.4.10"
|
kotlin = "2.4.10"
|
||||||
lifecycle_runtime_ktx = "2.11.0"
|
lifecycle_runtime_ktx = "2.11.0"
|
||||||
okhttp = "5.4.0"
|
okhttp = "5.5.0"
|
||||||
paging = "3.5.1"
|
paging = "3.5.1"
|
||||||
profileinstaller = "1.4.1"
|
profileinstaller = "1.4.1"
|
||||||
kotlinx_coroutines = "1.11.0"
|
kotlinx_coroutines = "1.11.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user