BrokerPort: cap the wait after a pending frame at a day
M3a review finding 8. The wait was expires plus the timeout with no bound, and the "expiry too far away" guard could not fire, so a far expiry (which brokerd produces when now + ttl_ms does not fit) parked a turn for ever. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
//! After a pending frame, `BrokerPort` waits for `expires` plus its timeout, but never longer than
|
||||
//! its cap, whatever `expires` says (M3a review finding 8). `brokerd` falls back to the largest
|
||||
//! timestamp when `now + ttl_ms` does not fit, so a far `expires` is reachable by configuration.
|
||||
|
||||
#[path = "support/broker.rs"]
|
||||
mod fake;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use fake::{broker, request, send};
|
||||
use loopd::broker_port::{BrokerPort, MAX_PENDING_WAIT, UNAVAILABLE};
|
||||
use loopd::tools::ToolPort;
|
||||
use proto::{Timestamp, ToolResponse};
|
||||
|
||||
#[test]
|
||||
fn the_default_cap_is_a_day() {
|
||||
assert_eq!(MAX_PENDING_WAIT, Duration::from_secs(24 * 60 * 60));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_pending_frame_with_the_largest_expiry_still_ends_at_the_cap() {
|
||||
let (socket, broker) = broker(|stream, request| {
|
||||
let pending = ToolResponse::PendingApproval {
|
||||
approval: 7,
|
||||
expires: Timestamp::MAX,
|
||||
};
|
||||
send(stream, request.id, false, pending);
|
||||
thread::sleep(Duration::from_millis(1_500));
|
||||
});
|
||||
let lines = Arc::new(Mutex::new(Vec::new()));
|
||||
let sink = lines.clone();
|
||||
let port = BrokerPort::with_log(
|
||||
socket,
|
||||
Duration::from_millis(100),
|
||||
Box::new(move |line| sink.lock().unwrap().push(line.to_string())),
|
||||
)
|
||||
.with_pending_cap(Duration::from_millis(200));
|
||||
|
||||
let started = Instant::now();
|
||||
let answer = port.call(&request(), &mut |_| {});
|
||||
let took = started.elapsed();
|
||||
assert_eq!(
|
||||
answer,
|
||||
ToolResponse::Failed {
|
||||
message: UNAVAILABLE.to_string()
|
||||
}
|
||||
);
|
||||
assert!(
|
||||
took >= Duration::from_millis(250),
|
||||
"cap plus timeout: {took:?}"
|
||||
);
|
||||
assert!(
|
||||
took < Duration::from_millis(1_200),
|
||||
"gave up late: {took:?}"
|
||||
);
|
||||
assert_eq!(lines.lock().unwrap().len(), 1);
|
||||
broker.join().unwrap();
|
||||
}
|
||||
Reference in New Issue
Block a user