schedule icon indicating copy to clipboard operation
schedule copied to clipboard

at_multiple_of and force_missed_run

Open TanJeremy opened this issue 4 years ago • 2 comments

Hello I made this Override over your Classes, I Share it in case you want to implement it:

class CustomScheduler(Scheduler):
    def __init__(self):
        super(CustomScheduler, self).__init__()

    def at_multiple_of(self, interval):
        """
        Schedule a new periodic job.

        :param interval: A quantity of a certain time unit
        :return: An unconfigured :class:`Job <Job>`
        """
        job = CustomJob(interval, self)
        job.run_at_multiple_of = True
        return job


class CustomJob(Job):
    def __init__(self, interval, scheduler=None):
        super(CustomJob, self).__init__(interval, scheduler)
        self.run_at_multiple_of = False
        self._force_missed_run = False
        self.future_run = None

    @property
    def force_missed_run(self):
        self._force_missed_run = True
        return self

    @property
    def modulo(self):
        if self.unit == "minutes":
            return self.next_run.minute % self.interval
        if self.unit == "hours":
            return self.next_run.hour % self.interval
        if self.unit == "days":
            return self.next_run.day % self.interval

    def _schedule_next_run(self):
        super(CustomJob, self)._schedule_next_run()

        if self.latest is None and self.run_at_multiple_of:
            if self.modulo != 0:
                self.next_run -= datetime.timedelta(**{self.unit: self.modulo})

        if self.future_run and self.future_run < self.next_run and self._force_missed_run:
            self.next_run, self.future_run = self.future_run, self.next_run
        else:
            self.future_run = self.next_run + self.period

I implemented 2 features:

  • at_multiple_of

    :warning: If the unit is not divisible by your multiple: ex : 60 minutes are not divisible by 7, it will be scheduled at: 00:00, 00:07, 00:14, 00:21, 00:28, 00:35, 00:42, 00:49, 00:56 and 01:00 and not 01:03

    exemple with every:

    schedule.every(5).minutes.at(":01").do(do_something)
    

    results:

    Launched at 13:33:52
    Start at 13:38:01
    Start at 13:43:01
    Start at 13:48:01
    

    exemple with at_multiple_of:

    schedule.at_multiple_of(5).minutes.at(":01").do(do_something_at_multiple)
    

    results:

    Launched at 13:33:52
    Start at 13:35:01
    Start at 13:40:01
    Start at 13:45:01
    
  • force_missed_run Re execute a job that missed a run (when a job took longer than the periode) exemple :

    schedule.every().minutes.at(":01").do(do_something)
    

    results:

    Launched at 13:33:52
    Start at 13:34:01
    Done at 13:35:10
    Start at 13:36:01
    Done at 13:37:10
    Start at 13:38:01
    
    schedule.every().minutes.at(":01").force_missed_run.do(do_something)
    

    results:

    Launched at 13:33:52
    Start at 13:34:01
    Done at 13:34:10
    Start at 13:34:10
    Done at 13:35:21
    Start at 13:35:21
    

PS: The Architecture of this Library is awesome, It's simple but really effective and user-friendly Great Job!

TanJeremy avatar Apr 05 '21 12:04 TanJeremy

great job

AYiXi avatar Apr 15 '21 06:04 AYiXi

Great job! This could be quite a nice addition to the docs :+1:

SijmenHuizenga avatar May 20 '21 17:05 SijmenHuizenga