diff --git a/.idea/bbb-status.iml b/.idea/bbb-status.iml
index e0afde7..3c77fb3 100644
--- a/.idea/bbb-status.iml
+++ b/.idea/bbb-status.iml
@@ -3,8 +3,9 @@
+
-
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 9727bbc..d4e4db6 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index 3935217..7e9686c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3.7'
services:
bbb-status:
build: .
- command: ["log"] # see main.py for available commandline arguments
+ command: ["log-verbose"] # see main.py for available commandline arguments
environment:
- PYTHONPATH=/usr/src/ # pythonpath is required to import from self created modules ("from langfingaz ...")
- PYTHONUNBUFFERED=1
diff --git a/src/langfingaz/bbbRequest.py b/src/langfingaz/bbbRequest.py
index 1b22c9e..a51bb77 100644
--- a/src/langfingaz/bbbRequest.py
+++ b/src/langfingaz/bbbRequest.py
@@ -1,17 +1,27 @@
import hashlib
+import logging
+
import requests
+from requests.adapters import HTTPAdapter
+import requests.packages.urllib3.exceptions
+from requests.packages.urllib3.util.retry import Retry
+
from xml.etree import ElementTree
import langfingaz.util.fileUtil as fileUtil
-import langfingaz.util.util as util
-def requestMeetingData() -> str:
+def requestMeetingData(maxRetry=0, gracePeriod: int = 1) -> str:
+ """
+ :arg maxRetry: maximum connection retries; if maxRetry=None, then unlimited retires
+ :arg gracePeriod: seconds to wait before retry
+ :return: XML file containing data about currently active BBB meetings
+ See also: https://docs.bigbluebutton.org/dev/api.html#monitoring
+ as well as: https://docs.bigbluebutton.org/dev/api.html#getmeetings
+ """
+
requestUrl = getRequestUrl()
- util.debug("starting request for " + requestUrl)
- response = requests.get(requestUrl)
- if not response.ok:
- raise ValueError("error during request, got status code {}".format(response.status_code))
+ response: requests.Response = doGetRequest(requestUrl)
tree = ElementTree.fromstring(response.content)
if tree.find('returncode').text != 'SUCCESS':
@@ -20,6 +30,37 @@ def requestMeetingData() -> str:
return str(response.content, encoding=response.encoding)
+def doGetRequest(requestUrl: str, maxRetries=6) -> requests.Response:
+ """
+ Performs a HTTPS GET request for the given url and does at most maxRetries retries
+ on connection errors.
+
+ :raises requests.exceptions.HTTPError: If status code not 200 (will retry if 502, 503, 504)
+ :raises requests.packages.urllib3.exceptions.MaxRetryError:
+ """
+
+ logLevel = logging.root.level # https://stackoverflow.com/a/53951759/6334421
+ logging.basicConfig(level=logging.DEBUG)
+
+ # https://stackoverflow.com/a/35636367/6334421
+ # Retry on basic connectivity issues (including DNS lookup failures),
+ # and HTTP status codes of 502, 503 and 504
+ # Grace period increases after each retry.
+ # See also:
+ # - Session: https://requests.readthedocs.io/en/master/user/advanced/
+ s: requests.sessions.Session = requests.Session()
+ retries: Retry = Retry(total=maxRetries, backoff_factor=5, status_forcelist=[502, 503, 504])
+ s.mount('https://', HTTPAdapter(max_retries=retries))
+
+ response: requests.Response = s.get(requestUrl)
+ logging.basicConfig(level=logLevel)
+
+ # raise exception if status conde NOT 200
+ response.raise_for_status()
+
+ return response
+
+
def getRequestUrl(api_method: str = 'getMeetings', query_string: str = '') -> str:
url = getUrl()
api_url = url + "api/"
@@ -48,4 +89,3 @@ def getSecret() -> str:
if len(secret) <= min_length:
raise ValueError("secret should be longer than {} characters!".format(min_length))
return secret
-
diff --git a/src/langfingaz/logMeetingData.py b/src/langfingaz/logMeetingData.py
index 0415dc3..bca3803 100755
--- a/src/langfingaz/logMeetingData.py
+++ b/src/langfingaz/logMeetingData.py
@@ -14,9 +14,7 @@ def sleepFiveMin(verbose=False):
if verbose:
print(">> Sleeping for five minutes <<")
-
- sys.stdout.flush()
- time.sleep(fiveMinutes)
+ util.sleep(fiveMinutes)
def v2(folder: Path = saveData.getDefaultFolder()):
diff --git a/src/langfingaz/main.py b/src/langfingaz/main.py
index cc8b40f..67b0129 100755
--- a/src/langfingaz/main.py
+++ b/src/langfingaz/main.py
@@ -1,14 +1,14 @@
#!/usr/bin/python3
from sys import argv
+import logging
from langfingaz import plotMeetings
from langfingaz import logMeetingData
-from langfingaz.util import util
def main():
print("=== bbb-status ===")
- util.debug(str(argv))
+ logging.debug(str(argv))
print()
usageStr = 'Usage:\n' + argv[0] + ' [log|log-verbose|plot]\n' + \
diff --git a/src/langfingaz/util/util.py b/src/langfingaz/util/util.py
index 9afcefe..b7c9b6c 100644
--- a/src/langfingaz/util/util.py
+++ b/src/langfingaz/util/util.py
@@ -1,9 +1,9 @@
-BBB_STATUS_DEBUG = True
+import time
-def debug(message: str):
- if BBB_STATUS_DEBUG:
- print(">> " + message)
+def sleep(seconds: float):
+ print(flush=True) # print newline -> so that all characters of current line get flushed as well
+ time.sleep(seconds)
def indentMultilineStr(s: str, indentWith='\t'):