mirror of https://github.com/janLo/punkow
Implement a timer to increase frequency at special times
This commit is contained in:
parent
9510fbedec
commit
f3763a3d29
|
|
@ -0,0 +1,91 @@
|
||||||
|
import asyncio
|
||||||
|
import contextlib
|
||||||
|
import datetime
|
||||||
|
import logging
|
||||||
|
import typing
|
||||||
|
|
||||||
|
import croniter
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class TimeStream(object):
|
||||||
|
def __init__(self, timespec, now):
|
||||||
|
self._spec = timespec
|
||||||
|
self._iter = croniter.croniter(timespec, now)
|
||||||
|
self._special_window = datetime.timedelta(minutes=10)
|
||||||
|
|
||||||
|
self._prev = self._iter.get_prev(datetime.datetime)
|
||||||
|
self._next = self._iter.get_next(datetime.datetime)
|
||||||
|
|
||||||
|
def is_between(self, now: datetime.datetime) -> bool:
|
||||||
|
|
||||||
|
while now > self._next:
|
||||||
|
self._prev = self._next
|
||||||
|
self._next = self._iter.get_next(datetime.datetime)
|
||||||
|
|
||||||
|
while now < self._prev:
|
||||||
|
self._next = self._prev
|
||||||
|
self._prev = self._iter.get_prev(datetime.datetime)
|
||||||
|
|
||||||
|
if now - self._special_window < self._prev:
|
||||||
|
logger.debug("Less than 10 minutes since %s -> increase interval", self._prev.isoformat())
|
||||||
|
return True
|
||||||
|
|
||||||
|
if now + self._special_window > self._next:
|
||||||
|
logger.debug("Less than 10 minutes to %s -> increase interval", self._next.isoformat())
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class Timer(object):
|
||||||
|
def __init__(self, interval: float = 5 * 60,
|
||||||
|
special_times: typing.List[str] = None,
|
||||||
|
time_zone: str = 'CET'):
|
||||||
|
self._interval = interval
|
||||||
|
self._special_times = [] # type: typing.List[TimeStream]
|
||||||
|
self._time_zone = pytz.timezone(time_zone)
|
||||||
|
|
||||||
|
now = self._now()
|
||||||
|
|
||||||
|
for line in special_times:
|
||||||
|
if not croniter.croniter.is_valid(line):
|
||||||
|
logger.warning("Special time definition '%s' not valid. Ignoring!")
|
||||||
|
else:
|
||||||
|
self._special_times.append(TimeStream(line, now))
|
||||||
|
|
||||||
|
def _now(self) -> datetime.datetime:
|
||||||
|
utc_now = pytz.utc.localize(datetime.datetime.utcnow())
|
||||||
|
return utc_now.astimezone(self._time_zone)
|
||||||
|
|
||||||
|
def _wait_time(self, now):
|
||||||
|
for special in self._special_times:
|
||||||
|
if special.is_between(now):
|
||||||
|
return 1
|
||||||
|
return self._interval
|
||||||
|
|
||||||
|
@contextlib.asynccontextmanager
|
||||||
|
async def timed(self):
|
||||||
|
start = self._now()
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
end = self._now()
|
||||||
|
elapsed = (end - start).total_seconds()
|
||||||
|
sleep = max(0.0, self._wait_time(end) - elapsed)
|
||||||
|
logger.debug("Booking run completed in %0.2f seconds - now sleep for %0.2f seconds", elapsed, sleep)
|
||||||
|
await asyncio.sleep(sleep)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
t = Timer(20, ["0 0 * * *"])
|
||||||
|
z = pytz.timezone("CET")
|
||||||
|
d = datetime.datetime(2019, 1, 17, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
for i in range(40):
|
||||||
|
tm = d + datetime.timedelta(minutes=i-20)
|
||||||
|
|
||||||
|
inte = t._wait_time(z.localize(tm))
|
||||||
|
print(tm.isoformat(), inte)
|
||||||
Loading…
Reference in New Issue