mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2026-11-03 04:40:14 -06:00
chore: timeouts on channel calls to the bus
This commit is contained in:
1 parent
df1c9848d3
commit
0d9acda3e1
1 file changed
+57
-8
@@ -3,22 +3,70 @@ use lqos_bus::{BusReply, BusRequest, BusResponse};
|
|||||||
use lqos_probe::{ProbeClass, ProbeRequest};
|
use lqos_probe::{ProbeClass, ProbeRequest};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::time::Duration;
|
use std::time::{Duration, Instant};
|
||||||
|
use tokio::sync::mpsc::error::TrySendError;
|
||||||
|
use tokio::sync::oneshot::error::TryRecvError;
|
||||||
|
|
||||||
use crate::AttachmentProbeSpec;
|
use crate::AttachmentProbeSpec;
|
||||||
|
|
||||||
use super::TopologyBusSender;
|
use super::TopologyBusSender;
|
||||||
|
|
||||||
const TOPOLOGY_PROBE_MAX_AGE_MS: u64 = 250;
|
const TOPOLOGY_PROBE_MAX_AGE_MS: u64 = 250;
|
||||||
|
const BUS_CALL_TIMEOUT_MARGIN: Duration = Duration::from_millis(500);
|
||||||
|
const BUS_CALL_POLL_INTERVAL: Duration = Duration::from_millis(10);
|
||||||
|
|
||||||
fn bus_call(bus_tx: TopologyBusSender, request: BusRequest) -> anyhow::Result<BusReply> {
|
fn sleep_until_deadline(deadline: Instant) -> bool {
|
||||||
let (once_tx, once_rx) = tokio::sync::oneshot::channel();
|
let now = Instant::now();
|
||||||
|
if now >= deadline {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::thread::sleep(
|
||||||
|
deadline
|
||||||
|
.saturating_duration_since(now)
|
||||||
|
.min(BUS_CALL_POLL_INTERVAL),
|
||||||
|
);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bus_call(
|
||||||
|
bus_tx: TopologyBusSender,
|
||||||
|
request: BusRequest,
|
||||||
|
timeout: Duration,
|
||||||
|
) -> anyhow::Result<BusReply> {
|
||||||
|
let deadline = Instant::now()
|
||||||
|
.checked_add(timeout)
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Invalid bus call timeout: {timeout:?}"))?;
|
||||||
|
let (once_tx, mut once_rx) = tokio::sync::oneshot::channel();
|
||||||
let request_copy = request.clone();
|
let request_copy = request.clone();
|
||||||
bus_tx.blocking_send((once_tx, request))?;
|
let mut pending = Some((once_tx, request));
|
||||||
if let Ok(reply) = once_rx.blocking_recv() {
|
|
||||||
Ok(reply)
|
while let Some(message) = pending.take() {
|
||||||
} else {
|
match bus_tx.try_send(message) {
|
||||||
anyhow::bail!("Call to {:?} failed", request_copy);
|
Ok(()) => break,
|
||||||
|
Err(TrySendError::Full(returned)) => {
|
||||||
|
pending = Some(returned);
|
||||||
|
if !sleep_until_deadline(deadline) {
|
||||||
|
anyhow::bail!("Timed out sending bus request: {request_copy:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(TrySendError::Closed(_)) => {
|
||||||
|
anyhow::bail!("Bus closed while sending request: {request_copy:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match once_rx.try_recv() {
|
||||||
|
Ok(reply) => return Ok(reply),
|
||||||
|
Err(TryRecvError::Empty) => {
|
||||||
|
if !sleep_until_deadline(deadline) {
|
||||||
|
anyhow::bail!("Timed out waiting for bus reply: {request_copy:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(TryRecvError::Closed) => {
|
||||||
|
anyhow::bail!("Bus reply channel closed for request: {request_copy:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +123,7 @@ pub(super) fn probe_specs(
|
|||||||
requests: probe_requests,
|
requests: probe_requests,
|
||||||
max_age_ms: TOPOLOGY_PROBE_MAX_AGE_MS,
|
max_age_ms: TOPOLOGY_PROBE_MAX_AGE_MS,
|
||||||
},
|
},
|
||||||
|
timeout.saturating_add(BUS_CALL_TIMEOUT_MARGIN),
|
||||||
)
|
)
|
||||||
.map_err(|err| anyhow::anyhow!("unable to query shared probe manager: {err}"))?
|
.map_err(|err| anyhow::anyhow!("unable to query shared probe manager: {err}"))?
|
||||||
.responses
|
.responses
|
||||||
|
|||||||
Reference in new issue
Block a user