mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-16 06:22:59 +00:00
make app initialize/start async
avoids need for run_sync
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
# Copyright (c) Jupyter Development Team.
|
# Copyright (c) Jupyter Development Team.
|
||||||
# Distributed under the terms of the Modified BSD License.
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
|
import atexit
|
||||||
import binascii
|
import binascii
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@@ -492,6 +493,7 @@ class JupyterHub(Application):
|
|||||||
|
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
|
@gen.coroutine
|
||||||
def init_users(self):
|
def init_users(self):
|
||||||
"""Load users into and from the database"""
|
"""Load users into and from the database"""
|
||||||
db = self.db
|
db = self.db
|
||||||
@@ -543,15 +545,10 @@ class JupyterHub(Application):
|
|||||||
# From this point on, any user changes should be done simultaneously
|
# From this point on, any user changes should be done simultaneously
|
||||||
# to the whitelist set and user db, unless the whitelist is empty (all users allowed).
|
# to the whitelist set and user db, unless the whitelist is empty (all users allowed).
|
||||||
|
|
||||||
# load any still-active spawners from JSON
|
|
||||||
current = IOLoop.current()
|
|
||||||
loop = IOLoop()
|
|
||||||
loop.make_current()
|
|
||||||
run_sync = loop.run_sync
|
|
||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
for user in new_users:
|
for user in new_users:
|
||||||
loop.run_sync(lambda : self.authenticator.add_user(user))
|
yield self.authenticator.add_user(user)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
user_summaries = ['']
|
user_summaries = ['']
|
||||||
@@ -582,7 +579,7 @@ class JupyterHub(Application):
|
|||||||
user.spawner = spawner = self.spawner_class(
|
user.spawner = spawner = self.spawner_class(
|
||||||
user=user, hub=self.hub, config=self.config,
|
user=user, hub=self.hub, config=self.config,
|
||||||
)
|
)
|
||||||
status = run_sync(spawner.poll)
|
status = yield spawner.poll()
|
||||||
if status is None:
|
if status is None:
|
||||||
self.log.info("%s still running", user.name)
|
self.log.info("%s still running", user.name)
|
||||||
spawner.add_poll_callback(user_stopped, user)
|
spawner.add_poll_callback(user_stopped, user)
|
||||||
@@ -599,7 +596,6 @@ class JupyterHub(Application):
|
|||||||
|
|
||||||
self.log.debug("Loaded users: %s", '\n'.join(user_summaries))
|
self.log.debug("Loaded users: %s", '\n'.join(user_summaries))
|
||||||
db.commit()
|
db.commit()
|
||||||
current.make_current()
|
|
||||||
|
|
||||||
def init_proxy(self):
|
def init_proxy(self):
|
||||||
"""Load the Proxy config into the database"""
|
"""Load the Proxy config into the database"""
|
||||||
@@ -738,6 +734,7 @@ class JupyterHub(Application):
|
|||||||
with open(self.pid_file, 'w') as f:
|
with open(self.pid_file, 'w') as f:
|
||||||
f.write('%i' % pid)
|
f.write('%i' % pid)
|
||||||
|
|
||||||
|
@gen.coroutine
|
||||||
@catch_config_error
|
@catch_config_error
|
||||||
def initialize(self, *args, **kwargs):
|
def initialize(self, *args, **kwargs):
|
||||||
super().initialize(*args, **kwargs)
|
super().initialize(*args, **kwargs)
|
||||||
@@ -760,7 +757,7 @@ class JupyterHub(Application):
|
|||||||
self.init_db()
|
self.init_db()
|
||||||
self.init_hub()
|
self.init_hub()
|
||||||
self.init_proxy()
|
self.init_proxy()
|
||||||
self.init_users()
|
yield self.init_users()
|
||||||
self.init_handlers()
|
self.init_handlers()
|
||||||
self.init_tornado_settings()
|
self.init_tornado_settings()
|
||||||
self.init_tornado_application()
|
self.init_tornado_application()
|
||||||
@@ -844,23 +841,29 @@ class JupyterHub(Application):
|
|||||||
|
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
|
@gen.coroutine
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Start the whole thing"""
|
"""Start the whole thing"""
|
||||||
|
loop = IOLoop.current()
|
||||||
|
|
||||||
if self.subapp:
|
if self.subapp:
|
||||||
return self.subapp.start()
|
self.subapp.start()
|
||||||
|
loop.stop()
|
||||||
|
return
|
||||||
|
|
||||||
if self.generate_config:
|
if self.generate_config:
|
||||||
self.write_config_file()
|
self.write_config_file()
|
||||||
|
loop.stop()
|
||||||
return
|
return
|
||||||
|
|
||||||
# start the proxy
|
# start the proxy
|
||||||
try:
|
try:
|
||||||
IOLoop().run_sync(self.start_proxy)
|
yield self.start_proxy()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log.critical("Failed to start proxy", exc_info=True)
|
self.log.critical("Failed to start proxy", exc_info=True)
|
||||||
|
self.exit(1)
|
||||||
return
|
return
|
||||||
|
|
||||||
loop = IOLoop.current()
|
|
||||||
loop.add_callback(self.proxy.add_all_users)
|
loop.add_callback(self.proxy.add_all_users)
|
||||||
|
|
||||||
if self.proxy_process:
|
if self.proxy_process:
|
||||||
@@ -877,14 +880,24 @@ class JupyterHub(Application):
|
|||||||
# start the webserver
|
# start the webserver
|
||||||
http_server = tornado.httpserver.HTTPServer(self.tornado_application)
|
http_server = tornado.httpserver.HTTPServer(self.tornado_application)
|
||||||
http_server.listen(self.hub_port)
|
http_server.listen(self.hub_port)
|
||||||
|
# run the cleanup step (in a new loop, because the interrupted one is unclean)
|
||||||
|
|
||||||
|
atexit.register(lambda : IOLoop().run_sync(self.cleanup))
|
||||||
|
|
||||||
|
@gen.coroutine
|
||||||
|
def launch_instance_async(self, argv=None):
|
||||||
|
yield self.initialize(argv)
|
||||||
|
yield self.start()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def launch_instance(cls, argv=None):
|
||||||
|
self = cls.instance(argv=argv)
|
||||||
|
loop = IOLoop.current()
|
||||||
|
loop.add_callback(self.launch_instance_async, argv)
|
||||||
try:
|
try:
|
||||||
loop.start()
|
loop.start()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\nInterrupted")
|
print("\nInterrupted")
|
||||||
finally:
|
|
||||||
# run the cleanup step (in a new loop, because the interrupted one is unclean)
|
|
||||||
IOLoop().run_sync(self.cleanup)
|
|
||||||
|
|
||||||
main = JupyterHub.launch_instance
|
main = JupyterHub.launch_instance
|
||||||
|
|
||||||
|
@@ -94,23 +94,30 @@ class MockHub(JupyterHub):
|
|||||||
self.db_file = NamedTemporaryFile()
|
self.db_file = NamedTemporaryFile()
|
||||||
self.db_url = 'sqlite:///' + self.db_file.name
|
self.db_url = 'sqlite:///' + self.db_file.name
|
||||||
evt = threading.Event()
|
evt = threading.Event()
|
||||||
def _start():
|
@gen.coroutine
|
||||||
self.io_loop = IOLoop.current()
|
def _start_co():
|
||||||
# put initialize in start for SQLAlchemy threading reasons
|
# put initialize in start for SQLAlchemy threading reasons
|
||||||
super(MockHub, self).initialize(argv=argv)
|
yield super(MockHub, self).initialize(argv=argv)
|
||||||
|
|
||||||
# add an initial user
|
# add an initial user
|
||||||
user = orm.User(name='user')
|
user = orm.User(name='user')
|
||||||
self.db.add(user)
|
self.db.add(user)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
yield super(MockHub, self).start()
|
||||||
self.io_loop.add_callback(evt.set)
|
self.io_loop.add_callback(evt.set)
|
||||||
super(MockHub, self).start()
|
|
||||||
|
def _start():
|
||||||
|
self.io_loop = IOLoop.current()
|
||||||
|
self.io_loop.add_callback(_start_co)
|
||||||
|
self.io_loop.start()
|
||||||
|
|
||||||
self._thread = threading.Thread(target=_start)
|
self._thread = threading.Thread(target=_start)
|
||||||
self._thread.start()
|
self._thread.start()
|
||||||
evt.wait(timeout=5)
|
evt.wait(timeout=5)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.db_file.close()
|
|
||||||
self.io_loop.add_callback(self.io_loop.stop)
|
self.io_loop.add_callback(self.io_loop.stop)
|
||||||
self._thread.join()
|
self._thread.join()
|
||||||
|
IOLoop().run_sync(self.cleanup)
|
||||||
|
# ignore the call that will fire in atexit
|
||||||
|
self.cleanup = lambda : None
|
||||||
|
self.db_file.close()
|
||||||
|
Reference in New Issue
Block a user