Degrade gracefully when Iroh modules fail

This commit is contained in:
Eric Wendland 2026-07-18 16:00:13 +02:00
commit 7d67da9dfe
4 changed files with 193 additions and 55 deletions

View file

@ -5566,7 +5566,7 @@ pub fn handle_request(
iroh_relay_mode: node.iroh_status.relay_mode.clone(),
iroh_local_discovery: node.iroh_status.local_discovery,
iroh: node.iroh_status.note.clone(),
native_backends: native_backend_statuses(),
native_backends: native_backend_statuses(node)?,
}))
}
ControlRequest::NodeId => Ok(ControlResponse::NodeId(NodeIdResponse {
@ -7579,10 +7579,46 @@ pub fn handle_request(
}
}
fn native_backend_statuses() -> Vec<NativeBackendStatus> {
geth_iroh::native_iroh_libraries()
fn native_backend_statuses(node: &LocalNode) -> Result<Vec<NativeBackendStatus>, NodeError> {
let endpoint_ready = node
.iroh_endpoint
.lock()
.map_err(|_| NodeError::RuntimeLockPoisoned)?
.is_some();
let blobs_ready = node
.iroh_blob_store
.lock()
.map_err(|_| NodeError::RuntimeLockPoisoned)?
.is_some();
let docs_ready = node
.iroh_docs
.lock()
.map_err(|_| NodeError::RuntimeLockPoisoned)?
.is_some();
let gossip_ready = node
.iroh_gossip
.lock()
.map_err(|_| NodeError::RuntimeLockPoisoned)?
.is_some();
Ok(geth_iroh::native_iroh_libraries()
.into_iter()
.map(|library| {
let runtime_ready = match library.module.as_str() {
"cas" => endpoint_ready && blobs_ready,
"kv" => endpoint_ready && docs_ready,
"pubsub" => endpoint_ready && gossip_ready,
_ => endpoint_ready,
};
if !runtime_ready {
return NativeBackendStatus {
module: library.module,
current_backend: "unavailable".to_owned(),
target_crate: library.crate_name,
target_version: library.crate_version,
status: "unavailable".to_owned(),
blocker: node.iroh_status.note.clone(),
};
}
let (status, blocker) = match library.module.as_str() {
"cas" => (
"wired",
@ -7623,7 +7659,7 @@ fn native_backend_statuses() -> Vec<NativeBackendStatus> {
blocker,
}
})
.collect()
.collect())
}
fn stored_resource_to_descriptor(stored: StoredResource) -> Result<ResourceDescriptor, NodeError> {
@ -11151,6 +11187,21 @@ mod tests {
);
}
#[test]
fn native_backend_status_reflects_runtime_availability() {
let dir = tempfile::tempdir().expect("tempdir");
let node = init_node(&GethPaths::from_home(dir.path())).expect("init node");
let statuses = native_backend_statuses(&node).expect("backend status");
assert!(!statuses.is_empty());
assert!(statuses.iter().all(|status| status.status == "unavailable"));
assert!(
statuses
.iter()
.all(|status| status.current_backend == "unavailable")
);
}
#[derive(Debug, PartialEq, Eq)]
enum RemoteGuardKind {
Capability,