summaryrefslogtreecommitdiffstats
path: root/src/state/timing.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/timing.rs')
-rw-r--r--src/state/timing.rs75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/state/timing.rs b/src/state/timing.rs
new file mode 100644
index 0000000..406e207
--- /dev/null
+++ b/src/state/timing.rs
@@ -0,0 +1,75 @@
+//! The intervals the protocol runs on, derived from the keepalive.
+
+use std::time::Duration;
+
+use crate::backoff::Backoff;
+
+/// First wait for a sync answer; generous, since Mycelium delivers large messages in
+/// many small packets.
+const SYNC_REPLY_TIMEOUT: Duration = Duration::from_secs(10);
+/// Upper bound, as a multiple of the first wait: 5 minutes (Mycelium gives up on a
+/// message after five minutes).
+const SYNC_REPLY_TIMEOUT_MAX_FACTOR: u32 = 30;
+/// How long Mycelium tries to deliver a message before dropping it.
+const MYCELIUM_DELIVERY_LIMIT: Duration = Duration::from_secs(300);
+
+#[derive(Clone, Copy, Debug)]
+pub(crate) struct Timing {
+ pub(crate) keepalive: Duration,
+ pub(crate) dormant_after: Duration,
+ pub(crate) resync_after: Duration,
+ pub(crate) dormant_probe: Duration,
+ /// While catching up: PING the source after this much silence (`swarm::source`).
+ pub(crate) catch_up_probe: Duration,
+ /// First wait for an answer to a sync message before sending again; doubles while
+ /// answers stay out (`SyncSession::reply_backoff`).
+ pub(crate) sync_reply_timeout: Duration,
+ /// How long the transport tries to deliver a message before dropping it (Mycelium:
+ /// five minutes): a peer silent for longer has nothing on the way to us any more.
+ pub(crate) delivery_limit: Duration,
+}
+
+impl Timing {
+ /// How long a round-trip sample stays meaningful (`swarm::rtt`): a few keepalive
+ /// intervals, since nodes move.
+ pub(crate) fn rtt_fresh_for(&self) -> Duration {
+ self.keepalive * 5
+ }
+
+ // Recommended values
+ // Environment | Keepalive | Notes
+ // --------------------------------------------+-----------+------------------------------------------------------------
+ // Test harness | 1-2 s | Dormancy after about 4–8 s and healing within seconds keep tests short.
+ // LAN or small swarm (up to ~50 nodes) | 15-30 s | Under 3.5 messages/s per node at 50 nodes and 30 s. Current setting.
+ // WAN, mobile or metered links, or 100+ nodes | 60-120 s | At 100 nodes and 30 s it’s about 6–7 messages/s per node. Fine, but rarely worth it on battery or metered links.
+ // Several hundred nodes or more | - | The full mesh becomes the problem in itself, not the interval. Message counts grow O(N²) across the swarm, which calls for partial views (SWIM-style random probing and syncing with a subset of peers).
+ pub(crate) fn from_keepalive(keepalive: Duration) -> Self {
+ Self::new(keepalive, SYNC_REPLY_TIMEOUT)
+ }
+
+ /// [`from_keepalive`](Self::from_keepalive) with another first sync reply timeout:
+ /// for tests, whose messages don't travel for seconds.
+ pub(crate) fn new(keepalive: Duration, sync_reply_timeout: Duration) -> Self {
+ Self {
+ keepalive,
+ dormant_after: keepalive * 4, // dormant_after >= 4* keepalive to tolerate three lost PINGs in a row
+ // >= 2 keepalives, so a second exchange confirms the difference; and >= twice
+ // the first sync reply timeout, so a lost message's sender resends it first.
+ resync_after: (keepalive * 2).max(sync_reply_timeout * 2),
+ dormant_probe: keepalive * 10, // >= 10*: dormant peers cost almost nothing, but still rejoin within minutes
+ // Seconds, not a keepalive interval: a dead source should cost little time.
+ // Only the source gets these, and only while catching up.
+ catch_up_probe: (keepalive / 30).clamp(Duration::from_secs(1), Duration::from_secs(5)),
+ sync_reply_timeout,
+ delivery_limit: MYCELIUM_DELIVERY_LIMIT,
+ }
+ }
+
+ /// Waits for sync answers: `sync_reply_timeout`, doubling up to 30 times as much.
+ pub(crate) fn sync_reply_backoff(&self) -> Backoff {
+ Backoff::new(
+ self.sync_reply_timeout,
+ self.sync_reply_timeout * SYNC_REPLY_TIMEOUT_MAX_FACTOR,
+ )
+ }
+}