Time out on a stalled transfer, not on a slow one
The HTTP client had a 60-second *total* request timeout. That is not a hang detector; it is a floor on link speed. A face shard runs to 25 MB, so it demanded a sustained 425 KB/s or the transfer failed — and having failed it was retried on the next pass and failed again, for ever. A tablet on ordinary wifi could therefore never finish taking in a library's faces, and nothing said why: each attempt looked like a network blip rather than an arithmetic impossibility. The catalog snapshot is 36 MB and has the same problem. `read_timeout` fires when no bytes arrive for the period, which is the condition actually worth failing on. A slow transfer that is still moving now finishes, however long it takes; a connection that has genuinely died is still caught in a minute. The connect timeout is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -637,11 +637,23 @@ pub fn http_client(user_agent: &str) -> Result<reqwest::Client, RemoteError> {
|
|||||||
// webpki-roots set is still installed alongside.
|
// webpki-roots set is still installed alongside.
|
||||||
.tls_certs_only(extra_roots())
|
.tls_certs_only(extra_roots())
|
||||||
// A request that hangs forever is indistinguishable from a worker that
|
// A request that hangs forever is indistinguishable from a worker that
|
||||||
// died, and cost a long time to tell apart once. Connect and total
|
// died, and cost a long time to tell apart once. These turn that into
|
||||||
// timeouts turn that into an error the UI can show. Generous enough for
|
// an error the UI can show.
|
||||||
// a slow phone on mobile data; the login poll has its own deadline.
|
|
||||||
.connect_timeout(std::time::Duration::from_secs(15))
|
.connect_timeout(std::time::Duration::from_secs(15))
|
||||||
.timeout(std::time::Duration::from_secs(60))
|
// **Inactivity, not duration.** This was a 60-second *total* timeout,
|
||||||
|
// which is not a hang detector at all — it is a floor on link speed.
|
||||||
|
// A face shard runs to 25 MB, so it demanded a sustained 425 KB/s or
|
||||||
|
// the transfer failed; and having failed it was retried on the next
|
||||||
|
// pass, and failed again, for ever. A tablet on ordinary wifi could
|
||||||
|
// therefore never finish adopting a library's faces, and nothing said
|
||||||
|
// why: each attempt looked like a network blip rather than an
|
||||||
|
// arithmetic impossibility.
|
||||||
|
//
|
||||||
|
// `read_timeout` fires when *no bytes arrive* for the given period,
|
||||||
|
// which is the condition actually worth failing on. A slow transfer
|
||||||
|
// that is still moving now finishes, however long it takes, while a
|
||||||
|
// connection that has genuinely died is still caught in a minute.
|
||||||
|
.read_timeout(std::time::Duration::from_secs(60))
|
||||||
.build()
|
.build()
|
||||||
.map_err(|e| RemoteError::Network(e.to_string()))
|
.map_err(|e| RemoteError::Network(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user