From aa0f207d595edd04c57cbadad2e5f7c3cb7ae9d6 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Thu, 2 Oct 2025 20:21:21 +0200 Subject: [PATCH] Also start exponentially delayed connection retry on connecting timeout. --- src/ircplom/client.py | 38 ++++++++++++++++++++++---------------- src/ircplom/irc_conn.py | 4 +++- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/ircplom/client.py b/src/ircplom/client.py index bf8c28b..2714ccc 100644 --- a/src/ircplom/client.py +++ b/src/ircplom/client.py @@ -820,7 +820,7 @@ class Client(ABC, ClientQueueMixin): conn: Optional[IrcConnection] = None _cls_conn: type[IrcConnection] = IrcConnection _expected_pong: str - _retry_connect_in_s: int + _retry_connect_in_s: int = -1 _retry_connect_id: Optional[UUID] = None def __init__(self, conn_setup: IrcConnSetup, channels: set[str], **kwargs @@ -849,8 +849,12 @@ class Client(ABC, ClientQueueMixin): self.conn = self._cls_conn( hostname=self.db.hostname, port=self.db.port, _q_out=self._q_out, client_id=self.client_id) - except IrcConnAbortException as e: + except IrcConnException as e: self.db.connection_state = f'failed to connect: {e}' + if isinstance(e, IrcConnTimeoutException): + if not self._retry_connect_in_s > 0: + self._retry_connect_in_s = 1 + self._client_trigger('_delayed_retry_connect') except Exception as e: # pylint: disable=broad-exception-caught self._put(ExceptionEvent(CrashingException(e))) else: @@ -865,6 +869,21 @@ class Client(ABC, ClientQueueMixin): # Do this in a thread, not to block flow of other (e.g. TUI) events. Thread(target=connect, daemon=True, args=(self,)).start() + def _delayed_retry_connect(self) -> None: + def delayed_connect(self, wait_s: int, retry_connect_id: UUID + ) -> None: + sleep(wait_s) + if self._retry_connect_id == retry_connect_id: + self._client_trigger('connect') + + self._retry_connect_id = uuid4() + self._alert( + f'will retry connecting in {self._retry_connect_in_s} seconds') + Thread(target=delayed_connect, daemon=True, + args=(self, self._retry_connect_in_s, self._retry_connect_id) + ).start() + self._retry_connect_in_s *= 2 + def close(self) -> None: 'Close connection, wipe memory of its states, reconnect if indicated.' if not self._autojoins: @@ -875,20 +894,7 @@ class Client(ABC, ClientQueueMixin): self.conn.close() self.conn = None if self._retry_connect_in_s > 0: - def delayed_connect(self, wait_s: int, retry_connect_id: UUID - ) -> None: - sleep(wait_s) - if self._retry_connect_id == retry_connect_id: - self._client_trigger('connect') - - self._retry_connect_id = uuid4() - self._alert( - f'will retry connecting in {self._retry_connect_in_s} seconds') - Thread(target=delayed_connect, daemon=True, - args=(self, self._retry_connect_in_s, - self._retry_connect_id) - ).start() - self._retry_connect_in_s *= 2 + self._delayed_retry_connect() def on_handled_loop_exception(self, e: IrcConnException) -> None: 'On …AbortException, call .close(), on …Timeout… first (!) try PING.' diff --git a/src/ircplom/irc_conn.py b/src/ircplom/irc_conn.py index e7f7010..2605e94 100644 --- a/src/ircplom/irc_conn.py +++ b/src/ircplom/irc_conn.py @@ -159,7 +159,9 @@ class BaseIrcConnection(QueueMixin, ABC): self._socket.settimeout(_TIMEOUT_CONNECT) try: self._socket.connect((hostname, port)) - except (TimeoutError, socket_gaierror) as e: + except TimeoutError as e: + raise IrcConnTimeoutException(e) from e + except socket_gaierror as e: raise IrcConnAbortException(e) from e self._socket.settimeout(_TIMEOUT_RECV_LOOP) -- 2.30.2