summaryrefslogtreecommitdiff
path: root/apscheduler/triggers/base.py
blob: bbfabbdea475378a78c60838e4a97825603245c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from abc import ABCMeta, abstractmethod
from datetime import timedelta
import random


class BaseTrigger(metaclass=ABCMeta):
    """Abstract base class that defines the interface that every trigger must implement."""

    __slots__ = ()

    @abstractmethod
    def get_next_fire_time(self, previous_fire_time, now):
        """
        Returns the next datetime to fire on, If no such datetime can be calculated, returns
        ``None``.

        :param datetime.datetime previous_fire_time: the previous time the trigger was fired
        :param datetime.datetime now: current datetime
        """

    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``

        :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 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