history: use the job_state module to manage job events
Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
d0c104aceb
commit
21ee446509
|
@ -3,7 +3,6 @@
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import logging
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# Annotation imports
|
# Annotation imports
|
||||||
|
@ -19,10 +18,9 @@ if TYPE_CHECKING:
|
||||||
from confighelper import ConfigHelper
|
from confighelper import ConfigHelper
|
||||||
from websockets import WebRequest
|
from websockets import WebRequest
|
||||||
from . import database
|
from . import database
|
||||||
from . import klippy_apis
|
from .job_state import JobState
|
||||||
from .file_manager import file_manager
|
from .file_manager import file_manager
|
||||||
DBComp = database.MoonrakerDatabase
|
DBComp = database.MoonrakerDatabase
|
||||||
APIComp = klippy_apis.KlippyAPI
|
|
||||||
FMComp = file_manager.FileManager
|
FMComp = file_manager.FileManager
|
||||||
|
|
||||||
HIST_NAMESPACE = "history"
|
HIST_NAMESPACE = "history"
|
||||||
|
@ -46,14 +44,20 @@ class History:
|
||||||
'longest_print': 0.
|
'longest_print': 0.
|
||||||
})
|
})
|
||||||
|
|
||||||
self.server.register_event_handler(
|
|
||||||
"server:klippy_ready", self._init_ready)
|
|
||||||
self.server.register_event_handler(
|
|
||||||
"server:status_update", self._status_update)
|
|
||||||
self.server.register_event_handler(
|
self.server.register_event_handler(
|
||||||
"server:klippy_disconnect", self._handle_disconnect)
|
"server:klippy_disconnect", self._handle_disconnect)
|
||||||
self.server.register_event_handler(
|
self.server.register_event_handler(
|
||||||
"server:klippy_shutdown", self._handle_shutdown)
|
"server:klippy_shutdown", self._handle_shutdown)
|
||||||
|
self.server.register_event_handler(
|
||||||
|
"job_state:started", self._on_job_started)
|
||||||
|
self.server.register_event_handler(
|
||||||
|
"job_state:complete", self._on_job_complete)
|
||||||
|
self.server.register_event_handler(
|
||||||
|
"job_state:cancelled", self._on_job_cancelled)
|
||||||
|
self.server.register_event_handler(
|
||||||
|
"job_state:standby", self._on_job_standby)
|
||||||
|
self.server.register_event_handler(
|
||||||
|
"job_state:error", self._on_job_error)
|
||||||
self.server.register_notification("history:history_changed")
|
self.server.register_notification("history:history_changed")
|
||||||
|
|
||||||
self.server.register_endpoint(
|
self.server.register_endpoint(
|
||||||
|
@ -69,21 +73,11 @@ class History:
|
||||||
|
|
||||||
self.current_job: Optional[PrinterJob] = None
|
self.current_job: Optional[PrinterJob] = None
|
||||||
self.current_job_id: Optional[str] = None
|
self.current_job_id: Optional[str] = None
|
||||||
self.print_stats: Dict[str, Any] = {}
|
|
||||||
self.next_job_id: int = 0
|
self.next_job_id: int = 0
|
||||||
self.cached_job_ids = self.history_ns.keys()
|
self.cached_job_ids = self.history_ns.keys()
|
||||||
if self.cached_job_ids:
|
if self.cached_job_ids:
|
||||||
self.next_job_id = int(self.cached_job_ids[-1], 16) + 1
|
self.next_job_id = int(self.cached_job_ids[-1], 16) + 1
|
||||||
|
|
||||||
async def _init_ready(self) -> None:
|
|
||||||
klippy_apis: APIComp = self.server.lookup_component('klippy_apis')
|
|
||||||
sub: Dict[str, Optional[List[str]]] = {"print_stats": None}
|
|
||||||
try:
|
|
||||||
result = await klippy_apis.subscribe_objects(sub)
|
|
||||||
except self.server.error as e:
|
|
||||||
logging.info(f"Error subscribing to print_stats")
|
|
||||||
self.print_stats = result.get("print_stats", {})
|
|
||||||
|
|
||||||
async def _handle_job_request(self,
|
async def _handle_job_request(self,
|
||||||
web_request: WebRequest
|
web_request: WebRequest
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
|
@ -173,50 +167,50 @@ class History:
|
||||||
) -> Dict[str, Dict[str, float]]:
|
) -> Dict[str, Dict[str, float]]:
|
||||||
return {'job_totals': self.job_totals}
|
return {'job_totals': self.job_totals}
|
||||||
|
|
||||||
async def _status_update(self, data: Dict[str, Any]) -> None:
|
def _on_job_started(self,
|
||||||
ps = data.get("print_stats", {})
|
prev_stats: Dict[str, Any],
|
||||||
if "state" in ps:
|
new_stats: Dict[str, Any]
|
||||||
old_state: str = self.print_stats['state']
|
) -> None:
|
||||||
new_state: str = ps['state']
|
if self.current_job is not None:
|
||||||
new_ps = dict(self.print_stats)
|
# Finish with the previous state
|
||||||
new_ps.update(ps)
|
self.finish_job("cancelled", prev_stats)
|
||||||
|
self.add_job(PrinterJob(new_stats))
|
||||||
|
|
||||||
if new_state is not old_state:
|
def _on_job_complete(self,
|
||||||
if new_state == "printing" and self.current_job is None:
|
prev_stats: Dict[str, Any],
|
||||||
# always add new job if no existing job is present
|
new_stats: Dict[str, Any]
|
||||||
self.add_job(PrinterJob(new_ps))
|
) -> None:
|
||||||
elif self.current_job is not None:
|
self.finish_job("completed", new_stats)
|
||||||
if new_state == "complete":
|
|
||||||
self.finish_job("completed", new_ps)
|
|
||||||
elif new_state == "cancelled":
|
|
||||||
self.finish_job("cancelled", new_ps)
|
|
||||||
elif new_state == "standby":
|
|
||||||
# Backward compatibility with
|
|
||||||
# `CLEAR_PAUSE/SDCARD_RESET_FILE` workflow
|
|
||||||
self.finish_job("cancelled", self.print_stats)
|
|
||||||
elif new_state == "error":
|
|
||||||
self.finish_job("error", new_ps)
|
|
||||||
elif new_state == "printing" and \
|
|
||||||
self._check_need_cancel(new_ps):
|
|
||||||
# Finish with the previous state
|
|
||||||
self.finish_job("cancelled", self.print_stats)
|
|
||||||
self.add_job(PrinterJob(new_ps))
|
|
||||||
|
|
||||||
self.print_stats.update(ps)
|
def _on_job_cancelled(self,
|
||||||
|
prev_stats: Dict[str, Any],
|
||||||
|
new_stats: Dict[str, Any]
|
||||||
|
) -> None:
|
||||||
|
self.finish_job("cancelled", new_stats)
|
||||||
|
|
||||||
|
def _on_job_error(self,
|
||||||
|
prev_stats: Dict[str, Any],
|
||||||
|
new_stats: Dict[str, Any]
|
||||||
|
) -> None:
|
||||||
|
self.finish_job("error", new_stats)
|
||||||
|
|
||||||
|
def _on_job_standby(self,
|
||||||
|
prev_stats: Dict[str, Any],
|
||||||
|
new_stats: Dict[str, Any]
|
||||||
|
) -> None:
|
||||||
|
# Backward compatibility with
|
||||||
|
# `CLEAR_PAUSE/SDCARD_RESET_FILE` workflow
|
||||||
|
self.finish_job("cancelled", prev_stats)
|
||||||
|
|
||||||
def _handle_shutdown(self) -> None:
|
def _handle_shutdown(self) -> None:
|
||||||
self.finish_job("klippy_shutdown", self.print_stats)
|
jstate: JobState = self.server.lookup_component("job_state")
|
||||||
|
last_ps = jstate.get_last_stats()
|
||||||
|
self.finish_job("klippy_shutdown", last_ps)
|
||||||
|
|
||||||
def _handle_disconnect(self) -> None:
|
def _handle_disconnect(self) -> None:
|
||||||
self.finish_job("klippy_disconnect", self.print_stats)
|
jstate: JobState = self.server.lookup_component("job_state")
|
||||||
|
last_ps = jstate.get_last_stats()
|
||||||
def _check_need_cancel(self, new_stats: Dict[str, Any]) -> bool:
|
self.finish_job("klippy_disconnect", last_ps)
|
||||||
# Cancel if the file name has changed, total duration has
|
|
||||||
# decreased, or if job is not resuming from a pause
|
|
||||||
ps = self.print_stats
|
|
||||||
return ps['filename'] != new_stats['filename'] or \
|
|
||||||
ps['total_duration'] > new_stats['total_duration'] or \
|
|
||||||
ps['state'] != "paused"
|
|
||||||
|
|
||||||
def add_job(self, job: PrinterJob) -> None:
|
def add_job(self, job: PrinterJob) -> None:
|
||||||
if len(self.cached_job_ids) >= MAX_JOBS:
|
if len(self.cached_job_ids) >= MAX_JOBS:
|
||||||
|
@ -241,6 +235,13 @@ class History:
|
||||||
def finish_job(self, status: str, pstats: Dict[str, Any]) -> None:
|
def finish_job(self, status: str, pstats: Dict[str, Any]) -> None:
|
||||||
if self.current_job is None:
|
if self.current_job is None:
|
||||||
return
|
return
|
||||||
|
cj = self.current_job
|
||||||
|
if (
|
||||||
|
pstats.get('filename') != cj.get('filename') or
|
||||||
|
pstats.get('total_duration', 0.) < cj.get('total_duration')
|
||||||
|
):
|
||||||
|
# Print stats have been reset, do not update this job with them
|
||||||
|
pstats = {}
|
||||||
|
|
||||||
self.current_job.finish(status, pstats)
|
self.current_job.finish(status, pstats)
|
||||||
# Regrab metadata incase metadata wasn't parsed yet due to file upload
|
# Regrab metadata incase metadata wasn't parsed yet due to file upload
|
||||||
|
@ -318,7 +319,9 @@ class History:
|
||||||
return job
|
return job
|
||||||
|
|
||||||
def on_exit(self) -> None:
|
def on_exit(self) -> None:
|
||||||
self.finish_job("server_exit", self.print_stats)
|
jstate: JobState = self.server.lookup_component("job_state")
|
||||||
|
last_ps = jstate.get_last_stats()
|
||||||
|
self.finish_job("server_exit", last_ps)
|
||||||
|
|
||||||
class PrinterJob:
|
class PrinterJob:
|
||||||
def __init__(self, data: Dict[str, Any] = {}) -> None:
|
def __init__(self, data: Dict[str, Any] = {}) -> None:
|
||||||
|
|
Loading…
Reference in New Issue