0

Does PeriodicCallback ensure no parallel executions? Is the callback triggered while a previous triggered one is still running or does it ensure that there is only one callback running at a time? As far as I can see the later one is true, but I want to be sure! I should control that time of asynchronous function is no longer than next periodiccallback scheduler.

For example:

If I have a periodiccallback every 5 seconds and my function time sometimes (because makes http request etc) is longer (for example 7 second), how can I jump the "10 second" and pass to 15? Only when it happens.

Cœur
  • 37,241
  • 25
  • 195
  • 267

1 Answers1

0

The tornado docs says

If the callback runs for longer than callback_time milliseconds, subsequent invocations will be skipped to get back on schedule.

So if I'm understanding your question correctly, PeriodicCallback already does exactly what you want if your callback is a synchronous function!

If your callback isn't synchronous, then you will need to use locks to check yourself if something is already running or not. Something like:

from tornado import gen, locks

lock = locks.Lock()
running = False
@gen.coroutine
def task():
    global running
    with (yield lock.acquire()):
        if running:
            return
        running = True
    try:
        yield do_something()
    finally:
        with (yield lock.acquire()):
            running = False

http://www.tornadoweb.org/en/stable/ioloop.html#tornado.ioloop.PeriodicCallback

Arthur
  • 4,093
  • 3
  • 17
  • 28
  • But is there a distinction for asyncronous function? In this case how periodicCallback can know if subsequent is finished or not? – Luca Palombella Mar 20 '18 at 09:51
  • Right, sorry, I missed the asynchronous part of your question. I have amended my answer how I would do it for asynchronous callbacks, but I haven't really tested it, so try it first… – Arthur Mar 20 '18 at 10:09
  • Ok i'll try it, thanks!. but where can i set the schedule timing? Task() function is started from periodicCallback? – Luca Palombella Mar 20 '18 at 10:34
  • yes, `task` is just a wrapper around your `do_something` coroutine that you can pass along to `PeriodicCallback` to schedule it – Arthur Mar 20 '18 at 10:36
  • Ok perfect so it can be: periodicCallback(task(), 5000) # every 5 seconds Task() {...} # called from periodic but only if do_something is finished do_something() {...} # function that do something (maybe longer than 5 seconds...) Correct? :) ps: nonlocal is global python statement? – Luca Palombella Mar 20 '18 at 10:39
  • yes exactly ; nonlocal should actually read `global` here, I'll amend my response – Arthur Mar 21 '18 at 15:45