apscheduler icon indicating copy to clipboard operation
apscheduler copied to clipboard

Problem on combining triggers

Open masoudr opened this issue 6 years ago • 4 comments

Hi, I'm trying to use combine triggers. For example, I want to run a function on the first minute for every 2 seconds:

from time import sleep
from apscheduler.triggers.combining import AndTrigger
from apscheduler.triggers.interval import IntervalTrigger
from apscheduler.triggers.cron import CronTrigger
from apscheduler.schedulers.background import BackgroundScheduler


def job_function():
    print("hello from function")


if __name__ == "__main__":
    scheduler = BackgroundScheduler()
    trigger = AndTrigger([IntervalTrigger(seconds=2),
                          CronTrigger(minute=1)])
    scheduler.add_job(job_function, trigger)
    print("before start", scheduler.get_jobs())
    scheduler.start()
    print("after start", scheduler.get_jobs())
    print("ok")
    while True:
        sleep(.1)

But the program never prints after start. It is very strange to me. The OrTrigger works fine for this example. If it is a bug is there any workaround?

masoudr avatar May 13 '18 03:05 masoudr

You're not the first one to run into this issue. This happens because the times generated by the two triggers never coincide because IntervalTrigger starts from the current time which of course has milliseconds that are unlikely to be exact 0, while CronTrigger produces datetimes with the fractional part as 0. The question is, how to resolve this? Should CronTrigger ignore the fractional part when comparing datetimes, or should IntervalTrigger's start time drop the millisecond part?

agronholm avatar May 13 '18 21:05 agronholm

Thanks, I tried a method that creates two jobs. first with a cron job as expected. In the cron job itself, it creates an interval job and the job destroyed after a specific amount of runs (I added this by myself manually). Here is my example, I want to run my function on the 10th day of each month on 10:0:0 on every 10 seconds for 6 times. If each call of my function takes less than 10 seconds. on 10:1:0 the interval should end. Is there any way to do this with combining triggers or what I've done is the best I can do?

masoudr avatar May 15 '18 12:05 masoudr

Why not just: day=10, hour=10, second='*/10'?

agronholm avatar May 15 '18 16:05 agronholm

You are right but how about adding a limitation on the amount of function runs like run only for 6 times only, how can I implement that?

masoudr avatar May 16 '18 04:05 masoudr

The proper solution would have been to use CronTrigger(minute=1, second="*/2"). v4.0.0a1 also includes a threshold parameter for AndTrigger which can be used to solve the issue of the trigger run times not matching exactly.

agronholm avatar Aug 17 '22 21:08 agronholm