created stop signal for breaking out of coroutine loop

This commit is contained in:
Maxime Van Hees authored and Lee Smet committed 2024-08-26 13:18:25 +02:00
1 parent f50cc7ca56
commit 30d2da280d
5 files changed
+129 -50

No files matched your search

+1
View File
@@ -3063,6 +3063,7 @@ dependencies = [
"dioxus-free-icons",
"dioxus-logger",
"dioxus-sortable",
"futures-util",
"human_bytes",
"manganis",
"mycelium",
+1
View File
@@ -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"
+48 -3
View File
@@ -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 {
+65 -46
View File
@@ -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
View File
@@ -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);