Events: Add (re)connect success/fail events.
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.
This commit is contained in:
@@ -12,6 +12,7 @@ use super::{
|
|||||||
connection::{error::Error as ConnectionError, Connection},
|
connection::{error::Error as ConnectionError, Connection},
|
||||||
Config,
|
Config,
|
||||||
};
|
};
|
||||||
|
use crate::events::CoreContext;
|
||||||
use flume::{Receiver, RecvError, Sender};
|
use flume::{Receiver, RecvError, Sender};
|
||||||
use message::*;
|
use message::*;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
@@ -75,12 +76,21 @@ async fn runner(mut config: Config, rx: Receiver<CoreMessage>, tx: Sender<CoreMe
|
|||||||
Ok(connection) => {
|
Ok(connection) => {
|
||||||
// Other side may not be listening: this is fine.
|
// Other side may not be listening: this is fine.
|
||||||
let _ = tx.send(Ok(()));
|
let _ = tx.send(Ok(()));
|
||||||
|
|
||||||
|
let _ = interconnect
|
||||||
|
.events
|
||||||
|
.send(EventMessage::FireCoreEvent(CoreContext::DriverConnect));
|
||||||
|
|
||||||
Some(connection)
|
Some(connection)
|
||||||
},
|
},
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
// See above.
|
// See above.
|
||||||
let _ = tx.send(Err(why));
|
let _ = tx.send(Err(why));
|
||||||
|
|
||||||
|
let _ = interconnect.events.send(EventMessage::FireCoreEvent(
|
||||||
|
CoreContext::DriverConnectFailed,
|
||||||
|
));
|
||||||
|
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -145,10 +155,19 @@ async fn runner(mut config: Config, rx: Receiver<CoreMessage>, tx: Sender<CoreMe
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Catastrophic connection failure. Stopping. {:?}", e);
|
error!("Catastrophic connection failure. Stopping. {:?}", e);
|
||||||
|
let _ = interconnect.events.send(EventMessage::FireCoreEvent(
|
||||||
|
CoreContext::DriverReconnectFailed,
|
||||||
|
));
|
||||||
e
|
e
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if connection.is_some() {
|
||||||
|
let _ = interconnect
|
||||||
|
.events
|
||||||
|
.send(EventMessage::FireCoreEvent(CoreContext::DriverReconnect));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Ok(CoreMessage::FullReconnect) =>
|
Ok(CoreMessage::FullReconnect) =>
|
||||||
@@ -159,9 +178,18 @@ async fn runner(mut config: Config, rx: Receiver<CoreMessage>, tx: Sender<CoreMe
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Catastrophic connection failure. Stopping. {:?}", e);
|
error!("Catastrophic connection failure. Stopping. {:?}", e);
|
||||||
|
let _ = interconnect.events.send(EventMessage::FireCoreEvent(
|
||||||
|
CoreContext::DriverReconnectFailed,
|
||||||
|
));
|
||||||
e
|
e
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
|
if connection.is_some() {
|
||||||
|
let _ = interconnect
|
||||||
|
.events
|
||||||
|
.send(EventMessage::FireCoreEvent(CoreContext::DriverReconnect));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Ok(CoreMessage::RebuildInterconnect) => {
|
Ok(CoreMessage::RebuildInterconnect) => {
|
||||||
interconnect.restart_volatile_internals();
|
interconnect.restart_volatile_internals();
|
||||||
|
|||||||
@@ -69,6 +69,16 @@ pub enum EventContext<'a> {
|
|||||||
ClientConnect(ClientConnect),
|
ClientConnect(ClientConnect),
|
||||||
/// Fired whenever a client disconnects.
|
/// Fired whenever a client disconnects.
|
||||||
ClientDisconnect(ClientDisconnect),
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -91,6 +101,10 @@ pub enum CoreContext {
|
|||||||
},
|
},
|
||||||
ClientConnect(ClientConnect),
|
ClientConnect(ClientConnect),
|
||||||
ClientDisconnect(ClientDisconnect),
|
ClientDisconnect(ClientDisconnect),
|
||||||
|
DriverConnect,
|
||||||
|
DriverReconnect,
|
||||||
|
DriverConnectFailed,
|
||||||
|
DriverReconnectFailed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CoreContext {
|
impl<'a> CoreContext {
|
||||||
@@ -125,6 +139,10 @@ impl<'a> CoreContext {
|
|||||||
},
|
},
|
||||||
ClientConnect(evt) => EventContext::ClientConnect(*evt),
|
ClientConnect(evt) => EventContext::ClientConnect(*evt),
|
||||||
ClientDisconnect(evt) => EventContext::ClientDisconnect(*evt),
|
ClientDisconnect(evt) => EventContext::ClientDisconnect(*evt),
|
||||||
|
DriverConnect => EventContext::DriverConnect,
|
||||||
|
DriverReconnect => EventContext::DriverReconnect,
|
||||||
|
DriverConnectFailed => EventContext::DriverConnectFailed,
|
||||||
|
DriverReconnectFailed => EventContext::DriverReconnectFailed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +160,10 @@ impl EventContext<'_> {
|
|||||||
RtcpPacket { .. } => Some(CoreEvent::RtcpPacket),
|
RtcpPacket { .. } => Some(CoreEvent::RtcpPacket),
|
||||||
ClientConnect { .. } => Some(CoreEvent::ClientConnect),
|
ClientConnect { .. } => Some(CoreEvent::ClientConnect),
|
||||||
ClientDisconnect { .. } => Some(CoreEvent::ClientDisconnect),
|
ClientDisconnect { .. } => Some(CoreEvent::ClientDisconnect),
|
||||||
|
DriverConnect => Some(CoreEvent::DriverConnect),
|
||||||
|
DriverReconnect => Some(CoreEvent::DriverReconnect),
|
||||||
|
DriverConnectFailed => Some(CoreEvent::DriverConnectFailed),
|
||||||
|
DriverReconnectFailed => Some(CoreEvent::DriverReconnectFailed),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,4 +29,14 @@ pub enum CoreEvent {
|
|||||||
ClientConnect,
|
ClientConnect,
|
||||||
/// Fires whenever a user disconnects from the same stream as the bot.
|
/// Fires whenever a user disconnects from the same stream as the bot.
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user