mirror of
https://github.com/threefoldtech/mycelium.git
synced 2026-10-23 22:12:20 +00:00
created stop signal for breaking out of coroutine loop
This commit is contained in:
1 parent
f50cc7ca56
commit
30d2da280d
5 files changed
+129
-50
No files matched your search
Generated
+1
@@ -3063,6 +3063,7 @@ dependencies = [
|
||||
"dioxus-free-icons",
|
||||
"dioxus-logger",
|
||||
"dioxus-sortable",
|
||||
"futures-util",
|
||||
"human_bytes",
|
||||
"manganis",
|
||||
"mycelium",
|
||||
|
||||
@@ -27,3 +27,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"
|
||||
futures-util = "0.3.30"
|
||||
@@ -336,10 +336,25 @@ h2 {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.graph-container {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.graph-title {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--secondary-color);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.expanded-content {
|
||||
padding: 1rem;
|
||||
padding: 2rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
/* justify-content: space-between; */
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -348,13 +363,43 @@ h2 {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Style for both Tx and Rx charts */
|
||||
.expanded-content svg {
|
||||
margin-bottom: 2rem;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Style for chart lines */
|
||||
.expanded-content path {
|
||||
stroke-width: 3;
|
||||
}
|
||||
|
||||
/* Style for Tx bytes chart */
|
||||
.graph-container:nth-child(1) path {
|
||||
stroke: #3498db;
|
||||
}
|
||||
|
||||
/* Style for Rx bytes chart */
|
||||
.graph-container:nth-child(2) path {
|
||||
stroke: #2ecc71;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
border-radius: 4px;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
background-color: #2980b9;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use crate::get_sort_indicator;
|
||||
use crate::{api, PeerSignalMapping, SearchState, ServerAddress, SortDirection};
|
||||
use crate::{
|
||||
api, PeerSignalMapping, SearchState, ServerAddress, SortDirection, StopFetchingPeerSignal,
|
||||
};
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_charts::LineChart;
|
||||
use futures_util::StreamExt;
|
||||
use human_bytes::human_bytes;
|
||||
use mycelium::peer_manager::{PeerStats, PeerType};
|
||||
use std::{
|
||||
@@ -18,33 +21,43 @@ pub fn Peers() -> Element {
|
||||
let error = use_signal(|| None::<String>);
|
||||
// Mapping between peer and their corresponding signal
|
||||
let peer_signal_map = use_context::<Signal<PeerSignalMapping>>();
|
||||
// Set to false when user is on Peers page. Changes to true when visiting any other page of the
|
||||
// application
|
||||
let stop_fetching_signal = use_context::<Signal<StopFetchingPeerSignal>>().read().0;
|
||||
println!("current value stop_fetching_signal: {stop_fetching_signal}");
|
||||
|
||||
let _: Coroutine<()> = use_coroutine(|_rx: UnboundedReceiver<_>| {
|
||||
let _: Coroutine<()> = use_coroutine(|_rx| {
|
||||
async move {
|
||||
to_owned![server_addr, error, peer_signal_map];
|
||||
loop {
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(REFRESH_RATE_MS)).await;
|
||||
match api::get_peers(server_addr).await {
|
||||
Ok(fetched_peers) => {
|
||||
let mut peer_signal_map = peer_signal_map.write();
|
||||
// populate the peer_signal_map
|
||||
for peer in fetched_peers {
|
||||
peer_signal_map
|
||||
.0
|
||||
.entry(peer.endpoint)
|
||||
.or_insert(use_signal(|| peer.clone())) // ret. mut ref to signal
|
||||
.set(peer); // set signal (each time, so with new rx/tx data incl.)
|
||||
}
|
||||
if !stop_fetching_signal {
|
||||
println!("Starting loop");
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(REFRESH_RATE_MS)).await;
|
||||
match api::get_peers(server_addr).await {
|
||||
Ok(fetched_peers) => {
|
||||
let mut peer_signal_map = peer_signal_map.write();
|
||||
// populate the peer_signal_map
|
||||
for peer in fetched_peers {
|
||||
peer_signal_map
|
||||
.0
|
||||
.entry(peer.endpoint)
|
||||
.or_insert(use_signal(|| peer.clone()))
|
||||
.set(peer); // set signal (each time, so with new rx/tx data incl.)
|
||||
}
|
||||
|
||||
error.set(None);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error fetching peers: {}", e);
|
||||
error.set(Some(format!(
|
||||
"An error has occurred while fetching peers: {}",
|
||||
e
|
||||
)))
|
||||
error.set(None);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error fetching peers: {}", e);
|
||||
error.set(Some(format!(
|
||||
"An error has occurred while fetching peers: {}",
|
||||
e
|
||||
)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("breaking out of loop");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,13 +67,12 @@ pub fn Peers() -> Element {
|
||||
if let Some(err) = error.read().as_ref() {
|
||||
div { class: "error-message", "{err}" }
|
||||
} else {
|
||||
PeersTable { } // no arg reuiqred --> we use (global shared) context now
|
||||
PeersTable { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
// fn PeersTable(peer_signal_map: HashMap<Endpoint, Signal<PeerStats>>) -> Element {
|
||||
fn PeersTable() -> Element {
|
||||
let mut current_page = use_signal(|| 0);
|
||||
let items_per_page = 20;
|
||||
@@ -355,29 +367,36 @@ fn ExpandedPeerRow(peer: Signal<PeerStats>, on_close: EventHandler<()>) -> Eleme
|
||||
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_data.read().to_vec()],
|
||||
labels: labels.clone(),
|
||||
series_labels: vec!["Tx Bytes/s".into()],
|
||||
div { class: "graph-container",
|
||||
// Tx chart
|
||||
div { class: "graph-title", "Tx Bytes/s" }
|
||||
LineChart {
|
||||
show_grid: false,
|
||||
show_grid_ticks: true,
|
||||
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_data.read().to_vec()],
|
||||
labels: labels.clone(),
|
||||
series_labels: vec!["Tx Bytes/s".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_data.read().clone()],
|
||||
labels: labels.clone(),
|
||||
series_labels: vec!["Rx Bytes/s".into()],
|
||||
div { class: "graph-container",
|
||||
// Rx chart
|
||||
div { class: "graph-title", "Rx Bytes/s" }
|
||||
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_data.read().clone()],
|
||||
labels: labels.clone(),
|
||||
series_labels: vec!["Rx Bytes/s".into()],
|
||||
}
|
||||
}
|
||||
button { class: "close-button",
|
||||
onclick: move |_| on_close.call(()),
|
||||
|
||||
+14
-1
@@ -34,9 +34,17 @@ fn App() -> Element {
|
||||
HashMap::<Endpoint, Signal<PeerStats>>::new(),
|
||||
))
|
||||
});
|
||||
use_context_provider(|| Signal::new(StopFetchingPeerSignal(false)));
|
||||
|
||||
rsx! {
|
||||
Router::<Route> {}
|
||||
Router::<Route> {
|
||||
config: || {
|
||||
RouterConfig::default().on_update(|state| {
|
||||
use_context::<Signal<StopFetchingPeerSignal>>().write().0 = state.current() != Route::Peers {};
|
||||
(state.current() == Route::Peers {}).then_some(NavigationTarget::Internal(Route::Peers {}))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +69,11 @@ struct SearchState {
|
||||
column: String,
|
||||
}
|
||||
|
||||
// This signal is used to stop the loop that keeps fetching information about the peers when
|
||||
// looking at the peers table, e.g. when the user goes back to Home or Routes page.
|
||||
#[derive(Clone, PartialEq)]
|
||||
struct StopFetchingPeerSignal(bool);
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
struct ServerAddress(SocketAddr);
|
||||
|
||||
|
||||
Reference in new issue
Block a user