Skip to content

Commit

Permalink
Events: Add (re)connect success/fail events.
Browse files Browse the repository at this point in the history
These should allow bots to hook up events to a variety of important connection events as required. This was primarily motivated by the user who raised dcb6ad9.

Although I really would have liked to squeeze in (finite) reconnection attempts with exponential backoff, so that automated repeat attempts could be neatly handled, `Config` was accidentally *not* made non-exhaustive. Adding this and its needed configuration would then be a breaking change. This should warn users about an accidentally dead connection, until the next version can be put forth.
  • Loading branch information
FelixMcFelix committed Jan 17, 2021
1 parent 55b8e7f commit cb2398f
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/driver/tasks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use super::{
connection::{error::Error as ConnectionError, Connection},
Config,
};
use crate::events::CoreContext;
use flume::{Receiver, RecvError, Sender};
use message::*;
use tokio::runtime::Handle;
Expand Down Expand Up @@ -75,12 +76,21 @@ async fn runner(mut config: Config, rx: Receiver<CoreMessage>, tx: Sender<CoreMe
Ok(connection) => {
// Other side may not be listening: this is fine.
let _ = tx.send(Ok(()));

let _ = interconnect
.events
.send(EventMessage::FireCoreEvent(CoreContext::DriverConnect));

Some(connection)
},
Err(why) => {
// See above.
let _ = tx.send(Err(why));

let _ = interconnect.events.send(EventMessage::FireCoreEvent(
CoreContext::DriverConnectFailed,
));

None
},
};
Expand Down Expand Up @@ -145,10 +155,19 @@ async fn runner(mut config: Config, rx: Receiver<CoreMessage>, tx: Sender<CoreMe
.await
.map_err(|e| {
error!("Catastrophic connection failure. Stopping. {:?}", e);
let _ = interconnect.events.send(EventMessage::FireCoreEvent(
CoreContext::DriverReconnectFailed,
));
e
})
.ok();
}

if connection.is_some() {
let _ = interconnect
.events
.send(EventMessage::FireCoreEvent(CoreContext::DriverReconnect));
}
}
},
Ok(CoreMessage::FullReconnect) =>
Expand All @@ -159,9 +178,18 @@ async fn runner(mut config: Config, rx: Receiver<CoreMessage>, tx: Sender<CoreMe
.await
.map_err(|e| {
error!("Catastrophic connection failure. Stopping. {:?}", e);
let _ = interconnect.events.send(EventMessage::FireCoreEvent(
CoreContext::DriverReconnectFailed,
));
e
})
.ok();

if connection.is_some() {
let _ = interconnect
.events
.send(EventMessage::FireCoreEvent(CoreContext::DriverReconnect));
}
},
Ok(CoreMessage::RebuildInterconnect) => {
interconnect.restart_volatile_internals();
Expand Down
22 changes: 22 additions & 0 deletions src/events/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ pub enum EventContext<'a> {
ClientConnect(ClientConnect),
/// Fired whenever a client disconnects.
ClientDisconnect(ClientDisconnect),
/// Fires when this driver successully connects to a voice channel.
DriverConnect,
/// Fires when this driver successful reconnects after a network error.
DriverReconnect,
/// Fires when this driver fails to connect to a voice channel.
DriverConnectFailed,
/// Fires when this driver fails to reconnect to a voice channel after a network error.
///
/// Users will need to manually reconnect on receipt of this error.
DriverReconnectFailed,
}

#[derive(Clone, Debug)]
Expand All @@ -91,6 +101,10 @@ pub enum CoreContext {
},
ClientConnect(ClientConnect),
ClientDisconnect(ClientDisconnect),
DriverConnect,
DriverReconnect,
DriverConnectFailed,
DriverReconnectFailed,
}

impl<'a> CoreContext {
Expand Down Expand Up @@ -125,6 +139,10 @@ impl<'a> CoreContext {
},
ClientConnect(evt) => EventContext::ClientConnect(*evt),
ClientDisconnect(evt) => EventContext::ClientDisconnect(*evt),
DriverConnect => EventContext::DriverConnect,
DriverReconnect => EventContext::DriverReconnect,
DriverConnectFailed => EventContext::DriverConnectFailed,
DriverReconnectFailed => EventContext::DriverReconnectFailed,
}
}
}
Expand All @@ -142,6 +160,10 @@ impl EventContext<'_> {
RtcpPacket { .. } => Some(CoreEvent::RtcpPacket),
ClientConnect { .. } => Some(CoreEvent::ClientConnect),
ClientDisconnect { .. } => Some(CoreEvent::ClientDisconnect),
DriverConnect => Some(CoreEvent::DriverConnect),
DriverReconnect => Some(CoreEvent::DriverReconnect),
DriverConnectFailed => Some(CoreEvent::DriverConnectFailed),
DriverReconnectFailed => Some(CoreEvent::DriverReconnectFailed),
_ => None,
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/events/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,14 @@ pub enum CoreEvent {
ClientConnect,
/// Fires whenever a user disconnects from the same stream as the bot.
ClientDisconnect,
/// Fires when this driver successully connects to a voice channel.
DriverConnect,
/// Fires when this driver successful reconnects after a network error.
DriverReconnect,
/// Fires when this driver fails to connect to a voice channel.
DriverConnectFailed,
/// Fires when this driver fails to reconnect to a voice channel after a network error.
///
/// Users will need to manually reconnect on receipt of this error.
DriverReconnectFailed,
}

0 comments on commit cb2398f

Please sign in to comment.