from dataclasses import dataclass, InitVar
from getpass import getuser
from threading import Thread
+from time import sleep
from typing import (Any, Callable, Collection, Generic, Iterable, Iterator,
Optional, Self, Set, TypeVar)
+from uuid import UUID, uuid4
# ourselves
from ircplom.events import (
AffectiveEvent, CrashingException, ExceptionEvent, QueueMixin)
conn: Optional[IrcConnection] = None
_cls_conn: type[IrcConnection] = IrcConnection
_expected_pong: str
- _retry_in_s: int
+ _retry_connect_in_s: int
+ _retry_connect_id: Optional[UUID] = None
def __init__(self, conn_setup: IrcConnSetup, channels: set[str], **kwargs
) -> None:
def connect(self) -> None:
'Attempt to open connection, on success perform session init steps.'
+ self._retry_connect_id = None
self.db.connection_state = 'connecting'
def connect(self) -> None:
self._put(ExceptionEvent(CrashingException(e)))
else:
self._expected_pong = ''
- self._retry_in_s = -1
+ self._retry_connect_in_s = -1
self.db.connection_state = 'connected'
self.caps.start_negotation()
self.send('USER', self.db.user_wanted,
if self.conn:
self.conn.close()
self.conn = None
- if self._retry_in_s > 0:
- self._retry_in_s *= 2
- self.connect()
+ 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
def on_handled_loop_exception(self, e: IrcConnException) -> None:
'On …AbortException, call .close(), on …Timeout… first (!) try PING.'
self.close()
elif isinstance(e, IrcConnTimeoutException):
if self._expected_pong:
- self._retry_in_s = 1
+ self._retry_connect_in_s = 1
self.on_handled_loop_exception(
IrcConnAbortException('no timely PONG from server'))
else: