Add XMPP auto-reconnect loop
XMPPClient.connect_async() now runs a persistent reconnect loop in a daemon thread. On connection loss, it reconnects after 5s with exponential backoff up to 60s. The on_ready callback is only called on the first successful connection. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+50
-33
@@ -71,41 +71,57 @@ class XMPPClient:
|
|||||||
return bare in self.admin_jids
|
return bare in self.admin_jids
|
||||||
|
|
||||||
def connect_async(self, on_ready: Optional[Callable] = None):
|
def connect_async(self, on_ready: Optional[Callable] = None):
|
||||||
"""Connexion XMPP dans un thread dédié.
|
"""Connexion XMPP dans un thread dédié avec reconnexion automatique."""
|
||||||
on_ready() est appelé une fois la connexion établie.
|
|
||||||
"""
|
|
||||||
self._on_ready_cb = on_ready
|
self._on_ready_cb = on_ready
|
||||||
self._client = _SlixClient(
|
self._stop_reconnect = False
|
||||||
jid=self.jid,
|
threading.Thread(target=self._reconnect_loop, daemon=True, name="xmpp-reconnect").start()
|
||||||
password=self.password,
|
|
||||||
muc_room=self.muc_room,
|
|
||||||
muc_nick=self.muc_nick,
|
|
||||||
use_omemo=self.use_omemo,
|
|
||||||
on_message=self._on_message,
|
|
||||||
on_connected=self._connected.set,
|
|
||||||
)
|
|
||||||
self._thread = threading.Thread(
|
|
||||||
target=self._client.start,
|
|
||||||
daemon=True,
|
|
||||||
name="xmpp-client",
|
|
||||||
)
|
|
||||||
self._thread.start()
|
|
||||||
threading.Thread(target=self._wait_and_log, daemon=True).start()
|
|
||||||
|
|
||||||
def _wait_and_log(self):
|
def _reconnect_loop(self):
|
||||||
if self._connected.wait(timeout=30):
|
"""Boucle de connexion/reconnexion XMPP."""
|
||||||
logger.info(f"[XMPP] Connecté : {self.jid}")
|
import time as _time
|
||||||
if self.muc_room:
|
delay = 5
|
||||||
logger.info(f"[XMPP] Groupe rejoint : {self.muc_room}")
|
first = True
|
||||||
if self.admin_jids:
|
while not self._stop_reconnect:
|
||||||
logger.info(f"[XMPP] Admins autorisés : {', '.join(sorted(self.admin_jids))}")
|
self._connected.clear()
|
||||||
if self._on_ready_cb:
|
try:
|
||||||
try:
|
self._client = _SlixClient(
|
||||||
self._on_ready_cb()
|
jid=self.jid,
|
||||||
except Exception as e:
|
password=self.password,
|
||||||
logger.error(f"[XMPP] Erreur on_ready callback : {e}")
|
muc_room=self.muc_room,
|
||||||
else:
|
muc_nick=self.muc_nick,
|
||||||
logger.warning("[XMPP] Timeout connexion")
|
use_omemo=self.use_omemo,
|
||||||
|
on_message=self._on_message,
|
||||||
|
on_connected=self._connected.set,
|
||||||
|
)
|
||||||
|
# Lance la connexion dans ce thread (bloquant)
|
||||||
|
t = threading.Thread(target=self._client.start, daemon=True, name="xmpp-client")
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
if self._connected.wait(timeout=30):
|
||||||
|
logger.info(f"[XMPP] Connecté : {self.jid}")
|
||||||
|
if self.muc_room:
|
||||||
|
logger.info(f"[XMPP] Groupe rejoint : {self.muc_room}")
|
||||||
|
if self.admin_jids:
|
||||||
|
logger.info(f"[XMPP] Admins autorisés : {', '.join(sorted(self.admin_jids))}")
|
||||||
|
if first and self._on_ready_cb:
|
||||||
|
first = False
|
||||||
|
try:
|
||||||
|
self._on_ready_cb()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[XMPP] Erreur on_ready callback : {e}")
|
||||||
|
delay = 5 # Reset du délai après succès
|
||||||
|
t.join() # Attend la fin de la session (déconnexion)
|
||||||
|
if not self._stop_reconnect:
|
||||||
|
logger.warning("[XMPP] Connexion perdue. Reconnexion dans 5s...")
|
||||||
|
else:
|
||||||
|
logger.warning("[XMPP] Timeout connexion. Nouvelle tentative dans 10s...")
|
||||||
|
delay = 10
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[XMPP] Erreur connexion : {e}. Retry dans {delay}s...")
|
||||||
|
|
||||||
|
if not self._stop_reconnect:
|
||||||
|
_time.sleep(delay)
|
||||||
|
delay = min(delay * 2, 60) # Backoff exponentiel jusqu'à 60s
|
||||||
|
|
||||||
def _on_message(self, sender: str, body: str, is_muc: bool):
|
def _on_message(self, sender: str, body: str, is_muc: bool):
|
||||||
"""Filtre les messages : seuls les admins sont traités (sauf MUC)."""
|
"""Filtre les messages : seuls les admins sont traités (sauf MUC)."""
|
||||||
@@ -157,6 +173,7 @@ class XMPPClient:
|
|||||||
logger.info(f"[XMPP] Admin retiré : {bare}")
|
logger.info(f"[XMPP] Admin retiré : {bare}")
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
|
self._stop_reconnect = True
|
||||||
if self._client:
|
if self._client:
|
||||||
try:
|
try:
|
||||||
self._client.disconnect()
|
self._client.disconnect()
|
||||||
|
|||||||
Reference in New Issue
Block a user