jaraco / tempora

MIT License
20 stars 5 forks source link

Does precision depend on frequency of an event loop? #14

Closed andrewgin closed 3 years ago

andrewgin commented 3 years ago

This isn't a bug as such, but I saw your comment on here https://github.com/dbader/schedule/pull/16 regarding timezone aware scheduling of functions and you suggested tempora should be able to do the job

I'm not sure how to use the functionality; Once I create a command, eg run do_stuff every day at 12:15 with

when = datetime.time(12, 15, tzinfo=pytz.utc)
cmd = schedule.PeriodicCommandFixedDelay.daily_at(
    when,
    target=do_stuff(),
)

I would then register the command with the scheduler with

sched = schedule.InvokeScheduler()
sched.add(cmd)

Then to actually invoke the scheduler, I'd need to have the following in an event thread of some sort?

while True:
    sched.run_pending()
    time.sleep(600)

So for example if my event loop only ran every 10 mins, I wouldn't actually be guaranteed do_stuff would run at exactly 12:15pm, have I got that correct?

Would cron be a better tool for this use case?

Thanks

jaraco commented 3 years ago

Great question.

have I got that correct?

Yes, but you could change it to sleep(0.1) or sleep(1) and it would work as you intend.

The scheduler provided by tempora was extracted from the irc package, which itself had a primitive event loop, where it would "run forever", periodically triggering scheduled items. Your event loop to run_pending periodically is a suitable approach, though I would recommend a suitable sleep period to allow the run_pending to run happen frequently enough that the scheduled items happen close to their scheduled time.

For example, if you knew that your scheduler never got items scheduled sooner than the next item in the scheduler, you could do something like:

while True:
    sched.run_pending()
    time.sleep((sched.queue[0] - utc.now()).total_seconds()))

Or if you're using an event loop from some other event system, you could hook into that event system to schedule a call to run_pending or to simply call the commands when they become due.

Perhaps you could describe a little bit more about what you're trying to achieve and I could put together a more concrete example.

andrewgin commented 3 years ago

I'm looking for a way to run execute a function that pulls data from an API at certain times of the day (eg 9:30am eastern time every weekday) as part of a larger web application. I thought if I can bundle the scheduler mechanism into the application itself instead of using cron, it means one less thing to do for the person setting it up.

Thinking about it a bit more I think perhaps cron might be the better option in this case because if I scale up my application to have multiple instances running, I will also get multiple instances of the scheduled task running as well. Whereas if I used cron, I can have multiple instances of the web app running and a single cron instance to look after the scheduled data pull.

I suppose this can be closed now as you've confirmed that is the correct way to invoke the scheduled tasks.

Thanks