wait for HTTP servers to start accepting requests

avoids error messages in the proxy when servers are slow to start.
This commit is contained in:
MinRK
2014-10-14 14:39:53 -07:00
parent 2991468a32
commit 08fd76d1e8
2 changed files with 38 additions and 6 deletions

View File

@@ -26,7 +26,7 @@ from sqlalchemy import create_engine
from IPython.utils.py3compat import str_to_unicode from IPython.utils.py3compat import str_to_unicode
from .utils import random_port, url_path_join, wait_for_server from .utils import random_port, url_path_join, wait_for_server, wait_for_http_server
def new_token(*args, **kwargs): def new_token(*args, **kwargs):
@@ -96,8 +96,11 @@ class Server(Base):
) )
@gen.coroutine @gen.coroutine
def wait_up(self, timeout=10): def wait_up(self, timeout=10, http=False):
"""Wait for this server to come up""" """Wait for this server to come up"""
if http:
yield wait_for_http_server(self.url.replace('//*', '//localhost'), timeout=timeout)
else:
yield wait_for_server(self.ip or 'localhost', self.port, timeout=timeout) yield wait_for_server(self.ip or 'localhost', self.port, timeout=timeout)
def is_up(self): def is_up(self):
@@ -324,7 +327,7 @@ class User(Base):
self.last_activity = datetime.utcnow() self.last_activity = datetime.utcnow()
db.commit() db.commit()
yield self.server.wait_up() yield self.server.wait_up(http=True)
raise gen.Return(self) raise gen.Return(self)
@gen.coroutine @gen.coroutine

View File

@@ -8,6 +8,7 @@ import errno
import os import os
import socket import socket
from tornado import web, gen, ioloop from tornado import web, gen, ioloop
from tornado.httpclient import HTTPRequest, AsyncHTTPClient, HTTPError
from tornado.log import app_log from tornado.log import app_log
from IPython.html.utils import url_path_join from IPython.html.utils import url_path_join
@@ -41,7 +42,7 @@ def random_hex(nbytes):
@gen.coroutine @gen.coroutine
def wait_for_server(ip, port, timeout=10): def wait_for_server(ip, port, timeout=10):
"""wait for a server to show up at ip:port""" """wait for any server to show up at ip:port"""
loop = ioloop.IOLoop.current() loop = ioloop.IOLoop.current()
tic = loop.time() tic = loop.time()
while loop.time() - tic < timeout: while loop.time() - tic < timeout:
@@ -57,6 +58,34 @@ def wait_for_server(ip, port, timeout=10):
return return
raise TimeoutError raise TimeoutError
@gen.coroutine
def wait_for_http_server(url, timeout=10):
"""Wait for an HTTP Server to respond at url
Any non-5XX response code will do, even 404.
"""
loop = ioloop.IOLoop.current()
tic = loop.time()
client = AsyncHTTPClient()
while loop.time() - tic < timeout:
try:
r = yield client.fetch(url, follow_redirects=False)
except HTTPError as e:
if e.code >= 500:
# failed to respond properly, wait and try again
if e.code != 599:
# we expect 599 for no connection,
# but 502 or other proxy error is conceivable
app_log.warn("Server at %s responded with error: %s", url, e.code)
yield gen.Task(loop.add_timeout, loop.time() + 0.25)
else:
app_log.debug("Server at %s responded with %s", url, e.code)
return
else:
return
raise TimeoutError
def auth_decorator(check_auth): def auth_decorator(check_auth):
"""Make an authentication decorator """Make an authentication decorator