Created
December 2, 2016 07:59
-
-
Save wixb50/a529221465e5420f8c2c85314ef81379 to your computer and use it in GitHub Desktop.
"timeout” a Request in Tornado.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import contextlib | |
from tornado.ioloop import IOLoop | |
import tornado.web | |
from tornado import gen | |
@gen.coroutine | |
def async_sleep(timeout): | |
yield gen.Task(IOLoop.instance().add_timeout, time.time() + timeout) | |
@contextlib.contextmanager | |
def auto_timeout(self, timeout=2): # Seconds | |
handle = IOLoop.instance().add_timeout(time.time() + timeout, self.timed_out) | |
try: | |
yield handle | |
except Exception as e: | |
print("Caught %s" % e) | |
finally: | |
IOLoop.instance().remove_timeout(handle) | |
if not self._timed_out: | |
self.finish() | |
else: | |
raise Exception("Request timed out") # Don't continue on passed this point | |
class TimeoutableHandler(tornado.web.RequestHandler): | |
def initialize(self): | |
self._timed_out = False | |
def timed_out(self): | |
self._timed_out = True | |
self.write("Request timed out!\n") | |
self.finish() # Connection to client closes here. | |
# You might want to do other clean up here. | |
class MainHandler(TimeoutableHandler): | |
@gen.coroutine | |
def get(self): | |
with auto_timeout(self): # We'll timeout after 2 seconds spent in this block. | |
self.sleeper = async_sleep(5) | |
yield self.sleeper | |
print("writing") # get will abort before we reach here if we timed out. | |
self.write("hey\n") | |
def on_connection_close(self): | |
# This isn't the greatest way to cancel a future, since it will not actually | |
# stop the work being done asynchronously. You'll need to cancel that some | |
# other way. Should be pretty straightforward with a DB connection (close | |
# the cursor/connection, maybe?) | |
self.sleeper.set_exception(Exception("cancelled")) | |
application = tornado.web.Application([ | |
(r"/test", MainHandler), | |
]) | |
application.listen(8888) | |
IOLoop.instance().start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment