Can a single Tornado RequestHandler
class attend new requests, while waiting for a Future
to finish in one of its instances?
I was debugging a Tornado coroutine that called a ThreadPoolExecutor
and I noticed that, while the coroutine was waiting for the executor to finish, the RequestHandler
was blocked. So any new requests to this handler where waiting for the coroutine to finish.
Here is the code I wrote to reproduce my observation:
from time import sleep
from concurrent.futures import ThreadPoolExecutor
from tornado.ioloop import IOLoop, PeriodicCallback
from tornado.web import Application, RequestHandler
from tornado.gen import coroutine
class Handler1(RequestHandler):
@coroutine
def get(self):
print('Setting up executor ...')
thread_pool = ThreadPoolExecutor(1)
print('Yielding ...')
yield thread_pool.submit(sleep, 30)
self.write('Ready!')
print('Finished!')
app = Application([('/1$', Handler1)])
app.listen(8888)
PeriodicCallback(lambda: print('##'), 10000).start()
IOLoop.instance().start()
Now, if I access localhost:8888/1
twice I get the following output:
##
Setting up executor ...
Yielding ...
##
##
##
Finished!
Setting up executor ...
Yielding ...
##
##
##
Finished!
##
But I would expect the following to occur:
##
Setting up executor ...
Yielding ...
Setting up executor ...
Yielding ...
##
##
##
Finished!
Finished!
##
Notice that only the RequestHandler
seems to be blocked, because we still get the ##
every 10 seconds. In fact if you add another identical RequestHandler
(Handler2) and you access localhost:8888/1
and localhost:8888/2
, this will produce the expected output.
Is this normal? Is this the intended behaviour?
Sorry for my bad English.