moonraker: don't timeout requests to Klippy

Klippy requests typically only timeout when the connection between Klippy and the Server is disconnected.  Rather returning a timeout, send an error if there are any pending requests when a disconnection is detected.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Arksine 2020-08-04 21:27:58 -04:00
parent d235139e6b
commit d19737f4c5
1 changed files with 18 additions and 31 deletions

View File

@ -36,11 +36,6 @@ class Server:
self.host = args.address self.host = args.address
self.port = args.port self.port = args.port
# Options configurable by Klippy
self.request_timeout = 5.
self.long_running_gcodes = {}
self.long_running_requests = {}
# Event initialization # Event initialization
self.events = {} self.events = {}
@ -271,12 +266,6 @@ class Server:
"klippy.log for more information") "klippy.log for more information")
def _load_config(self, config): def _load_config(self, config):
self.request_timeout = config.get(
'request_timeout', self.request_timeout)
self.long_running_gcodes = config.get(
'long_running_gcodes', self.long_running_gcodes)
self.long_running_requests = config.get(
'long_running_requests', self.long_running_requests)
self.moonraker_app.load_config(config) self.moonraker_app.load_config(config)
# load config for core plugins # load config for core plugins
for plugin_name in CORE_PLUGINS: for plugin_name in CORE_PLUGINS:
@ -329,14 +318,7 @@ class Server:
self.send_event("server:status_update", status) self.send_event("server:status_update", status)
def make_request(self, path, method, args): def make_request(self, path, method, args):
timeout = self.long_running_requests.get(path, self.request_timeout) base_request = BaseRequest(path, method, args)
if path == "gcode/script":
script = args.get('script', "")
base_gc = script.strip().split()[0].upper()
timeout = self.long_running_gcodes.get(base_gc, timeout)
base_request = BaseRequest(path, method, args, timeout)
self.pending_requests[base_request.id] = base_request self.pending_requests[base_request.id] = base_request
ret = self.klippy_send(base_request.to_dict()) ret = self.klippy_send(base_request.to_dict())
if not ret: if not ret:
@ -365,6 +347,9 @@ class Server:
self.is_klippy_ready = False self.is_klippy_ready = False
self.server_configured = False self.server_configured = False
self.init_cb.stop() self.init_cb.stop()
for request in self.pending_requests.values():
request.notify(ServerError("Klippy Disconnected", 503))
self.pending_requests = {}
if self.is_klippy_connected: if self.is_klippy_connected:
self.is_klippy_connected = False self.is_klippy_connected = False
logging.info("Klippy Connection Removed") logging.info("Klippy Connection Removed")
@ -385,26 +370,28 @@ class Server:
# Basic WebRequest class, easily converted to dict for json encoding # Basic WebRequest class, easily converted to dict for json encoding
class BaseRequest: class BaseRequest:
def __init__(self, path, method, args, timeout=None): def __init__(self, path, method, args):
self.id = id(self) self.id = id(self)
self.path = path self.path = path
self.method = method self.method = method
self.args = args self.args = args
self._timeout = timeout
self._event = Event() self._event = Event()
self.response = None self.response = None
if timeout is not None:
self._timeout = time.time() + timeout
async def wait(self): async def wait(self):
# Wait for klippy to process the request or until the timeout # Log pending requests every 60 seconds
# has been reached. start_time = time.time()
try: while True:
await self._event.wait(timeout=self._timeout) timeout = time.time() + 60.
except TimeoutError: try:
logging.info("Request '%s' Timed Out" % await self._event.wait(timeout=timeout)
(self.method + " " + self.path)) except TimeoutError:
return ServerError("Klippy Request Timed Out", 500) pending_time = time.time() - start_time
logging.info("Request '%s %s' pending: %.2f seconds" %
(self.method, self.path, pending_time))
self._event.clear()
continue
break
return self.response return self.response
def notify(self, response): def notify(self, response):