Skip to content

Commit

Permalink
Merge f6d8cf2 into 3e20570
Browse files Browse the repository at this point in the history
  • Loading branch information
agronholm committed Jan 11, 2020
2 parents 3e20570 + f6d8cf2 commit 56b440c
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 35 deletions.
19 changes: 4 additions & 15 deletions apscheduler/triggers/base.py
Expand Up @@ -22,27 +22,16 @@ def get_next_fire_time(self, previous_fire_time, now):

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))
7 changes: 7 additions & 0 deletions docs/versionhistory.rst
Expand Up @@ -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
-----

Expand Down
20 changes: 0 additions & 20 deletions tests/test_triggers.py
Expand Up @@ -50,16 +50,6 @@ def test_jitter_positive(self, monkeypatch):
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.)

Expand All @@ -70,16 +60,6 @@ def test_jitter_in_future_but_initial_date_in_past(self, monkeypatch):
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.)

Expand Down

0 comments on commit 56b440c

Please sign in to comment.