mirror of
https://github.com/damus-io/notedeck.git
synced 2024-09-19 21:26:33 +00:00
net: geometric backoff connection retries on disconnects
This commit is contained in:
parent
6dee4bbe7d
commit
f46797ea10
@ -63,6 +63,14 @@ impl Relay {
|
||||
self.sender.send(txt);
|
||||
}
|
||||
|
||||
pub fn connect(&mut self, wakeup: impl Fn() + Send + Sync + 'static) -> Result<()> {
|
||||
let (sender, receiver) = ewebsock::connect_with_wakeup(&self.url, wakeup)?;
|
||||
self.status = RelayStatus::Connecting;
|
||||
self.sender = sender;
|
||||
self.receiver = receiver;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn ping(&mut self) {
|
||||
let msg = WsMessage::Ping(vec![]);
|
||||
self.sender.send(msg);
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::relay::message::RelayEvent;
|
||||
use crate::relay::Relay;
|
||||
use crate::relay::{Relay, RelayStatus};
|
||||
use crate::{ClientMessage, Result};
|
||||
|
||||
use std::time::{Duration, Instant};
|
||||
@ -21,6 +21,8 @@ pub struct PoolEvent<'a> {
|
||||
pub struct PoolRelay {
|
||||
pub relay: Relay,
|
||||
pub last_ping: Instant,
|
||||
pub last_connect_attempt: Instant,
|
||||
pub retry_connect_after: Duration,
|
||||
}
|
||||
|
||||
impl PoolRelay {
|
||||
@ -28,8 +30,14 @@ impl PoolRelay {
|
||||
PoolRelay {
|
||||
relay: relay,
|
||||
last_ping: Instant::now(),
|
||||
last_connect_attempt: Instant::now(),
|
||||
retry_connect_after: Self::initial_reconnect_duration(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initial_reconnect_duration() -> Duration {
|
||||
Duration::from_secs(2)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RelayPool {
|
||||
@ -68,14 +76,43 @@ impl RelayPool {
|
||||
|
||||
/// Keep relay connectiongs alive by pinging relays that haven't been
|
||||
/// pinged in awhile. Adjust ping rate with [`ping_rate`].
|
||||
pub fn keepalive_ping(&mut self) {
|
||||
pub fn keepalive_ping(&mut self, wakeup: impl Fn() + Send + Sync + Clone + 'static) {
|
||||
for relay in &mut self.relays {
|
||||
let now = std::time::Instant::now();
|
||||
let should_ping = now - relay.last_ping > self.ping_rate;
|
||||
if should_ping {
|
||||
debug!("pinging {}", relay.relay.url);
|
||||
relay.relay.ping();
|
||||
relay.last_ping = Instant::now();
|
||||
|
||||
match relay.relay.status {
|
||||
RelayStatus::Disconnected => {
|
||||
let reconnect_at = relay.last_connect_attempt + relay.retry_connect_after;
|
||||
if now > reconnect_at {
|
||||
relay.last_connect_attempt = now;
|
||||
let next_duration = Duration::from_millis(
|
||||
((relay.retry_connect_after.as_millis() as f64) * 1.5) as u64,
|
||||
);
|
||||
debug!(
|
||||
"bumping reconnect duration from {:?} to {:?} and retrying connect",
|
||||
relay.retry_connect_after, next_duration
|
||||
);
|
||||
relay.retry_connect_after = next_duration;
|
||||
relay.relay.connect(wakeup.clone());
|
||||
} else {
|
||||
// let's wait a bit before we try again
|
||||
}
|
||||
}
|
||||
|
||||
RelayStatus::Connected => {
|
||||
relay.retry_connect_after = PoolRelay::initial_reconnect_duration();
|
||||
|
||||
let should_ping = now - relay.last_ping > self.ping_rate;
|
||||
if should_ping {
|
||||
debug!("pinging {}", relay.relay.url);
|
||||
relay.relay.ping();
|
||||
relay.last_ping = Instant::now();
|
||||
}
|
||||
}
|
||||
|
||||
RelayStatus::Connecting => {
|
||||
// cool story bro
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,7 +131,7 @@ impl RelayPool {
|
||||
pub fn add_url(
|
||||
&mut self,
|
||||
url: String,
|
||||
wakeup: impl Fn() + Send + Sync + 'static,
|
||||
wakeup: impl Fn() + Send + Sync + Clone + 'static,
|
||||
) -> Result<()> {
|
||||
let relay = Relay::new(url, wakeup)?;
|
||||
let pool_relay = PoolRelay::new(relay);
|
||||
@ -111,6 +148,7 @@ impl RelayPool {
|
||||
if let Some(msg) = relay.receiver.try_recv() {
|
||||
match msg.try_into() {
|
||||
Ok(event) => {
|
||||
relay.status = RelayStatus::Connected;
|
||||
// let's just handle pongs here.
|
||||
// We only need to do this natively.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@ -129,7 +167,8 @@ impl RelayPool {
|
||||
}
|
||||
|
||||
Err(e) => {
|
||||
error!("{:?}", e);
|
||||
relay.status = RelayStatus::Disconnected;
|
||||
error!("try_recv {:?}", e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,11 @@ fn try_process_event(damus: &mut Damus, ctx: &egui::Context) {
|
||||
ctx.set_pixels_per_point(ctx.pixels_per_point() - amount);
|
||||
}
|
||||
|
||||
damus.pool.keepalive_ping();
|
||||
let ctx2 = ctx.clone();
|
||||
let wakeup = move || {
|
||||
ctx2.request_repaint();
|
||||
};
|
||||
damus.pool.keepalive_ping(wakeup);
|
||||
|
||||
// pool stuff
|
||||
while let Some(ev) = damus.pool.try_recv() {
|
||||
|
Loading…
Reference in New Issue
Block a user