Skip to content

Commit

Permalink
add: RSS feed for unreachable nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
0xB10C committed Feb 21, 2024
1 parent 74ece17 commit 9d33b91
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 12 deletions.
41 changes: 29 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,13 @@ async fn main() -> Result<(), MainError> {
.and(rss::with_rss_base_url(config.rss_base_url.clone()))
.and_then(rss::lagging_nodes_response);

let unreachable_nodes_rss = warp::get()
.and(warp::path!("rss" / u32 / "unreachable.xml"))
.and(api::with_caches(caches.clone()))
.and(api::with_networks(network_infos.clone()))
.and(rss::with_rss_base_url(config.rss_base_url.clone()))
.and_then(rss::unreachable_nodes_response);

let networks_json = warp::get()
.and(warp::path!("api" / "networks.json"))
.and(api::with_networks(network_infos))
Expand Down Expand Up @@ -592,6 +599,7 @@ async fn main() -> Result<(), MainError> {
.or(change_sse)
.or(forks_rss)
.or(lagging_nodes_rss)
.or(unreachable_nodes_rss)
.or(invalid_blocks_rss);

warp::serve(routes).run(config.address).await;
Expand Down Expand Up @@ -636,14 +644,14 @@ mod tests {
use crate::node::NodeInfo;

async fn get_test_node_reachable(caches: &Caches, net_id: u32, node_id: u32) -> bool {
let locked_caches = caches.lock().await;
locked_caches
.get(&net_id)
.expect("network id should be there")
.node_data
.get(&node_id)
.expect("node id should be there")
.reachable
let locked_caches = caches.lock().await;
locked_caches
.get(&net_id)
.expect("network id should be there")
.node_data
.get(&node_id)
.expect("node id should be there")
.reachable
}

#[tokio::test]
Expand Down Expand Up @@ -672,12 +680,21 @@ mod tests {
},
);
}
assert_eq!(get_test_node_reachable(&caches, network_id, node.id).await, true);
assert_eq!(
get_test_node_reachable(&caches, network_id, node.id).await,
true
);

node_reachable(&caches, network_id, node.id, false).await;
assert_eq!(get_test_node_reachable(&caches, network_id, node.id).await, false);

assert_eq!(
get_test_node_reachable(&caches, network_id, node.id).await,
false
);

node_reachable(&caches, network_id, node.id, true).await;
assert_eq!(get_test_node_reachable(&caches, network_id, node.id).await, true);
assert_eq!(
get_test_node_reachable(&caches, network_id, node.id).await,
true
);
}
}
62 changes: 62 additions & 0 deletions src/rss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ impl Item {
guid: format!("lagging-node-{}-on-{}", node.name, height),
}
}

pub fn unreachable_node_item(node: &NodeDataJson) -> Item {
Item {
title: format!("Node '{}' (id={}) is unreachable", node.name, node.id),
description: format!(
"The RPC server of this node is not reachable. The node might be offline or there might be other networking issues. The nodes tip data was last updated at timestamp {} (zero indicates never).",
node.last_changed_timestamp,
),
guid: format!("unreachable-node-{}-last-{}", node.id, node.last_changed_timestamp),
}
}
}

pub async fn lagging_nodes_response(
Expand Down Expand Up @@ -323,6 +334,57 @@ pub async fn invalid_blocks_response(
}
}

pub async fn unreachable_nodes_response(
network_id: u32,
caches: Caches,
network_infos: Vec<NetworkJson>,
base_url: String,
) -> Result<impl warp::Reply, Infallible> {
let caches_locked = caches.lock().await;

match caches_locked.get(&network_id) {
Some(cache) => {
let mut network_name = "";
if let Some(network) = network_infos
.iter()
.filter(|net| net.id == network_id)
.collect::<Vec<&NetworkJson>>()
.first()
{
network_name = &network.name;
}

let unreachable_node_items: Vec<Item> = cache
.node_data
.values()
.filter(|node| !node.reachable)
.map(|node| Item::unreachable_node_item(node))
.collect();
let feed = Feed {
channel: Channel {
title: format!("Unreachable nodes - {}", network_name),
description: format!(
"Nodes on the {} network that can't be reached",
network_name
),
link: format!(
"{}?network={}?src=unreachable-nodes",
base_url.clone(),
network_id
),
href: format!("{}/rss/{}/unreachable.xml", base_url, network_id),
items: unreachable_node_items,
},
};

return Ok(Response::builder()
.header("content-type", "application/rss+xml")
.body(feed.to_string()));
}
None => Ok(Ok(response_unknown_network(network_infos))),
}
}

pub fn response_unknown_network(network_infos: Vec<NetworkJson>) -> Response<String> {
let avaliable_networks = network_infos
.iter()
Expand Down
4 changes: 4 additions & 0 deletions www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ <h3>Network: <span id="network_info_name"></span></h3>
<img src="static/img/rss-feed-white.svg" height=18>
<a target="_blank" id="rss_lagging_nodes">Lagging nodes</a>
</span>
<span>
<img src="static/img/rss-feed-white.svg" height=18>
<a target="_blank" id="rss_unreachable_nodes">Unreachable nodes</a>
</span>
</p>
<br>
<details style="color: var(--text-color);" open>
Expand Down
2 changes: 2 additions & 0 deletions www/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const connectionStatus = d3.select("#connection-status")
const rssRecentForks = d3.select("#rss_recent_forks")
const rssInvalidBlocks = d3.select("#rss_invalid_blocks")
const rssLaggingNodes = d3.select("#rss_lagging_nodes")
const rssUnreachableNodes = d3.select("#rss_unreachable_nodes")

const SEARCH_PARAM_NETWORK = "network"

Expand Down Expand Up @@ -58,6 +59,7 @@ function update_network() {
rssRecentForks.node().href = `rss/${current_network.id}/forks.xml`
rssInvalidBlocks.node().href = `rss/${current_network.id}/invalid.xml`
rssLaggingNodes.node().href = `rss/${current_network.id}/lagging.xml`
rssUnreachableNodes.node().href = `rss/${current_network.id}/unreachable.xml`
}

function set_initial_network() {
Expand Down

0 comments on commit 9d33b91

Please sign in to comment.