diff --git a/admission.py b/admission.py index 1e4c5b3..254ce03 100644 --- a/admission.py +++ b/admission.py @@ -88,7 +88,11 @@ def handle_notify() -> None: stream_list = config.LAST_STREAM_LIST.copy() # Remove or add the changed stream, as appropriate - if cherrypy.request.update_opening and cherrypy.request.update_stream not in stream_list: + # NOTE: This can result in the list containing duplicates; we need to de-dupe before we use it + # This is necessary because OME emits open and close events for rejections due to key + # already being in use. Without dupes, this scenario would knock the stream out of the + # list entirely. + if cherrypy.request.update_opening: stream_list.append(cherrypy.request.update_stream) if not cherrypy.request.update_opening and cherrypy.request.update_stream in stream_list: diff --git a/main.py b/main.py index 2b5a256..5785faa 100644 --- a/main.py +++ b/main.py @@ -44,9 +44,10 @@ if __name__ == "__main__": # Load config values config.load() - # If we have API access, use it to pull our stream list - if config.is_api_ready(): - config.LAST_STREAM_LIST = ovenapi.OvenAPI(config.API_USER, config.API_PASS).get_stream_list() + # If we have API access, use it to pull our stream list into cache + config.LAST_STREAM_LIST = ovenapi.get_api_handle( + username=config.API_USER, password=config.API_PASS + ).get_stream_list() runpath = Path(Path(__file__).parent.resolve(), "assets") diff --git a/management.py b/management.py index 493ec40..95ad191 100644 --- a/management.py +++ b/management.py @@ -13,7 +13,7 @@ class Management: def __init__(self): self.page_template = Path("template/management.mako").read_text(encoding="utf-8") self.redirect_template = Path("template/message.mako").read_text(encoding="utf-8") - self.api = ovenapi.OvenAPI(config.API_USER, config.API_PASS) + self.api = ovenapi.get_api_handle(username=config.API_USER, password=config.API_PASS) @staticmethod def __verify_same_domain() -> bool: diff --git a/ovenapi.py b/ovenapi.py index f77829d..d674c5e 100644 --- a/ovenapi.py +++ b/ovenapi.py @@ -1,6 +1,9 @@ import requests +API_HANDLE = None + + class OvenAPI: def __init__(self, username: str, password: str, api_path: str = "http://localhost:8081/v1") -> None: self.opener = requests.Session() @@ -111,3 +114,12 @@ class OvenAPI: return resp["response"]["input"]["sourceUrl"].split("://")[1].split(":")[0] except Exception: return None + + +def get_api_handle(**kwargs): + """Cache and return a single canonical API handle.""" + global API_HANDLE # noqa: PLW0603 + if API_HANDLE is None: + API_HANDLE = OvenAPI(**kwargs) + + return API_HANDLE diff --git a/status.py b/status.py index 5245424..d44d7e0 100644 --- a/status.py +++ b/status.py @@ -16,7 +16,7 @@ class Status: return self def __init__(self): - self.api = ovenapi.OvenAPI(config.API_USER, config.API_PASS) + self.api = ovenapi.get_api_handle(username=config.API_USER, password=config.API_PASS) @cherrypy.expose @cherrypy.tools.json_out() @@ -30,8 +30,10 @@ class Status: # Use config.LAST_STREAM_LIST here because this is a cache of the last # stream list the last time the list of streams changed. It should be # accurate. + # We de-dupe because the cached list can end up with duplicates but + # in all cases, one live entry should mean that stream is live. for s_vhost, s_app, s_stream in config.LAST_STREAM_LIST: - if s_vhost == vhost and s_app == app: + if s_vhost == vhost and s_app == app and s_stream not in streams: streams.append(s_stream) return streams diff --git a/viewer.py b/viewer.py index a38d8d3..c427024 100644 --- a/viewer.py +++ b/viewer.py @@ -12,7 +12,7 @@ class Viewer: def __init__(self): self.webcall_template = Path("template/webcall.mako").read_text(encoding="utf-8") self.single_template = Path("template/single.mako").read_text(encoding="utf-8") - self.api = ovenapi.OvenAPI(config.API_USER, config.API_PASS) + self.api = ovenapi.get_api_handle(username=config.API_USER, password=config.API_PASS) def app_is_okay(self, app_name): # If we can't access the API, we can't check if an app exists, just okay it