mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-16 22:43:00 +00:00
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:
@@ -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,9 +96,12 @@ 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"""
|
||||||
yield wait_for_server(self.ip or 'localhost', self.port, timeout=timeout)
|
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)
|
||||||
|
|
||||||
def is_up(self):
|
def is_up(self):
|
||||||
"""Is the server accepting connections?"""
|
"""Is the server accepting connections?"""
|
||||||
@@ -323,8 +326,8 @@ class User(Base):
|
|||||||
self.state = spawner.get_state()
|
self.state = spawner.get_state()
|
||||||
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
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user