add pings, reconnects, and a next reconnect status in settings menu
This commit is contained in:
parent
db78b2a4d3
commit
8f31087662
4 changed files with 73 additions and 13 deletions
12
src/main.rs
12
src/main.rs
|
@ -93,13 +93,13 @@ enum HootStatus {
|
|||
fn update_app(app: &mut Hoot, ctx: &egui::Context) {
|
||||
#[cfg(feature = "profiling")]
|
||||
puffin::profile_function!();
|
||||
let ctx = ctx.clone();
|
||||
let wake_up = move || {
|
||||
ctx.request_repaint();
|
||||
};
|
||||
|
||||
if app.status == HootStatus::Initalizing {
|
||||
info!("Initalizing Hoot...");
|
||||
let ctx = ctx.clone();
|
||||
let wake_up = move || {
|
||||
ctx.request_repaint();
|
||||
};
|
||||
match app.account_manager.load_keys() {
|
||||
Ok(..) => {}
|
||||
Err(v) => error!("something went wrong trying to load keys: {}", v),
|
||||
|
@ -109,7 +109,7 @@ fn update_app(app: &mut Hoot, ctx: &egui::Context) {
|
|||
.add_url("wss://relay.damus.io".to_string(), wake_up.clone());
|
||||
let _ = app
|
||||
.relays
|
||||
.add_url("wss://relay-dev.hoot.sh".to_string(), wake_up);
|
||||
.add_url("wss://relay-dev.hoot.sh".to_string(), wake_up.clone());
|
||||
|
||||
if app.account_manager.loaded_keys.len() > 0 {
|
||||
let mut pks: Vec<nostr::PublicKey> = Vec::new();
|
||||
|
@ -129,6 +129,8 @@ fn update_app(app: &mut Hoot, ctx: &egui::Context) {
|
|||
info!("Hoot Ready");
|
||||
}
|
||||
|
||||
app.relays.keepalive(wake_up);
|
||||
|
||||
let new_val = app.relays.try_recv();
|
||||
if new_val.is_some() {
|
||||
info!("{:?}", new_val.clone());
|
||||
|
|
|
@ -3,7 +3,7 @@ use ewebsock::{WsEvent, WsMessage};
|
|||
use tracing::{debug, error, info};
|
||||
|
||||
mod pool;
|
||||
pub use pool::RelayPool;
|
||||
pub use pool::{RelayPool, RELAY_RECONNECT_SECONDS};
|
||||
|
||||
mod message;
|
||||
pub use message::{ClientMessage, RelayMessage};
|
||||
|
@ -42,11 +42,20 @@ impl Relay {
|
|||
status: RelayStatus::Connecting,
|
||||
};
|
||||
|
||||
relay.ping();
|
||||
|
||||
relay
|
||||
}
|
||||
|
||||
// TODO: investigate whether this can cause a message to be dropped due to the writer being
|
||||
// overwritten
|
||||
pub fn reconnect(&mut self, wake_up: impl Fn() + Send + Sync + 'static) {
|
||||
let (sender, reciever) =
|
||||
ewebsock::connect_with_wakeup(self.url.clone(), ewebsock::Options::default(), wake_up)
|
||||
.unwrap();
|
||||
|
||||
self.reader = reciever;
|
||||
self.writer = sender;
|
||||
}
|
||||
|
||||
pub fn send(&mut self, message: WsMessage) -> Result<()> {
|
||||
if self.status != RelayStatus::Connected {
|
||||
return Err(Error::RelayNotConnected);
|
||||
|
@ -67,6 +76,7 @@ impl Relay {
|
|||
}
|
||||
Error(ref error) => {
|
||||
error!("error in websocket connection to {}: {}", self.url, error);
|
||||
self.status = RelayStatus::Disconnected;
|
||||
}
|
||||
Closed => {
|
||||
info!("connection to {} closed", self.url);
|
||||
|
|
|
@ -4,11 +4,16 @@ use crate::relay::Subscription;
|
|||
use crate::relay::{Relay, RelayStatus};
|
||||
use ewebsock::{WsEvent, WsMessage};
|
||||
use std::collections::HashMap;
|
||||
use tracing::error;
|
||||
use tracing::{error, debug};
|
||||
use std::time::{Instant, Duration};
|
||||
|
||||
pub const RELAY_RECONNECT_SECONDS: u64 = 5;
|
||||
|
||||
pub struct RelayPool {
|
||||
pub relays: HashMap<String, Relay>,
|
||||
pub subscriptions: HashMap<String, Subscription>,
|
||||
last_reconnect_attempt: Instant,
|
||||
last_ping: Instant,
|
||||
}
|
||||
|
||||
impl RelayPool {
|
||||
|
@ -16,6 +21,37 @@ impl RelayPool {
|
|||
Self {
|
||||
relays: HashMap::new(),
|
||||
subscriptions: HashMap::new(),
|
||||
last_reconnect_attempt: Instant::now(),
|
||||
last_ping: Instant::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_last_reconnect_attempt(&mut self) -> Instant {
|
||||
return self.last_reconnect_attempt;
|
||||
}
|
||||
|
||||
pub fn keepalive(&mut self, wake_up: impl Fn() + Send + Sync + Clone + 'static) {
|
||||
let now = Instant::now();
|
||||
|
||||
// Check disconnected relays
|
||||
if now.duration_since(self.last_reconnect_attempt) >= Duration::from_secs(RELAY_RECONNECT_SECONDS) {
|
||||
for relay in self.relays.values_mut() {
|
||||
if relay.status != RelayStatus::Connected {
|
||||
relay.status = RelayStatus::Connecting;
|
||||
relay.reconnect(wake_up.clone());
|
||||
}
|
||||
}
|
||||
self.last_reconnect_attempt = now;
|
||||
}
|
||||
|
||||
// Ping connected relays
|
||||
if now.duration_since(self.last_ping) >= Duration::from_secs(30) {
|
||||
for relay in self.relays.values_mut() {
|
||||
if relay.status == RelayStatus::Connected {
|
||||
relay.ping();
|
||||
}
|
||||
}
|
||||
self.last_ping = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,11 +89,12 @@ impl RelayPool {
|
|||
|
||||
pub fn try_recv(&mut self) -> Option<String> {
|
||||
for relay in self.relays.values_mut() {
|
||||
let relay_url = relay.url.clone();
|
||||
if let Some(event) = relay.try_recv() {
|
||||
use WsEvent::*;
|
||||
match event {
|
||||
Message(message) => {
|
||||
return self.handle_message(message);
|
||||
return self.handle_message(relay_url, message);
|
||||
}
|
||||
Opened => {
|
||||
for sub in self.subscriptions.clone() {
|
||||
|
@ -91,7 +128,7 @@ impl RelayPool {
|
|||
None
|
||||
}
|
||||
|
||||
fn handle_message(&mut self, message: WsMessage) -> Option<String> {
|
||||
fn handle_message(&mut self, url: String, message: WsMessage) -> Option<String> {
|
||||
use WsMessage::*;
|
||||
match message {
|
||||
Text(txt) => {
|
||||
|
@ -100,13 +137,16 @@ impl RelayPool {
|
|||
Binary(..) => {
|
||||
error!("recived binary messsage, your move semisol");
|
||||
}
|
||||
Ping(d) => {
|
||||
let pong_msg = WsMessage::Pong(d);
|
||||
Ping(m) => {
|
||||
let pong_msg = WsMessage::Pong(m);
|
||||
match self.send(pong_msg) {
|
||||
Ok(_) => {}
|
||||
Err(e) => error!("error when sending websocket message {:?}", e),
|
||||
}
|
||||
}
|
||||
Pong(m) => {
|
||||
debug!("pong recieved from {} after approx {} seconds", &url, self.last_ping.elapsed().as_secs());
|
||||
}
|
||||
_ => {
|
||||
// who cares
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ impl SettingsScreen {
|
|||
ui.label("Your Relays:");
|
||||
ui.vertical(|ui| {
|
||||
let mut relay_to_remove: Option<String> = None;
|
||||
let last_ping = app.relays.get_last_reconnect_attempt();
|
||||
for (url, relay) in app.relays.relays.iter() {
|
||||
ui.horizontal(|ui| {
|
||||
use crate::relay::RelayStatus::*;
|
||||
|
@ -103,6 +104,13 @@ impl SettingsScreen {
|
|||
painter.circle_filled(c, r, conn_fill);
|
||||
|
||||
ui.label(url);
|
||||
// TODO: this only updates when next frame is rendered, which can be more than
|
||||
// a few seconds between renders. Make it so it updates every second.
|
||||
if relay.status == crate::relay::RelayStatus::Disconnected {
|
||||
let next_ping = crate::relay::RELAY_RECONNECT_SECONDS - last_ping.elapsed().as_secs();
|
||||
|
||||
ui.label(format!("(Attempting reconnect in {} seconds)", next_ping));
|
||||
}
|
||||
if ui.button("Remove Relay").clicked() {
|
||||
relay_to_remove = Some(url.to_string());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue