|
|
|
|
@ -18,7 +18,7 @@ from apscheduler.triggers.cron import CronTrigger as APCronTrigger
|
|
|
|
|
from configspec import *
|
|
|
|
|
import preserve
|
|
|
|
|
|
|
|
|
|
from .util import HoldLock
|
|
|
|
|
# from .util import HoldLock
|
|
|
|
|
|
|
|
|
|
log = logging.getLogger("shepherd.agent.tasks")
|
|
|
|
|
|
|
|
|
|
@ -98,8 +98,8 @@ class CronTrigger(TaskTrigger):
|
|
|
|
|
return fire_time.astimezone(pytz.utc).astimezone(tz.tzutc())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TriggerSpec = ConfigSpecification()
|
|
|
|
|
TriggerSpec.add_specs({
|
|
|
|
|
CronTriggerSpec = ConfigSpecification()
|
|
|
|
|
CronTriggerSpec.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"),
|
|
|
|
|
@ -326,27 +326,7 @@ def _tasks_update_loop(config, suspend_hook, session):
|
|
|
|
|
|
|
|
|
|
_update_thread_init_done.clear()
|
|
|
|
|
|
|
|
|
|
# Right, so we have our task list, and calls have been resolved. Assume that any waiting period
|
|
|
|
|
# for control has already been handled.
|
|
|
|
|
|
|
|
|
|
# Eventually also need a system to wait for time to stabilise (hook?)
|
|
|
|
|
|
|
|
|
|
# What do we do when task list is empty? Return directly?
|
|
|
|
|
|
|
|
|
|
# That list then gets sorted by that time, and the main loop simply waits for the next scheduled
|
|
|
|
|
# time to pass before calling the task (on a different thread). The scheduled_for time gets updated,
|
|
|
|
|
# the scheduled_tasks list gets sorted again. The loop then looks at the next task, probably with
|
|
|
|
|
# some log if "scheduled_for" is too far in the past, but run the task anyway.
|
|
|
|
|
|
|
|
|
|
# Lowpower handling can then be in the section of the cycle where we'd otherwise be doing a delay.
|
|
|
|
|
# Have a minimum sleep delay (10ms or something), so we can have a task only run if it's past
|
|
|
|
|
# the scheduled_for, and then we can happily use that time to get the _next_ trigger time.
|
|
|
|
|
|
|
|
|
|
# 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.
|
|
|
|
|
# TODO Handle case when tasks return None as next trigger time, and when no triggers are left
|
|
|
|
|
# TODO Add maximum suspend period
|
|
|
|
|
# TODO Add "snooze" task checking even on new session, to catch tasks we miss if we restart
|
|
|
|
|
# due to new config
|
|
|
|
|
|