xmpp::Agent::wait_for_events cannot error

xmppftw created

Change summary

xmpp/ChangeLog             |  3 +++
xmpp/examples/hello_bot.rs |  6 ++----
xmpp/src/agent.rs          |  9 ++-------
xmpp/src/builder.rs        |  3 ++-
xmpp/src/event_loop.rs     | 16 +++++++---------
xmpp/src/lib.rs            |  3 ++-
6 files changed, 18 insertions(+), 22 deletions(-)

Detailed changes

xmpp/ChangeLog 🔗

@@ -2,6 +2,9 @@ Version NEXT
 XXXX-YY-ZZ [ RELEASER <admin@localhost> ]
     * Fixes:
       - Use tokio::sync::RwLock not std::sync::RwLock (!432)
+      - Agent::wait_for_events now return Vec<Event> and sets inner tokio_xmpp Client
+        auto-reconnect to true... It is still aware of Event::Disconnected but should
+        no longer have weird hanging state or panic (!436)
 
 Version 0.6.0:
 2024-07-27 [ Maxime “pep” Buquet <pep@bouah.net> ]

xmpp/examples/hello_bot.rs 🔗

@@ -33,8 +33,8 @@ async fn main() -> Result<(), Option<()>> {
         .enable_feature(ClientFeature::JoinRooms)
         .build();
 
-    while let Some(events) = client.wait_for_events().await {
-        for event in events {
+    loop {
+        for event in client.wait_for_events().await {
             match event {
                 Event::Online => {
                     println!("Online.");
@@ -95,6 +95,4 @@ async fn main() -> Result<(), Option<()>> {
             }
         }
     }
-
-    Ok(())
 }

xmpp/src/agent.rs 🔗

@@ -85,13 +85,8 @@ impl<C: ServerConnector> Agent<C> {
         muc::private_message::send_room_private_message(self, room, recipient, lang, text).await
     }
 
-    /// Wait for new events.
-    ///
-    /// # Returns
-    ///
-    /// - `Some(events)` if there are new events; multiple may be returned at once.
-    /// - `None` if the underlying stream is closed.
-    pub async fn wait_for_events(&mut self) -> Option<Vec<Event>> {
+    /// Wait for new events, or Error::Disconnected when connection is closed and will not reconnect.
+    pub async fn wait_for_events(&mut self) -> Vec<Event> {
         event_loop::wait_for_events(self).await
     }
 

xmpp/src/builder.rs 🔗

@@ -148,7 +148,8 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
             password: self.password.into(),
             server: self.server_connector.clone(),
         };
-        let client = TokioXmppClient::new_with_config(config);
+        let mut client = TokioXmppClient::new_with_config(config);
+        client.set_reconnect(true);
         self.build_impl(client)
     }
 

xmpp/src/event_loop.rs 🔗

@@ -15,13 +15,8 @@ use tokio_xmpp::{
 
 use crate::{iq, message, presence, Agent, Event};
 
-/// Wait for new events.
-///
-/// # Returns
-///
-/// - `Some(events)` if there are new events; multiple may be returned at once.
-/// - `None` if the underlying stream is closed.
-pub async fn wait_for_events<C: ServerConnector>(agent: &mut Agent<C>) -> Option<Vec<Event>> {
+/// Wait for new events, or Error::Disconnected when stream is closed and will not reconnect.
+pub async fn wait_for_events<C: ServerConnector>(agent: &mut Agent<C>) -> Vec<Event> {
     if let Some(event) = agent.client.next().await {
         let mut events = Vec::new();
 
@@ -72,8 +67,11 @@ pub async fn wait_for_events<C: ServerConnector>(agent: &mut Agent<C>) -> Option
             }
         }
 
-        Some(events)
+        events
     } else {
-        None
+        // Stream was closed and not opening again because TokioXmppClient reconnect is false
+        // However we set reconnect true in agent builder so this should never happen and indicates
+        // logic error in tokio_xmpp::AsyncClient::poll_next
+        panic!("xmpp::Agent should never receive None event (stream closed, no reconnect)");
     }
 }

xmpp/src/lib.rs 🔗

@@ -63,7 +63,8 @@ mod tests {
 
         let mut agent = client_builder.build_impl(client);
 
-        while let Some(events) = agent.wait_for_events().await {
+        loop {
+            let events = agent.wait_for_events().await;
             assert!(match events[0] {
                 Event::Disconnected(_) => true,
                 _ => false,