summaryrefslogtreecommitdiffstats
path: root/src/transport/mycelium
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-26 19:00:35 +0100
committertv <tv@krebsco.de>2026-10-26 19:00:35 +0100
commit2427b22204c72443fd1890583e39568140037ea4 (patch)
tree3551cda034bbd9a926dd90c7e889912824b49592 /src/transport/mycelium
parent181d75a0335a56e5295b035ec93795f0dfba6b26 (diff)
POST timeout depends on content size
Replace the fixed timeout by a variable one depending on content size with the formula: 10 s + content-size / 1 MiB/s
Diffstat (limited to 'src/transport/mycelium')
-rw-r--r--src/transport/mycelium/mod.rs25
1 files changed, 24 insertions, 1 deletions
diff --git a/src/transport/mycelium/mod.rs b/src/transport/mycelium/mod.rs
index f20f6a0..4edd1fd 100644
--- a/src/transport/mycelium/mod.rs
+++ b/src/transport/mycelium/mod.rs
@@ -15,6 +15,13 @@ pub mod daemon;
pub use daemon::{MyceliumSetup, MyceliumSpawnConfig};
const MYCELIUM_POLL_TIMEOUT_SECS: u64 = 300;
+/// How long a request to our Mycelium may take, before what its body adds
+/// (`post_timeout`).
+const REQUEST_TIMEOUT: Duration = Duration::from_secs(10);
+/// The slowest our Mycelium is expected to take a message body, in bytes per second:
+/// a large sync message gets more time than a PING, instead of failing (and being
+/// generated and sent whole again) at a fixed limit.
+const POST_MIN_RATE: u64 = 1 << 20;
/// The one Mycelium topic all of continuum's messages travel on; what a message is, its
/// payload says (`wire`).
@@ -74,7 +81,7 @@ impl MyceliumTransport {
let rest_url = setup.rest_url.clone();
let client = reqwest::Client::builder()
- .timeout(Duration::from_secs(10))
+ .timeout(REQUEST_TIMEOUT)
.build()?;
let poll_client = reqwest::Client::builder()
.timeout(Duration::from_secs(MYCELIUM_POLL_TIMEOUT_SECS + 30))
@@ -205,6 +212,7 @@ impl Transport for MyceliumTransport {
.client
.post(self.messages_endpoint.clone())
.header(reqwest::header::CONTENT_TYPE, "application/json")
+ .timeout(post_timeout(message.body.len()))
.body(message.body.clone())
.send()
.await?;
@@ -398,6 +406,12 @@ fn encode_payload(payload: &Vec<u8>) -> String {
BASE64.encode(payload)
}
+/// How long posting a body of `bytes` may take: `REQUEST_TIMEOUT`, plus the body at
+/// `POST_MIN_RATE`.
+fn post_timeout(bytes: usize) -> Duration {
+ REQUEST_TIMEOUT + Duration::from_millis(bytes as u64 * 1000 / POST_MIN_RATE)
+}
+
/// Length of what padded base64 `encoded` decodes to.
fn base64_decoded_len(encoded: &str) -> usize {
let padding = encoded.bytes().rev().take_while(|&b| b == b'=').count();
@@ -479,6 +493,15 @@ mod tests {
const MYCELIUM_CHUNK: usize = 1300;
#[test]
+ fn post_timeout_grows_with_the_body() {
+ assert_eq!(post_timeout(0), REQUEST_TIMEOUT);
+ assert_eq!(
+ post_timeout(64 << 20),
+ REQUEST_TIMEOUT + Duration::from_secs(64)
+ );
+ }
+
+ #[test]
fn largest_keepalive_fits_in_one_chunk() {
let keepalive = Keepalive {
heads: HeadsSummary::Heads(