When a job is disabled only increase it's _next_fire_time value if th…e job would have run at the current time, eg. the current _next_fire_time == now.

This commit is contained in:
Gareth J. Greenaway 2023-03-14 09:20:35 -07:00 committed by Pedro Algarvio
parent 326cb8d35b
commit 8901ff57d9
4 changed files with 208 additions and 12 deletions

1
changelog/63699.fixed.md Normal file
View file

@ -0,0 +1 @@
When a job is disabled only increase it's _next_fire_time value if the job would have run at the current time, eg. the current _next_fire_time == now.

View file

@ -217,11 +217,12 @@ class Schedule:
if remove_hidden:
_schedule = copy.deepcopy(schedule)
for job in _schedule:
if isinstance(_schedule[job], dict):
for item in _schedule[job]:
for job in schedule:
if isinstance(schedule[job], dict):
for item in schedule[job]:
if item.startswith("_"):
del schedule[job][item]
del _schedule[job][item]
return _schedule
return schedule
def _check_max_running(self, func, data, opts, now):
@ -1769,9 +1770,10 @@ class Schedule:
seconds=data["_seconds"]
)
elif "_skipped" in data and data["_skipped"]:
data["_next_fire_time"] = now + datetime.timedelta(
seconds=data["_seconds"]
)
if data["_next_fire_time"] <= now:
data["_next_fire_time"] = now + datetime.timedelta(
seconds=data["_seconds"]
)
elif run:
data["_next_fire_time"] = now + datetime.timedelta(
seconds=data["_seconds"]

View file

@ -502,6 +502,146 @@ def test_eval_disabled(schedule):
assert ret == job["schedule"][job_name]
def test_eval_disabled_seconds(schedule):
"""
verify that scheduled job does not run
"""
job_name = "test_eval_disabled_seconds"
job = {
"schedule": {
"enabled": True,
job_name: {"function": "test.ping", "seconds": "30"},
}
}
# Add the job to the scheduler
schedule.opts.update(job)
eval_time1 = dateutil.parser.parse("11/29/2017 4:00pm")
schedule.eval(now=eval_time1)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 16, 0, 30)
# Disable the job
schedule.opts["schedule"]["enabled"] = False
# Evaluate 1 second for 29 seconds
# Assert that the _next_fire_time does not change
# until the _next_fire_time is reached
for i in range(1, 30):
eval_time = eval_time1 + datetime.timedelta(seconds=i)
schedule.eval(now=eval_time)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 16, 0, 30)
eval_time = eval_time1 + datetime.timedelta(seconds=30)
schedule.eval(now=eval_time)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 16, 1, 0)
def test_eval_disabled_minutes(schedule):
"""
verify that scheduled job does not run
"""
job_name = "test_eval_disabled_minutes"
job = {
"schedule": {
"enabled": True,
job_name: {"function": "test.ping", "minutes": "55"},
}
}
# Add the job to the scheduler
schedule.opts.update(job)
eval_time1 = dateutil.parser.parse("11/29/2017 4:00pm")
schedule.eval(now=eval_time1)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 16, 55, 0)
# Evaluate 1 minute for 50 minutes
# Assert that the _next_fire_time does not change
# until the _next_fire_time is reached
for i in range(1, 50):
eval_time = eval_time1 + datetime.timedelta(minutes=i)
schedule.eval(now=eval_time)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 16, 55, 0)
# Disable the job
schedule.opts["schedule"]["enabled"] = False
for i in range(1, 10):
eval_time = eval_time1 + datetime.timedelta(seconds=i)
schedule.eval(now=eval_time)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 16, 55, 0)
eval_time = dateutil.parser.parse("11/29/2017 4:55pm")
schedule.eval(now=eval_time)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 17, 50, 0)
def test_eval_disabled_hours(schedule):
"""
verify that scheduled job does not run
"""
job_name = "test_eval_disabled_hours"
job = {
"schedule": {
"enabled": True,
job_name: {"function": "test.ping", "hours": "6"},
}
}
# Add the job to the scheduler
schedule.opts.update(job)
eval_time1 = dateutil.parser.parse("11/29/2017 4:00pm")
schedule.eval(now=eval_time1)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 22, 0, 0)
# Evaluate 1 hour for 5 hours
# Assert that the _next_fire_time does not change
# until the _next_fire_time is reached
for i in range(1, 5):
eval_time = eval_time1 + datetime.timedelta(hours=i)
schedule.eval(now=eval_time)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 22, 0, 0)
# Disable the job
schedule.opts["schedule"]["enabled"] = False
for i in range(1, 50):
eval_time = eval_time1 + datetime.timedelta(minutes=i)
schedule.eval(now=eval_time)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 29, 22, 0, 0)
eval_time = dateutil.parser.parse("11/29/2017 10:00pm")
schedule.eval(now=eval_time)
ret = schedule.job_status(job_name)
assert "_next_fire_time" in ret
assert ret["_next_fire_time"] == datetime.datetime(2017, 11, 30, 4, 0, 0)
def test_eval_global_disabled_job_enabled(schedule):
"""
verify that scheduled job does not run

View file

@ -1,24 +1,77 @@
import copy
import datetime
import logging
log = logging.getLogger(__name__)
def test_get_schedule(schedule):
def test_get_schedule_remove_hidden_true(schedule):
"""
verify that the _get_schedule function works
when remove_hidden is True and schedule data
contains enabled key
contains enabled key and that opts["schedule"]
is not changed.
"""
job_name = "test_get_schedule"
job = {
"schedule": {
"enabled": True,
job_name: {"function": "test.ping", "seconds": 60},
job_name: {
"function": "test.ping",
"seconds": 60,
"_next_fire_time": datetime.datetime(2023, 2, 13, 18, 25, 16, 271796),
"_splay": None,
"_seconds": 3600,
"_next_scheduled_fire_time": datetime.datetime(
2023, 2, 13, 18, 25, 16, 271796
),
"_skip_reason": "disabled",
"_skipped_time": datetime.datetime(2023, 2, 13, 17, 26, 16, 271381),
"_skipped": True,
},
}
}
expected_ret = {
"enabled": True,
job_name: {"function": "test.ping", "seconds": 60},
}
# Add the job to the scheduler
schedule.opts.update(copy.deepcopy(job))
ret = schedule._get_schedule(remove_hidden=True)
assert expected_ret == ret
assert schedule.opts["schedule"][job_name] == job["schedule"][job_name]
def test_get_schedule_remove_hidden_false(schedule):
"""
verify that the _get_schedule function works
when remove_hidden is False and schedule data
contains enabled key and that opts["schedule"]
is not changed.
"""
job_name = "test_get_schedule"
job = {
"schedule": {
"enabled": True,
job_name: {
"function": "test.ping",
"seconds": 60,
"_next_fire_time": datetime.datetime(2023, 2, 13, 18, 25, 16),
"_splay": None,
"_seconds": 3600,
"_next_scheduled_fire_time": datetime.datetime(2023, 2, 13, 18, 25, 16),
"_skip_reason": "disabled",
"_skipped_time": datetime.datetime(2023, 2, 13, 17, 26, 16),
"_skipped": True,
},
}
}
# Add the job to the scheduler
schedule.opts.update(job)
schedule.opts.update(copy.deepcopy(job))
ret = schedule._get_schedule(remove_hidden=True)
ret = schedule._get_schedule(remove_hidden=False)
assert job["schedule"] == ret