feat: implement timeouts for all methods (#34)

BREAKING CHANGE: Removed the `wait_timeout` parameter. Use the new `timeout` parameter instead. The `timeout` parameter specifies how many seconds the client should wait for the connection, an expected event or a server response.
This commit is contained in:
Lucas Held 2023-05-19 13:50:39 +02:00 committed by GitHub
parent 8e841cd324
commit 9728cfdb34
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 17 deletions

View file

@ -39,3 +39,5 @@ Exceptions
---------- ----------
.. autoexception:: UptimeKumaException .. autoexception:: UptimeKumaException
.. autoexception:: Timeout

View file

@ -6,6 +6,6 @@ from .proxy_protocol import ProxyProtocol
from .incident_style import IncidentStyle from .incident_style import IncidentStyle
from .docker_type import DockerType from .docker_type import DockerType
from .maintenance_strategy import MaintenanceStrategy from .maintenance_strategy import MaintenanceStrategy
from .exceptions import UptimeKumaException from .exceptions import UptimeKumaException, Timeout
from .event import Event from .event import Event
from .api import UptimeKumaApi from .api import UptimeKumaApi

View file

@ -21,6 +21,7 @@ from . import (AuthMethod,
MonitorType, MonitorType,
NotificationType, NotificationType,
ProxyProtocol, ProxyProtocol,
Timeout,
UptimeKumaException, UptimeKumaException,
notification_provider_conditions, notification_provider_conditions,
notification_provider_options) notification_provider_options)
@ -382,7 +383,8 @@ class UptimeKumaApi(object):
) )
:param str url: The url to the Uptime Kuma instance. For example ``http://127.0.0.1:3001`` :param str url: The url to the Uptime Kuma instance. For example ``http://127.0.0.1:3001``
:param float wait_timeout: How many seconds the client should wait for the connection., defaults to 1 :param float timeout: How many seconds the client should wait for the connection, an expected event or a server
response. Default is ``10``.
:param dict headers: Headers that are passed to the socketio connection, defaults to None :param dict headers: Headers that are passed to the socketio connection, defaults to None
:param bool ssl_verify: ``True`` to verify SSL certificates, or ``False`` to skip SSL certificate :param bool ssl_verify: ``True`` to verify SSL certificates, or ``False`` to skip SSL certificate
verification, allowing connections to servers with self signed certificates. verification, allowing connections to servers with self signed certificates.
@ -396,13 +398,13 @@ class UptimeKumaApi(object):
def __init__( def __init__(
self, self,
url: str, url: str,
wait_timeout: float = 1, timeout: float = 10,
headers: dict = None, headers: dict = None,
ssl_verify: bool = True, ssl_verify: bool = True,
wait_events: float = 0.2 wait_events: float = 0.2
) -> None: ) -> None:
self.url = url self.url = url
self.wait_timeout = wait_timeout self.timeout = timeout
self.headers = headers self.headers = headers
self.wait_events = wait_events self.wait_events = wait_events
self.sio = socketio.Client(ssl_verify=ssl_verify) self.sio = socketio.Client(ssl_verify=ssl_verify)
@ -454,26 +456,25 @@ class UptimeKumaApi(object):
@contextmanager @contextmanager
def wait_for_event(self, event: Event) -> None: def wait_for_event(self, event: Event) -> None:
# 200 * 0.05 seconds = 10 seconds # waits for the first event of the given type to arrive
retries = 200
sleep = 0.05
try: try:
yield yield
except: except:
raise raise
else: else:
counter = 0 timestamp = time.time()
while self._event_data[event] is None: while self._event_data[event] is None:
time.sleep(sleep) if time.time() - timestamp > self.timeout:
counter += 1 raise Timeout(f"Timed out while waiting for event {event}")
if counter >= retries: time.sleep(0.01)
print(f"wait_for_event {event} timeout")
break
def _get_event_data(self, event) -> Any: def _get_event_data(self, event) -> Any:
monitor_events = [Event.AVG_PING, Event.UPTIME, Event.HEARTBEAT_LIST, Event.IMPORTANT_HEARTBEAT_LIST, Event.CERT_INFO, Event.HEARTBEAT] monitor_events = [Event.AVG_PING, Event.UPTIME, Event.HEARTBEAT_LIST, Event.IMPORTANT_HEARTBEAT_LIST, Event.CERT_INFO, Event.HEARTBEAT]
timestamp = time.time()
while self._event_data[event] is None: while self._event_data[event] is None:
if time.time() - timestamp > self.timeout:
raise Timeout(f"Timed out while waiting for event {event}")
# do not wait for events that are not sent # do not wait for events that are not sent
if self._event_data[Event.MONITOR_LIST] == {} and event in monitor_events: if self._event_data[Event.MONITOR_LIST] == {} and event in monitor_events:
return [] return []
@ -482,7 +483,7 @@ class UptimeKumaApi(object):
return deepcopy(self._event_data[event]) return deepcopy(self._event_data[event])
def _call(self, event, data=None) -> Any: def _call(self, event, data=None) -> Any:
r = self.sio.call(event, data) r = self.sio.call(event, data, timeout=self.timeout)
if isinstance(r, dict) and "ok" in r: if isinstance(r, dict) and "ok" in r:
if not r["ok"]: if not r["ok"]:
raise UptimeKumaException(r.get("msg")) raise UptimeKumaException(r.get("msg"))
@ -587,7 +588,7 @@ class UptimeKumaApi(object):
""" """
url = self.url.rstrip("/") url = self.url.rstrip("/")
try: try:
self.sio.connect(f'{url}/socket.io/', wait_timeout=self.wait_timeout, headers=self.headers) self.sio.connect(f'{url}/socket.io/', wait_timeout=self.timeout, headers=self.headers)
except: except:
raise UptimeKumaException("unable to connect") raise UptimeKumaException("unable to connect")
@ -1727,7 +1728,10 @@ class UptimeKumaApi(object):
} }
""" """
r1 = self._call('getStatusPage', slug) r1 = self._call('getStatusPage', slug)
r2 = requests.get(f"{self.url}/api/status-page/{slug}").json() try:
r2 = requests.get(f"{self.url}/api/status-page/{slug}", timeout=self.timeout).json()
except requests.exceptions.Timeout as e:
raise Timeout(e)
config = r1["config"] config = r1["config"]
config.update(r2["config"]) config.update(r2["config"])

View file

@ -2,4 +2,9 @@ class UptimeKumaException(Exception):
""" """
There was an exception that occurred while communicating with Uptime Kuma. There was an exception that occurred while communicating with Uptime Kuma.
""" """
pass
class Timeout(UptimeKumaException):
"""
A timeout has occurred while communicating with Uptime Kuma.
"""