summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Grönholm <alex.gronholm@nextday.fi>2020-01-11 17:55:36 +0200
committerAlex Grönholm <alex.gronholm@nextday.fi>2020-01-11 19:46:31 +0200
commit9551c5b26191e118e29bd7341e04a9c3cda06af0 (patch)
tree3eef459148edf2526457889721e41bf548561039
parentc12305a8bdd26169094fd1d71d3cd95a6e5f25ac (diff)
downloadapscheduler-jitterfix.tar.gz
Ensured that jitter is always positivejitterfix
Fixes #291.
-rw-r--r--apscheduler/triggers/base.py19
-rw-r--r--docs/versionhistory.rst7
-rw-r--r--tests/test_triggers.py20
3 files changed, 11 insertions, 35 deletions
diff --git a/apscheduler/triggers/base.py b/apscheduler/triggers/base.py
index ce2526a..55d010d 100644
--- a/apscheduler/triggers/base.py
+++ b/apscheduler/triggers/base.py
@@ -22,27 +22,16 @@ class BaseTrigger(six.with_metaclass(ABCMeta)):
def _apply_jitter(self, next_fire_time, jitter, now):
"""
- Randomize ``next_fire_time`` by adding or subtracting a random value (the jitter). If the
- resulting datetime is in the past, returns the initial ``next_fire_time`` without jitter.
-
- ``next_fire_time - jitter <= result <= next_fire_time + jitter``
+ Randomize ``next_fire_time`` by adding a random value (the jitter).
:param datetime.datetime|None next_fire_time: next fire time without jitter applied. If
``None``, returns ``None``.
- :param int|None jitter: maximum number of seconds to add or subtract to
- ``next_fire_time``. If ``None`` or ``0``, returns ``next_fire_time``
+ :param int|None jitter: maximum number of seconds to add to ``next_fire_time``
+ (if ``None`` or ``0``, returns ``next_fire_time``)
:param datetime.datetime now: current datetime
:return datetime.datetime|None: next fire time with a jitter.
"""
if next_fire_time is None or not jitter:
return next_fire_time
- next_fire_time_with_jitter = next_fire_time + timedelta(
- seconds=random.uniform(-jitter, jitter))
-
- if next_fire_time_with_jitter < now:
- # Next fire time with jitter is in the past.
- # Ignore jitter to avoid false misfire.
- return next_fire_time
-
- return next_fire_time_with_jitter
+ return next_fire_time + timedelta(seconds=random.uniform(0, jitter))
diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst
index 79a40f7..bf33e4b 100644
--- a/docs/versionhistory.rst
+++ b/docs/versionhistory.rst
@@ -4,6 +4,13 @@ Version history
To find out how to migrate your application from a previous version of
APScheduler, see the :doc:`migration section <migration>`.
+UNRELEASED
+----------
+
+* Ensure that jitter is always non-negative to prevent triggers from firing more often than
+ intended
+
+
3.6.3
-----
diff --git a/tests/test_triggers.py b/tests/test_triggers.py
index a637485..ea0d1c1 100644
--- a/tests/test_triggers.py
+++ b/tests/test_triggers.py
@@ -50,16 +50,6 @@ class TestJitter(object):
trigger = _DummyTriggerWithJitter(dt, 60)
assert trigger.get_next_fire_time(None, now) == expected_dt
- def test_jitter_in_past_but_initial_date_in_future(self, monkeypatch):
- monkeypatch.setattr(random, 'uniform', lambda a, b: -30.)
-
- now = datetime(2017, 5, 25, 13, 40, 44)
- dt = datetime(2017, 5, 25, 13, 40, 47)
- expected_dt = dt
-
- trigger = _DummyTriggerWithJitter(dt, 60)
- assert trigger.get_next_fire_time(None, now) == expected_dt
-
def test_jitter_in_future_but_initial_date_in_past(self, monkeypatch):
monkeypatch.setattr(random, 'uniform', lambda a, b: 30.)
@@ -70,16 +60,6 @@ class TestJitter(object):
trigger = _DummyTriggerWithJitter(dt, 60)
assert trigger.get_next_fire_time(None, now) == expected_dt
- def test_jitter_misfire(self, monkeypatch):
- monkeypatch.setattr(random, 'uniform', lambda a, b: -30.)
-
- now = datetime(2017, 5, 25, 13, 40, 44)
- dt = datetime(2017, 5, 25, 13, 40, 40)
- expected_dt = dt
-
- trigger = _DummyTriggerWithJitter(dt, 60)
- assert trigger.get_next_fire_time(None, now) == expected_dt
-
def test_jitter_is_now(self, monkeypatch):
monkeypatch.setattr(random, 'uniform', lambda a, b: 4.)