server: improve event exception handling

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2023-06-26 08:09:43 -04:00
parent 0592181f54
commit f6770e2865
No known key found for this signature in database
GPG Key ID: 5A1EB336DFB4C71B

View File

@ -18,6 +18,7 @@ import logging
import signal import signal
import asyncio import asyncio
import uuid import uuid
import traceback
from . import confighelper from . import confighelper
from .eventloop import EventLoop from .eventloop import EventLoop
from .app import MoonrakerApp from .app import MoonrakerApp
@ -195,8 +196,9 @@ class Server:
if connect_to_klippy: if connect_to_klippy:
self.klippy_connection.connect() self.klippy_connection.connect()
def add_log_rollover_item(self, name: str, item: str, def add_log_rollover_item(
log: bool = True) -> None: self, name: str, item: str, log: bool = True
) -> None:
self.log_manager.set_rollover_info(name, item) self.log_manager.set_rollover_info(name, item)
if log and item is not None: if log and item is not None:
logging.info(item) logging.info(item)
@ -300,17 +302,15 @@ class Server:
f"Component '{component_name}' already registered") f"Component '{component_name}' already registered")
self.components[component_name] = component self.components[component_name] = component
def register_notification(self, def register_notification(
event_name: str, self, event_name: str, notify_name: Optional[str] = None
notify_name: Optional[str] = None ) -> None:
) -> None:
wsm: WebsocketManager = self.lookup_component("websockets") wsm: WebsocketManager = self.lookup_component("websockets")
wsm.register_notification(event_name, notify_name) wsm.register_notification(event_name, notify_name)
def register_event_handler(self, def register_event_handler(
event: str, self, event: str, callback: FlexCallback
callback: FlexCallback ) -> None:
) -> None:
self.events.setdefault(event, []).append(callback) self.events.setdefault(event, []).append(callback)
def send_event(self, event: str, *args) -> asyncio.Future: def send_event(self, event: str, *args) -> asyncio.Future:
@ -319,29 +319,38 @@ class Server:
self._process_event, fut, event, *args) self._process_event, fut, event, *args)
return fut return fut
async def _process_event(self, async def _process_event(
fut: asyncio.Future, self, fut: asyncio.Future, event: str, *args
event: str, ) -> None:
*args
) -> None:
events = self.events.get(event, []) events = self.events.get(event, [])
coroutines: List[Coroutine] = [] coroutines: List[Coroutine] = []
try: for func in events:
for func in events: try:
ret = func(*args) ret = func(*args)
except Exception:
logging.exception(f"Error processing callback in event {event}")
else:
if ret is not None: if ret is not None:
coroutines.append(ret) coroutines.append(ret)
if coroutines: if coroutines:
await asyncio.gather(*coroutines) results = await asyncio.gather(*coroutines, return_exceptions=True)
except ServerError as e: for val in results:
logging.exception(f"Error Processing Event: {fut}") if isinstance(val, Exception):
if sys.version_info < (3, 10):
exc_info = "".join(traceback.format_exception(
type(val), val, val.__traceback__
))
else:
exc_info = "".join(traceback.format_exception(val))
logging.info(
f"\nError processing callback in event {event}\n{exc_info}"
)
if not fut.done(): if not fut.done():
fut.set_result(None) fut.set_result(None)
def register_remote_method(self, def register_remote_method(
method_name: str, self, method_name: str, cb: FlexCallback
cb: FlexCallback ) -> None:
) -> None:
self.klippy_connection.register_remote_method(method_name, cb) self.klippy_connection.register_remote_method(method_name, cb)
def get_host_info(self) -> Dict[str, Any]: def get_host_info(self) -> Dict[str, Any]:
@ -417,9 +426,7 @@ class Server:
self.event_loop.register_callback(self._stop_server) self.event_loop.register_callback(self._stop_server)
return "ok" return "ok"
async def _handle_info_request(self, async def _handle_info_request(self, web_request: WebRequest) -> Dict[str, Any]:
web_request: WebRequest
) -> Dict[str, Any]:
raw = web_request.get_boolean("raw", False) raw = web_request.get_boolean("raw", False)
file_manager: Optional[FileManager] = self.lookup_component( file_manager: Optional[FileManager] = self.lookup_component(
'file_manager', None) 'file_manager', None)
@ -448,9 +455,7 @@ class Server:
'api_version_string': ".".join([str(v) for v in API_VERSION]) 'api_version_string': ".".join([str(v) for v in API_VERSION])
} }
async def _handle_config_request(self, async def _handle_config_request(self, web_request: WebRequest) -> Dict[str, Any]:
web_request: WebRequest
) -> Dict[str, Any]:
cfg_file_list: List[Dict[str, Any]] = [] cfg_file_list: List[Dict[str, Any]] = []
cfg_parent = pathlib.Path( cfg_parent = pathlib.Path(
self.app_args["config_file"] self.app_args["config_file"]