Mnt task now does a better job;

at tracking upcoming campaign start times
This commit is contained in:
DevilXD committed 2022-04-13 22:06:59 +02:00
1 parent ddd689c555
commit 903b299bfe
1 file changed
+21 -10
+21 -10
View File
@@ -2,9 +2,11 @@ from __future__ import annotations
import asyncio import asyncio
import logging import logging
from math import ceil
from time import time from time import time
from functools import partial from functools import partial
from collections import abc, OrderedDict from collections import abc, OrderedDict
from datetime import datetime, timedelta, timezone
from contextlib import suppress, asynccontextmanager from contextlib import suppress, asynccontextmanager
from typing import Final, NoReturn, cast, TYPE_CHECKING from typing import Final, NoReturn, cast, TYPE_CHECKING
@@ -32,8 +34,6 @@ from constants import (
) )
if TYPE_CHECKING: if TYPE_CHECKING:
from datetime import datetime
from utils import Game from utils import Game
from gui import LoginForm from gui import LoginForm
from settings import Settings from settings import Settings
@@ -200,9 +200,9 @@ class Twitch:
self._state_change.clear() self._state_change.clear()
elif self._state is State.INVENTORY_FETCH: elif self._state is State.INVENTORY_FETCH:
# NOTE: maintenance task is restarted on inventory fetch # NOTE: maintenance task is restarted on inventory fetch
if self._mnt_task is not None: if self._mnt_task is not None and not self._mnt_task.done():
self._mnt_task.cancel() self._mnt_task.cancel()
self._mnt_task = asyncio.create_task(self._maintenance_loop()) self._mnt_task = asyncio.create_task(self._maintenance_task())
await self.fetch_inventory() await self.fetch_inventory()
self.gui.set_games(set(campaign.game for campaign in self.inventory)) self.gui.set_games(set(campaign.game for campaign in self.inventory))
self.change_state(State.GAMES_UPDATE) self.change_state(State.GAMES_UPDATE)
@@ -449,18 +449,29 @@ class Twitch:
await self._watch_sleep(last_watch + interval - time()) await self._watch_sleep(last_watch + interval - time())
@task_wrapper @task_wrapper
async def _maintenance_loop(self) -> None: async def _maintenance_task(self) -> None:
# NOTE: this task is restarted on every inventory fetch # NOTE: this task is started anew / restarted on every inventory fetch
# 1m sleep to let the application sort out the starting sequence and watching channel
await asyncio.sleep(60) await asyncio.sleep(60)
for i in range(2): # figure out the maximum sleep period
# 1h at max, but can be shorter if there's an upcoming campaign earlier than that
# divide the period into up to two evenly spaced checks (usually ~15-30m)
now = datetime.now(timezone.utc)
period = min(
campaign.starts_at - now for campaign in self.inventory if campaign.starts_at > now
)
if period > (one_hour := timedelta(hours=1)):
period = one_hour
times = ceil(period.total_seconds() / 30 * 60)
period /= times
for i in range(times):
channel = self.watching_channel.get_with_default(None) channel = self.watching_channel.get_with_default(None)
# ensure every 30 minutes that we don't have unclaimed points bonus # ensure every ~20-30 minutes that we don't have unclaimed points bonus
if channel is not None: if channel is not None:
await channel.claim_bonus() await channel.claim_bonus()
await asyncio.sleep(30*60) await asyncio.sleep(period.total_seconds())
# this triggers this task restart every 60 minutes # this triggers this task restart every 60 minutes
self.change_state(State.INVENTORY_FETCH) self.change_state(State.INVENTORY_FETCH)
self._mnt_task = None
def can_watch(self, channel: Channel) -> bool: def can_watch(self, channel: Channel) -> bool:
""" """