From a6c973fdbecb927c1def98dec3126eece3820049 Mon Sep 17 00:00:00 2001 From: 15532th <92187332+15532th@users.noreply.github.com> Date: Sat, 16 Sep 2023 20:35:54 +0300 Subject: [PATCH] Handle exceptions in FC2LiveStream.wait_for_online (#47) * Make FC2LiveStream.get_meta raise on status code >= 400 Currently response with, for example, 503 error will cause json decoding error, making debugging harder. * Add try-except and exponential backoff in wait_for_online --------- Co-authored-by: user --- fc2_live_dl/fc2.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/fc2_live_dl/fc2.py b/fc2_live_dl/fc2.py index e0211e5..a4770d9 100644 --- a/fc2_live_dl/fc2.py +++ b/fc2_live_dl/fc2.py @@ -200,6 +200,9 @@ def __str__(self): class FC2LiveStream: + + MAX_LIVE_CHECK_INTERVAL = 300 + def __init__(self, session, channel_id): self._meta = None self._session = session @@ -207,8 +210,22 @@ def __init__(self, session, channel_id): self.channel_id = channel_id async def wait_for_online(self, interval): - while not await self.is_online(): - for _ in range(interval): + current_interval = interval + while True: + try: + if await self.is_online(): + break + except Exception as e: + description = f'{e.__class__.__name__}: {e}' + self._logger.warn(f'Error when checking if stream is live: {description}') + current_interval = min(current_interval * 2, self.MAX_LIVE_CHECK_INTERVAL) + self._logger.debug(f'Next check in {current_interval} seconds') + else: + if current_interval != interval: + self._logger.debug(f'Successfully fetched live status, restoring check interval of {interval} seconds') + current_interval = interval + + for _ in range(current_interval): self._logger.info("Waiting for stream", inline=True, spin=True) await asyncio.sleep(1) @@ -271,6 +288,7 @@ async def get_meta(self, *, refetch=False): } self._logger.trace("get_meta>", url, data) async with self._session.post(url, data=data) as resp: + resp.raise_for_status() # FC2 returns text/javascript instead of application/json # Content type is specified so aiohttp knows what to expect data = await resp.json(content_type="text/javascript")