From 66f05e161ae0697fd2d376d0c666a5ad8f46984f Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 10 Sep 2026 11:40:11 +0200 Subject: [PATCH] Expose fragment-set evictions in transport stats A receiver that survives loss by discarding stranded sets has to say so, or the drop is invisible and the next diagnosis starts from "delivered less than sent" again. CultNetTransportStats now carries fragment_sets_evicted, summed across hub peers like reliable_packets_expired, and the media delivery probe prints it beside delivered_pct. Co-Authored-By: Claude Fable 5.1 --- packages/cultnet-rs/examples/media_delivery_probe.rs | 5 +++-- packages/cultnet-rs/src/rudp.rs | 6 ++++++ packages/cultnet-rs/src/transport.rs | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/cultnet-rs/examples/media_delivery_probe.rs b/packages/cultnet-rs/examples/media_delivery_probe.rs index 75058eaf..e1f2ac97 100644 --- a/packages/cultnet-rs/examples/media_delivery_probe.rs +++ b/packages/cultnet-rs/examples/media_delivery_probe.rs @@ -87,10 +87,11 @@ fn recv(bind: SocketAddr, expect: u64) -> Result<()> { let elapsed = started.elapsed().as_secs_f64(); println!("RESULT recv frames={frames} expected={expect} payload_bytes={payload_bytes}"); println!( - "RESULT recv wire_bytes_in={} wire_bytes_out={} elapsed_s={elapsed:.2} delivered_pct={:.2}", + "RESULT recv wire_bytes_in={} wire_bytes_out={} elapsed_s={elapsed:.2} delivered_pct={:.2} fragment_sets_evicted={}", stats.bytes_received, stats.bytes_sent, - (frames as f64 / expect as f64) * 100.0 + (frames as f64 / expect as f64) * 100.0, + stats.fragment_sets_evicted ); Ok(()) } diff --git a/packages/cultnet-rs/src/rudp.rs b/packages/cultnet-rs/src/rudp.rs index 7e871288..b6a8fe95 100644 --- a/packages/cultnet-rs/src/rudp.rs +++ b/packages/cultnet-rs/src/rudp.rs @@ -1453,6 +1453,11 @@ impl CultNetRudpServerHub { .values() .map(|peer| peer.session.reliable_packets_expired()) .fold(0_u64, |total, expired| total.saturating_add(expired)); + stats.fragment_sets_evicted = self + .peers + .values() + .map(|peer| peer.session.fragment_sets_evicted()) + .fold(0_u64, |total, evicted| total.saturating_add(evicted)); stats } @@ -1754,6 +1759,7 @@ impl CultNetRudpSocketTransportConnection { pub fn stats(&self) -> CultNetTransportStats { let mut stats = self.stats.clone(); stats.reliable_packets_expired = self.session.reliable_packets_expired(); + stats.fragment_sets_evicted = self.session.fragment_sets_evicted(); stats } diff --git a/packages/cultnet-rs/src/transport.rs b/packages/cultnet-rs/src/transport.rs index cf28079e..d097aa3c 100644 --- a/packages/cultnet-rs/src/transport.rs +++ b/packages/cultnet-rs/src/transport.rs @@ -22,6 +22,10 @@ pub struct CultNetTransportStats { /// Reliable packets dropped by a send-side expiry deadline instead of being /// retransmitted. Always zero for transports without reliable expiry. pub reliable_packets_expired: u64, + /// Incomplete fragment sets discarded to admit newer ones. Each is one + /// payload that lost a fragment on the wire. Zero for non-fragmenting + /// transports. + pub fragment_sets_evicted: u64, } #[derive(Clone, Debug, PartialEq, Eq)]