tx and rx graph (to fix: circular dependency bug)

This commit is contained in:
Maxime Van Hees authored and Lee Smet committed 2024-08-26 13:18:25 +02:00
1 parent 2886054e17
commit dfacd9645e
3 files changed
+122 -53

No files matched your search

+11
View File
@@ -1015,6 +1015,16 @@ dependencies = [
"dioxus-signals",
]
[[package]]
name = "dioxus-charts"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53ed46a5bf524783e4a3496a8ab38fbe129590d8a3e436c1297c14f96c559a1a"
dependencies = [
"dioxus 0.5.1",
"log",
]
[[package]]
name = "dioxus-cli-config"
version = "0.5.0"
@@ -3049,6 +3059,7 @@ name = "mycelium-ui"
version = "0.1.0"
dependencies = [
"dioxus 0.5.1",
"dioxus-charts",
"dioxus-free-icons",
"dioxus-logger",
"dioxus-sortable",
+1
View File
@@ -26,3 +26,4 @@ dioxus-free-icons = { version = "0.8.6", features = [
] }
human_bytes = { version = "0.4.3", features = ["fast"] }
tokio = "1.39.2"
dioxus-charts = "0.2.0"
+110 -53
View File
@@ -1,57 +1,30 @@
use crate::get_sort_indicator;
use crate::{api, SearchState, ServerAddress, SortDirection};
use dioxus::prelude::*;
use dioxus_charts::LineChart;
use human_bytes::human_bytes;
use mycelium::peer_manager::PeerType;
use std::{cmp::Ordering, collections::HashSet};
use mycelium::peer_manager::{PeerStats, PeerType};
use std::{
cmp::Ordering,
collections::{HashSet, VecDeque},
};
#[component]
fn ExpandedPeerRow(peer: mycelium::peer_manager::PeerStats, on_close: EventHandler<()>) -> Element {
rsx! {
tr { class: "expanded-row",
td { colspan: "7",
div { class: "expanded-content",
p { "Tx bytes: {human_bytes(peer.tx_bytes as f64)}" }
p { "Rx bytes: {human_bytes(peer.rx_bytes as f64)}" }
button { class: "close-button",
onclick: move |_| on_close.call(()),
"Close"
}
}
}
}
}
}
const REFRESH_RATE_MS: u64 = 500;
#[component]
pub fn Peers() -> Element {
let server_addr = use_context::<Signal<ServerAddress>>().read().0;
let mut peers = use_signal(|| Vec::new());
let peers = use_signal(Vec::new);
let mut error = use_signal(|| None::<String>);
let _initial_fetch = use_resource(move || async move {
match api::get_peers(server_addr).await {
Ok(fetched_peers) => {
peers.set(fetched_peers);
error.set(None);
}
Err(e) => {
eprintln!("Error fetching peers: {}", e);
error.set(Some(format!(
"An error has occurred while fetching peers: {}",
e
)));
}
}
});
let _: Coroutine<()> = use_coroutine(|_rx: UnboundedReceiver<_>| {
to_owned![peers, server_addr];
async move {
loop {
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
tokio::time::sleep(tokio::time::Duration::from_millis(REFRESH_RATE_MS)).await;
match api::get_peers(server_addr).await {
Ok(fetched_peers) => {
println!("fetching them peers bro");
peers.set(fetched_peers);
error.set(None);
}
@@ -71,21 +44,18 @@ pub fn Peers() -> Element {
if let Some(err) = error.read().as_ref() {
div { class: "error-message", "{err}" }
} else {
{PeersTable(peers)}
PeersTable { peers: peers }
}
}
}
#[derive(Clone, PartialEq)]
// Rows that have been expaneded out to show additional information
struct ExpandedRows(HashSet<String>);
fn PeersTable(peers: Signal<Vec<mycelium::peer_manager::PeerStats>>) -> Element {
#[component]
fn PeersTable(peers: Signal<Vec<PeerStats>>) -> Element {
let mut current_page = use_signal(|| 0);
let items_per_page = 20;
let mut sort_column = use_signal(|| "Protocol".to_string());
let mut sort_direction = use_signal(|| SortDirection::Ascending);
let peers_len = peers.len();
let peers_len = peers.read().len();
let mut change_page = move |delta: i32| {
let cur_page = *current_page.read() as i32;
@@ -98,12 +68,13 @@ fn PeersTable(peers: Signal<Vec<mycelium::peer_manager::PeerStats>>) -> Element
let mut expanded_rows = use_signal(|| ExpandedRows(HashSet::new()));
let mut toggle_row_expansion = move |peer_endpoint: String| {
let mut expanded = expanded_rows.write();
if expanded.0.contains(&peer_endpoint) {
expanded.0.remove(&peer_endpoint);
} else {
expanded.0.insert(peer_endpoint);
}
expanded_rows.with_mut(|rows| {
if rows.0.contains(&peer_endpoint) {
rows.0.remove(&peer_endpoint);
} else {
rows.0.insert(peer_endpoint);
}
});
};
// Sorting
@@ -172,7 +143,7 @@ fn PeersTable(peers: Signal<Vec<mycelium::peer_manager::PeerStats>>) -> Element
_ => false,
})
.cloned()
.collect::<Vec<mycelium::peer_manager::PeerStats>>()
.collect::<Vec<PeerStats>>()
});
let peers_len = filtered_peers.read().len();
@@ -250,15 +221,18 @@ fn PeersTable(peers: Signal<Vec<mycelium::peer_manager::PeerStats>>) -> Element
}
{
let is_expanded = expanded_rows.read().0.contains(&peer.endpoint.to_string());
let mut peer_signal = use_signal(|| peer.clone());
// Update the peer_signal when the peers are fetched
peer_signal.set(peer.clone());
if is_expanded {
rsx! {
ExpandedPeerRow {
peer: peer.clone(),
peer: peer_signal,
on_close: move |_| toggle_row_expansion(peer.endpoint.to_string())
}
}
} else {
rsx! { }
rsx! {}
}
}
}
@@ -282,6 +256,89 @@ fn PeersTable(peers: Signal<Vec<mycelium::peer_manager::PeerStats>>) -> Element
}
}
#[component]
fn ExpandedPeerRow(
peer: Signal<mycelium::peer_manager::PeerStats>,
on_close: EventHandler<()>,
) -> Element {
let tx_data_deque: VecDeque<f32> = VecDeque::with_capacity(20);
let rx_data_deque: VecDeque<f32> = VecDeque::with_capacity(20);
let mut tx_chart_data = use_signal(|| tx_data_deque);
let mut rx_chart_data = use_signal(|| rx_data_deque);
let mut prev_tx = use_signal(|| 0f64);
let mut prev_rx = use_signal(|| 0f64);
use_effect(move || {
println!("yeah...");
let current_tx = peer.read().tx_bytes as f64;
let current_rx = peer.read().rx_bytes as f64;
// Calculate data flow per second
let tx_per_second = (current_tx - *prev_tx.read()) as u64 * (1000 / REFRESH_RATE_MS);
let rx_per_second = (current_rx - *prev_rx.read()) as u64 * (1000 / REFRESH_RATE_MS);
tx_chart_data.with_mut(|tx_data| {
if tx_data.len() >= 20 {
tx_data.pop_front();
}
tx_data.push_back(tx_per_second as f32);
});
rx_chart_data.with_mut(|rx_data| {
if rx_data.len() >= 20 {
rx_data.pop_front();
}
rx_data.push_back(rx_per_second as f32);
});
});
// Causes a circular dependency which causes the program to become unresponsive
// prev_tx.set(peer.read().tx_bytes as f64);
// prev_rx.set(peer.read().rx_bytes as f64);
rsx! {
tr { class: "expanded-row",
td { colspan: "7",
div { class: "expanded-content",
// Tx chart
LineChart {
show_grid: false,
padding_top: 80,
padding_left: 100,
padding_right: 80,
padding_bottom: 80,
label_interpolation: (|v| human_bytes(v as f64).to_string()) as fn(f32)-> String,
series: vec![tx_chart_data.read().iter().cloned().collect::<Vec<f32>>()],
labels: (0..tx_chart_data.read().len()).map(|i| i.to_string()).collect::<Vec<String>>(),
series_labels: vec!["Tx Bytes".into()],
}
// Rx chart
LineChart {
show_grid: false,
padding_top: 80,
padding_left: 100,
padding_right: 80,
padding_bottom: 80,
label_interpolation: (|v| human_bytes(v as f64).to_string()) as fn(f32)-> String,
series: vec![rx_chart_data.read().iter().cloned().collect::<Vec<f32>>()],
labels: (0..rx_chart_data.read().len()).map(|i| i.to_string()).collect::<Vec<String>>(),
series_labels: vec!["Rx Bytes".into()],
}
// p { "Tx bytes: {human_bytes(peer.read().tx_bytes as f64)}" }
// p { "Rx bytes: {human_bytes(peer.read().rx_bytes as f64)}" }
button { class: "close-button",
onclick: move |_| on_close.call(()),
"Close"
}
}
}
}
}
}
#[derive(Clone, PartialEq)]
// Rows that have been expaneded out to show additional information
struct ExpandedRows(HashSet<String>);
fn sort_peers(
peers: &mut [mycelium::peer_manager::PeerStats],
column: &str,