parent
19d702e62a
commit
3e6e481a0f
@ -0,0 +1,118 @@
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from dateutil import tz
|
||||
import pytz
|
||||
|
||||
from apscheduler.triggers.cron import CronTrigger as APCronTrigger
|
||||
|
||||
from configspec import *
|
||||
import preserve
|
||||
|
||||
|
||||
class TaskTrigger(ABC):
|
||||
"""Abstract trigger class"""
|
||||
@abstractmethod
|
||||
def next_time(self, base_time):
|
||||
"""
|
||||
Return a time indicating the next trigger time after base_time. Return None if no more
|
||||
trigger events.
|
||||
"""
|
||||
|
||||
|
||||
@preserve.preservable(exclude_attrs=['ap_trigger'])
|
||||
class CronTrigger(TaskTrigger):
|
||||
"""
|
||||
Interprets Cron strings using a wrapper around the APScheduler CronTrigger (and so function
|
||||
is similar). Values left as default or supplied as None are set to a wildcard, unless it is
|
||||
a smaller unit than those supplied - where it instead gets set to it's minimum (so setting
|
||||
`hour` to 3 will set `minute` and `second` to 0).
|
||||
|
||||
The trigger format will be matched against
|
||||
The timezone used is always the local system timezone.
|
||||
|
||||
Details available at https://apscheduler.readthedocs.io/en/latest/modules/triggers/cron.html
|
||||
"""
|
||||
|
||||
def __init__(self, month=None, day=None, day_of_week=None, hour=None,
|
||||
minute=None, second=None):
|
||||
self.month = month
|
||||
self.day = day
|
||||
self.day_of_week = day_of_week
|
||||
self.hour = hour
|
||||
self.minute = minute
|
||||
self.second = second
|
||||
self.__restore_init__()
|
||||
|
||||
def __restore_init__(self):
|
||||
# Default timezone is the one from tzlocal
|
||||
self.ap_trigger = APCronTrigger(month=self.month, day=self.day,
|
||||
day_of_week=self.day_of_week,
|
||||
hour=self.hour, minute=self.minute,
|
||||
second=self.second)
|
||||
|
||||
def next_time(self, base_time):
|
||||
"""
|
||||
Return a time indicating the next trigger time after base_time. Return None if no more
|
||||
trigger events.
|
||||
"""
|
||||
# Convert base_time to UTC with dateutil, then to pytz which APScheduler requires.
|
||||
utc_base_time = base_time.astimezone(tz.tzutc()).astimezone(pytz.utc)
|
||||
fire_time = self.ap_trigger.get_next_fire_time(None, utc_base_time)
|
||||
# Convert back to UTC, as ap_trigger returns a value with local timezone
|
||||
# Use DateUtil, as it doesn't add other crap to tzinfo
|
||||
return fire_time.astimezone(pytz.utc).astimezone(tz.tzutc())
|
||||
|
||||
|
||||
TriggerSpec = ConfigSpecification()
|
||||
TriggerSpec.add_specs({
|
||||
'month': StringSpec(helptext="Month in year, 1-12"),
|
||||
'day': StringSpec(helptext="Day of month, 1-32"),
|
||||
'day_of_week': StringSpec(helptext="Day of week, 0-6 or mon,tue,wed,thu,fri,sat,sun"),
|
||||
'hour': StringSpec(helptext="Hour in day, 0-23"),
|
||||
'minute': StringSpec(helptext="Minute in hour, 0-59"),
|
||||
'second': StringSpec(helptext="Second in minute, 0-59"),
|
||||
}, optional=True)
|
||||
|
||||
|
||||
# class IntervalTrigger(TaskTrigger):
|
||||
"""
|
||||
Triggers every x period starting from when it was first created (carries over lowpower)
|
||||
"""
|
||||
# pass
|
||||
|
||||
|
||||
# class SingleTrigger(TaskTrigger):
|
||||
"""
|
||||
Either pass a whole datetime instance, or a delta like a period that gets added to current.
|
||||
"""
|
||||
# pass
|
||||
|
||||
|
||||
class Task():
|
||||
def __init__(self, trigger, interface_call):
|
||||
pass
|
||||
# InterfaceCall already handles the callables and args for us, we just need to preserve
|
||||
# them. Trigger is going to be multiple formats, but the most common will be Cron style.
|
||||
|
||||
|
||||
def init_tasks(core_config, applied_config, interface_functions):
|
||||
pass
|
||||
# Check if we have a session to load
|
||||
# Load the session - this includes resolving interfacecalls
|
||||
|
||||
# Return a list of tasks
|
||||
|
||||
|
||||
def start_tasks(task_list):
|
||||
pass
|
||||
# Start our scheduler thread to fire off tasks, including the initial grace period checks
|
||||
# Due to our task constraints, our scheduler can be somewhat simplified. We know that task
|
||||
# triggers won't change after init, and they will be infrequent enough that we can just
|
||||
# make a new thread for each task.
|
||||
|
||||
# Maybe have "cycles", where we determine what task is going to occur next, and when.
|
||||
# A main dispatch loop then pretty much delays until that point, or triggers the low power
|
||||
# stuff somehow.
|
||||
|
||||
# Does the low power stuff occur here? Or somewhere else?
|
||||
Loading…
Reference in new issue