server: refactor startup
Use asyncio.run() to launch the server application as recommended by the Python docs. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
3a42dac02b
commit
0a8590643f
|
@ -1108,7 +1108,10 @@ class FileSourceWrapper(ConfigSourceWrapper):
|
|||
def get_configuration(
|
||||
server: Server, app_args: Dict[str, Any]
|
||||
) -> ConfigHelper:
|
||||
start_path = pathlib.Path(app_args['config_file']).expanduser().resolve()
|
||||
cfg_file = app_args["config_file"]
|
||||
if app_args["is_backup_config"]:
|
||||
cfg_file = app_args["backup_config"]
|
||||
start_path = pathlib.Path(cfg_file).expanduser().absolute()
|
||||
source = FileSourceWrapper(server)
|
||||
source.read_file(start_path)
|
||||
if not source.config.has_section('server'):
|
||||
|
|
|
@ -27,7 +27,7 @@ _uvl_var = os.getenv("MOONRAKER_ENABLE_UVLOOP", "y").lower()
|
|||
_uvl_enabled = False
|
||||
if _uvl_var in ["y", "yes", "true"]:
|
||||
with contextlib.suppress(ImportError):
|
||||
import uvloop
|
||||
import uvloop # type: ignore
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
_uvl_enabled = True
|
||||
|
||||
|
@ -48,7 +48,7 @@ class EventLoop:
|
|||
return self.aioloop
|
||||
|
||||
def reset(self) -> None:
|
||||
self.aioloop = self._create_new_loop()
|
||||
self.aioloop = asyncio.get_running_loop()
|
||||
self.add_signal_handler = self.aioloop.add_signal_handler
|
||||
self.remove_signal_handler = self.aioloop.remove_signal_handler
|
||||
self.add_reader = self.aioloop.add_reader
|
||||
|
@ -126,7 +126,7 @@ class EventLoop:
|
|||
host, port, family=0, type=socket.SOCK_STREAM
|
||||
)
|
||||
for res in ainfo:
|
||||
af, socktype, proto, canonname, sa = res
|
||||
af, socktype, proto, _cannon_name, _sa = res
|
||||
sock = None
|
||||
try:
|
||||
sock = socket.socket(af, socktype, proto)
|
||||
|
@ -152,12 +152,6 @@ class EventLoop:
|
|||
else:
|
||||
raise socket.error("getaddrinfo returns an empty list")
|
||||
|
||||
def start(self):
|
||||
self.aioloop.run_forever()
|
||||
|
||||
def stop(self):
|
||||
self.aioloop.stop()
|
||||
|
||||
def close(self):
|
||||
self.aioloop.close()
|
||||
|
||||
|
|
|
@ -130,7 +130,8 @@ class LogManager:
|
|||
return eventloop.run_in_thread(self.file_hdlr.doRollover)
|
||||
|
||||
def stop_logging(self):
|
||||
self.listener.stop()
|
||||
if self.listener is not None:
|
||||
self.listener.stop()
|
||||
|
||||
async def _handle_log_rollover(
|
||||
self, web_request: WebRequest
|
||||
|
|
|
@ -89,6 +89,7 @@ class Server:
|
|||
self.ssl_port: int = config.getint('ssl_port', 7130)
|
||||
self.exit_reason: str = ""
|
||||
self.server_running: bool = False
|
||||
self.app_running_evt = asyncio.Event()
|
||||
self.pip_recovery_attempted: bool = False
|
||||
|
||||
# Configure Debug Logging
|
||||
|
@ -198,10 +199,8 @@ class Server:
|
|||
await self.event_loop.run_in_thread(self.config.create_backup)
|
||||
|
||||
machine: Machine = self.lookup_component("machine")
|
||||
if await machine.validate_installation():
|
||||
return
|
||||
|
||||
if start_server:
|
||||
restarting = await machine.validate_installation()
|
||||
if not restarting and start_server:
|
||||
await self.start_server()
|
||||
|
||||
async def start_server(self, connect_to_klippy: bool = True) -> None:
|
||||
|
@ -218,6 +217,9 @@ class Server:
|
|||
if connect_to_klippy:
|
||||
self.klippy_connection.connect()
|
||||
|
||||
async def run_until_exit(self) -> None:
|
||||
await self.app_running_evt.wait()
|
||||
|
||||
def add_log_rollover_item(
|
||||
self, name: str, item: str, log: bool = True
|
||||
) -> None:
|
||||
|
@ -488,7 +490,7 @@ class Server:
|
|||
|
||||
self.exit_reason = exit_reason
|
||||
self.event_loop.remove_signal_handler(signal.SIGTERM)
|
||||
self.event_loop.stop()
|
||||
self.app_running_evt.set()
|
||||
|
||||
async def _handle_server_restart(self, web_request: WebRequest) -> str:
|
||||
self.event_loop.register_callback(self._stop_server)
|
||||
|
@ -540,6 +542,45 @@ class Server:
|
|||
'files': cfg_file_list
|
||||
}
|
||||
|
||||
async def launch_server(
|
||||
log_manager: LogManager, app_args: Dict[str, Any]
|
||||
) -> Optional[int]:
|
||||
eventloop = EventLoop()
|
||||
startup_warnings: List[str] = app_args["startup_warnings"]
|
||||
try:
|
||||
server = Server(app_args, log_manager, eventloop)
|
||||
server.load_components()
|
||||
except confighelper.ConfigError as e:
|
||||
logging.exception("Server Config Error")
|
||||
backup_cfg: Optional[str] = app_args["backup_config"]
|
||||
if app_args["is_backup_config"] or backup_cfg is None:
|
||||
return 1
|
||||
app_args["is_backup_config"] = True
|
||||
startup_warnings.append(
|
||||
f"Server configuration error: {e}\n"
|
||||
f"Loading most recent working configuration: '{backup_cfg}'\n"
|
||||
f"Please fix the issue in moonraker.conf and restart the server."
|
||||
)
|
||||
return True
|
||||
except Exception:
|
||||
logging.exception("Moonraker Error")
|
||||
return 1
|
||||
try:
|
||||
await server.server_init()
|
||||
await server.run_until_exit()
|
||||
except Exception:
|
||||
logging.exception("Server Running Error")
|
||||
return 1
|
||||
if server.exit_reason == "terminate":
|
||||
return 0
|
||||
# Restore the original config and clear the warning
|
||||
# before the server restarts
|
||||
if app_args["is_backup_config"]:
|
||||
startup_warnings.pop()
|
||||
app_args["is_backup_config"] = False
|
||||
del server
|
||||
return None
|
||||
|
||||
def main(from_package: bool = True) -> None:
|
||||
def get_env_bool(key: str) -> bool:
|
||||
return os.getenv(key, "").lower() in ["y", "yes", "true"]
|
||||
|
@ -635,6 +676,7 @@ def main(from_package: bool = True) -> None:
|
|||
"data_path": str(data_path),
|
||||
"is_default_data_path": cmd_line_args.datapath is None,
|
||||
"config_file": cfg_file,
|
||||
"backup_config": confighelper.find_config_backup(cfg_file),
|
||||
"startup_warnings": startup_warnings,
|
||||
"verbose": cmd_line_args.verbose,
|
||||
"debug": cmd_line_args.debug,
|
||||
|
@ -661,60 +703,14 @@ def main(from_package: bool = True) -> None:
|
|||
log_manager = LogManager(app_args, startup_warnings)
|
||||
|
||||
# Start asyncio event loop and server
|
||||
event_loop = EventLoop()
|
||||
alt_config_loaded = False
|
||||
estatus = 0
|
||||
while True:
|
||||
try:
|
||||
server = Server(app_args, log_manager, event_loop)
|
||||
server.load_components()
|
||||
except confighelper.ConfigError as e:
|
||||
backup_cfg = confighelper.find_config_backup(cfg_file)
|
||||
logging.exception("Server Config Error")
|
||||
if alt_config_loaded or backup_cfg is None:
|
||||
estatus = 1
|
||||
break
|
||||
app_args["config_file"] = backup_cfg
|
||||
app_args["is_backup_config"] = True
|
||||
warn_list = list(startup_warnings)
|
||||
app_args["startup_warnings"] = warn_list
|
||||
warn_list.append(
|
||||
f"Server configuration error: {e}\n"
|
||||
f"Loaded server from most recent working configuration:"
|
||||
f" '{app_args['config_file']}'\n"
|
||||
f"Please fix the issue in moonraker.conf and restart "
|
||||
f"the server."
|
||||
)
|
||||
alt_config_loaded = True
|
||||
continue
|
||||
except Exception:
|
||||
logging.exception("Moonraker Error")
|
||||
estatus = 1
|
||||
estatus = asyncio.run(launch_server(log_manager, app_args))
|
||||
if estatus is not None:
|
||||
break
|
||||
try:
|
||||
event_loop.register_callback(server.server_init)
|
||||
event_loop.start()
|
||||
except Exception:
|
||||
logging.exception("Server Running Error")
|
||||
estatus = 1
|
||||
break
|
||||
if server.exit_reason == "terminate":
|
||||
break
|
||||
# Restore the original config and clear the warning
|
||||
# before the server restarts
|
||||
if alt_config_loaded:
|
||||
app_args["config_file"] = cfg_file
|
||||
app_args["startup_warnings"] = startup_warnings
|
||||
app_args["is_backup_config"] = False
|
||||
alt_config_loaded = False
|
||||
event_loop.close()
|
||||
# Since we are running outside of the the server
|
||||
# it is ok to use a blocking sleep here
|
||||
time.sleep(.5)
|
||||
logging.info("Attempting Server Restart...")
|
||||
del server
|
||||
event_loop.reset()
|
||||
event_loop.close()
|
||||
logging.info("Server Shutdown")
|
||||
log_manager.stop_logging()
|
||||
exit(estatus)
|
||||
|
|
Loading…
Reference in New Issue