fix(managed): decouple peer-close control from event delivery

Add a scheduler-owned saturating peer-close counter shared with the group session. Update it before best-effort TargetFinished publication so bounded subscriber overflow cannot hide the live shutdown condition, while retaining the existing events, bounded history, and aggregate accounting.

Make grouped CLI and TUI supervision consult the durable count on each existing activity loop and funnel both count and event observations through one-shot stop policy. Preserve interruption suppression, queued-event draining, structured failures, drop reporting, and peer-close diagnostic precedence.

Cover scheduler-only accounting, non-peer exclusions, receiver and removal races, deterministic capacity-one DropOldest eviction with an active target, frontend one-shot policy, and the existing process-level peer-close and interruption behavior.
This commit is contained in:
Nils Andreas Svee committed 2026-07-28 15:49:53 +07:00
1 parent bbe3261eb3
commit 7cc55bd619
4 files changed
+316 -59

No files matched your search

+19 -8
View File
@@ -26,8 +26,8 @@ use crate::shared::client::expected_probe_count;
use crate::shared::client::{
is_shutdown_requested,
session::{
peer_close_run_error, request_group_stop_once, should_print_final_summary,
should_stop_group_on_peer_close,
peer_close_run_error, request_group_stop_for_peer_close, request_group_stop_once,
should_print_final_summary,
},
};
@@ -396,6 +396,15 @@ fn run_group_stream(
session.stop();
}
}
if request_group_stop_for_peer_close(
continuous,
interrupted,
session.peer_closed_target_count(),
&mut peer_close_requested_stop,
&mut stop_requested,
) {
session.stop();
}
match events.try_recv() {
Ok(Some(group_event)) => {
@@ -423,15 +432,17 @@ fn run_group_stream(
ManagedGroupEvent::TargetFinished(target) => {
report_target_failure(&target);
terminal_targets.insert(target.id.as_str().to_owned());
if should_stop_group_on_peer_close(
if request_group_stop_for_peer_close(
continuous,
interrupted,
&target.end_reason,
u64::from(matches!(
&target.end_reason,
irtt_client::ManagedTargetEndReason::PeerClosed
)),
&mut peer_close_requested_stop,
&mut stop_requested,
) {
peer_close_requested_stop = true;
if request_group_stop_once(&mut stop_requested) {
session.stop();
}
session.stop();
}
}
}
+48 -15
View File
@@ -16,7 +16,9 @@ use crate::{
cmd::tui::args::{ResolvedTuiTarget, TuiArgs},
shared::client::{
is_shutdown_requested,
session::{peer_close_run_error, request_group_stop_once, should_stop_group_on_peer_close},
session::{
peer_close_run_error, request_group_stop_for_peer_close, request_group_stop_once,
},
},
};
@@ -200,6 +202,15 @@ fn run_group_tui(
session.stop();
}
}
if request_group_stop_for_peer_close(
args.is_continuous(),
interrupted,
session.peer_closed_target_count(),
&mut peer_close_requested_stop,
&mut stop_requested,
) {
session.stop();
}
match events.try_recv() {
Ok(Some(group_event)) => {
@@ -212,15 +223,17 @@ fn run_group_tui(
ManagedGroupEvent::TargetFinished(target) => {
terminal_targets.insert(target.id.as_str().to_owned());
state.process_target_outcome(&target);
if should_stop_group_on_peer_close(
if request_group_stop_for_peer_close(
args.is_continuous(),
interrupted,
&target.end_reason,
u64::from(matches!(
&target.end_reason,
irtt_client::ManagedTargetEndReason::PeerClosed
)),
&mut peer_close_requested_stop,
&mut stop_requested,
) {
peer_close_requested_stop = true;
if request_group_stop_once(&mut stop_requested) {
session.stop();
}
session.stop();
}
}
}
@@ -553,21 +566,41 @@ mod tests {
}
#[test]
fn continuous_group_peer_close_requests_stop_unless_interrupted() {
assert!(should_stop_group_on_peer_close(
fn continuous_group_reliable_peer_close_status_requests_stop_once() {
let mut peer_close_requested_stop = false;
let mut stop_requested = false;
assert!(request_group_stop_for_peer_close(
true,
false,
&irtt_client::ManagedTargetEndReason::PeerClosed
1,
&mut peer_close_requested_stop,
&mut stop_requested,
));
assert!(!should_stop_group_on_peer_close(
assert!(peer_close_requested_stop);
assert!(stop_requested);
assert!(!request_group_stop_for_peer_close(
true,
false,
false,
&irtt_client::ManagedTargetEndReason::PeerClosed
1,
&mut peer_close_requested_stop,
&mut stop_requested,
));
assert!(!should_stop_group_on_peer_close(
let mut peer_close_requested_stop = false;
let mut stop_requested = false;
assert!(!request_group_stop_for_peer_close(
false,
false,
1,
&mut peer_close_requested_stop,
&mut stop_requested,
));
assert!(!request_group_stop_for_peer_close(
true,
true,
&irtt_client::ManagedTargetEndReason::PeerClosed
1,
&mut peer_close_requested_stop,
&mut stop_requested,
));
}