diff --git a/calparrot/__main__.py b/calparrot/__main__.py index 3669bce9391c7d7dcdba7c59811ad5f2dcce7b33..0a2c681cf46d4c081d1d73d5f514c7afd6aa03c5 100644 --- a/calparrot/__main__.py +++ b/calparrot/__main__.py @@ -13,11 +13,11 @@ try: except ImportError: restful_config = {} -def main(): +async def amain(): ap = argparse.ArgumentParser() ap.add_argument('--debug', action='store_true') ap.add_argument('--db', default='calparrot.sqlite') - ap.add_argument('--port-file', help="File to write port number into") + ap.add_argument('command', nargs='+') args = ap.parse_args() logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO) # Suppress tornado's access logging when things are working correctly: @@ -40,15 +40,17 @@ def main(): app = ProxyApp(base_url, oauth_info, args.db) log.info("CalParrot will serve constant queries on http://127.0.0.1:%d", app.port) - if args.port_file: - with open(args.port_file, 'w') as f: - f.write(str(app.port)) - if os.fork() == 0: - asyncio.run(app.serve()) - else: - # Parent process - exit now - return 0 + try: + env = os.environ.copy() + # Tell the child process (running the notebook) to talk to our proxy: + env['CAL_CAL_TOOLS_CALCAT'] = "{base-api-url='http://127.0.0.1:{app.port}/api', use-oauth2=false}" + proc = await asyncio.create_subprocess_exec(*args.command, env=env) + retcode = await proc.wait() + finally: + await app.shutdown() + + return retcode if __name__ == '__main__': - sys.exit(main()) + sys.exit(asyncio.run(amain())) diff --git a/calparrot/proxy.py b/calparrot/proxy.py index 663af2fdc47dcd7070af9cd4feb3bed8444c7fe8..6c63951318ac05af467b5e6d7b652829965b37f7 100644 --- a/calparrot/proxy.py +++ b/calparrot/proxy.py @@ -181,17 +181,7 @@ class ProxyHandler(RequestHandler): await self.finish(response.body) -class ShutdownHandler(RequestHandler): - def initialize(self, proxy_app): - self.proxy_app = proxy_app - - def post(self): - self.proxy_app.shutdown() - - class ProxyApp: - quit_event: asyncio.Event - def __init__(self, base_url, oauth_info=None, db_path='calparrot.sqlite'): self.response_store = ResponsesDB(db_path) base_url = base_url.rstrip('/') # e.g. https://in.xfel.eu/calibration @@ -208,7 +198,6 @@ class ProxyApp: self.client = AsyncHTTPClient() self.tornado_app = Application([ - ('/.calparrot/stop', ShutdownHandler, {'proxy_app': self}), ('(/.*)', ProxyHandler, { 'base_url': base_url, 'upstream_client': self.client, @@ -218,25 +207,18 @@ class ProxyApp: # Bind a random port to listen on self.sockets = bind_sockets(0, '127.0.0.1') + self.server = HTTPServer(self.tornado_app) + # add_sockets hooks up the server to the event loop + self.server.add_sockets(self.sockets) @property def port(self): return self.sockets[0].getsockname()[1] - async def serve(self): - """Serve requests until asked to quit""" - self.quit_event = asyncio.Event() - server = HTTPServer(self.tornado_app) - # add_sockets hooks up the server to the event loop - server.add_sockets(self.sockets) - - await self.quit_event.wait() - + async def shutdown(self): + """Cleanly shut down the server""" log.info("CalParrot shutting down") - server.stop() # Stop accepting new connections - await server.close_all_connections() # Close existing connections + self.server.stop() # Stop accepting new connections + await self.server.close_all_connections() # Close existing connections self.response_store.close() log.info("Query stats: %s", self.response_store.stats) - - def shutdown(self): - self.quit_event.set()