job_queue: improve state reporting

Only report ready when an item is in the queue and automatic transition is enabled.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2024-06-30 10:45:34 -04:00
parent 8f3b30a04f
commit dc00d38b01
1 changed files with 25 additions and 17 deletions

View File

@ -24,15 +24,17 @@ if TYPE_CHECKING:
from ..common import WebRequest, UserInfo from ..common import WebRequest, UserInfo
from .klippy_apis import KlippyAPI from .klippy_apis import KlippyAPI
from .file_manager.file_manager import FileManager from .file_manager.file_manager import FileManager
from .job_state import JobState
class JobQueue: class JobQueue:
def __init__(self, config: ConfigHelper) -> None: def __init__(self, config: ConfigHelper) -> None:
self.server = config.get_server() self.server = config.get_server()
self.queued_jobs: Dict[str, QueuedJob] = {} self.queued_jobs: Dict[str, QueuedJob] = {}
self.lock = asyncio.Lock() self.lock = asyncio.Lock()
self.pause_requested: bool = False
self.load_on_start = config.getboolean("load_on_startup", False) self.load_on_start = config.getboolean("load_on_startup", False)
self.automatic = config.getboolean("automatic_transition", False) self.automatic = config.getboolean("automatic_transition", False)
self.queue_state: str = "ready" if self.automatic else "paused" self.queue_state: str = "paused"
self.job_delay = config.getfloat("job_transition_delay", 0.01) self.job_delay = config.getfloat("job_transition_delay", 0.01)
if self.job_delay <= 0.: if self.job_delay <= 0.:
raise config.error( raise config.error(
@ -52,8 +54,7 @@ class JobQueue:
self.server.register_notification("job_queue:job_queue_changed") self.server.register_notification("job_queue:job_queue_changed")
self.server.register_remote_method("pause_job_queue", self.pause_queue) self.server.register_remote_method("pause_job_queue", self.pause_queue)
self.server.register_remote_method("start_job_queue", self.server.register_remote_method("start_job_queue", self.start_queue)
self.start_queue)
self.server.register_endpoint( self.server.register_endpoint(
"/server/job_queue/job", RequestType.POST | RequestType.DELETE, "/server/job_queue/job", RequestType.POST | RequestType.DELETE,
@ -84,9 +85,9 @@ class JobQueue:
1., self._pop_job, False) 1., self._pop_job, False)
async def _handle_shutdown(self) -> None: async def _handle_shutdown(self) -> None:
has_requested_pause = self.pause_requested
await self.pause_queue() await self.pause_queue()
if not self.queued_jobs and self.automatic: self.pause_requested = has_requested_pause
self._set_queue_state("ready")
async def _on_job_state_changed(self, job_event: JobEvent, *args) -> None: async def _on_job_state_changed(self, job_event: JobEvent, *args) -> None:
if job_event == JobEvent.COMPLETE: if job_event == JobEvent.COMPLETE:
@ -116,8 +117,7 @@ class JobQueue:
if self.queue_state == "paused": if self.queue_state == "paused":
return return
if not self.queued_jobs: if not self.queued_jobs:
qs = "ready" if self.automatic else "paused" self._set_queue_state("paused")
self._set_queue_state(qs)
return return
kapis: KlippyAPI = self.server.lookup_component('klippy_apis') kapis: KlippyAPI = self.server.lookup_component('klippy_apis')
uid, job = list(self.queued_jobs.items())[0] uid, job = list(self.queued_jobs.items())[0]
@ -132,6 +132,7 @@ class JobQueue:
# Check to see if the queue was paused while running # Check to see if the queue was paused while running
# the job transition gcode # the job transition gcode
if self.queue_state != "loading": if self.queue_state != "loading":
self._set_queue_state("paused")
raise self.server.error( raise self.server.error(
"Queue State Changed during Transition Gcode") "Queue State Changed during Transition Gcode")
self._set_queue_state("starting") self._set_queue_state("starting")
@ -144,8 +145,9 @@ class JobQueue:
else: else:
self.queued_jobs.pop(uid, None) self.queued_jobs.pop(uid, None)
if self.queue_state == "starting": if self.queue_state == "starting":
# If the queue was not paused while starting the print, # Set the queue to ready if items are in the queue
set_ready = not self.queued_jobs or self.automatic # and auto transition is enabled
set_ready = len(self.queued_jobs) > 0 and self.automatic
self.queue_state = "ready" if set_ready else "paused" self.queue_state = "ready" if set_ready else "paused"
self._send_queue_event(action="job_loaded") self._send_queue_event(action="job_loaded")
@ -184,6 +186,11 @@ class JobQueue:
queued_job = QueuedJob(fname, user) queued_job = QueuedJob(fname, user)
self.queued_jobs[queued_job.job_id] = queued_job self.queued_jobs[queued_job.job_id] = queued_job
self._send_queue_event(action="jobs_added") self._send_queue_event(action="jobs_added")
if self.automatic and not self.pause_requested:
jstate: JobState = self.server.lookup_component("job_state")
last_evt = jstate.get_last_job_event()
if last_evt.is_printing or last_evt == JobEvent.PAUSED:
self._set_queue_state("ready")
async def delete_job(self, async def delete_job(self,
job_ids: Union[str, List[str]], job_ids: Union[str, List[str]],
@ -210,23 +217,24 @@ class JobQueue:
if self.pop_queue_handle is not None: if self.pop_queue_handle is not None:
self.pop_queue_handle.cancel() self.pop_queue_handle.cancel()
self.pop_queue_handle = None self.pop_queue_handle = None
# Acquire the lock to wait for any pending operations to # Acquire the lock to wait for any pending operations to complete
# complete async with self.lock:
await self.lock.acquire() self.pause_requested = True
self.lock.release()
async def start_queue(self) -> None: async def start_queue(self) -> None:
async with self.lock: async with self.lock:
if self.queue_state != "loading": self.pause_requested = False
if self.queued_jobs and await self._check_can_print(): if self.queue_state in ("ready", "paused"):
if not self.queued_jobs:
self._set_queue_state("paused")
elif await self._check_can_print():
self._set_queue_state("loading") self._set_queue_state("loading")
event_loop = self.server.get_event_loop() event_loop = self.server.get_event_loop()
self.pop_queue_handle = event_loop.delay_callback( self.pop_queue_handle = event_loop.delay_callback(
0.01, self._pop_job, False 0.01, self._pop_job, False
) )
else: else:
qs = "ready" if self.automatic else "paused" self._set_queue_state("ready" if self.automatic else "paused")
self._set_queue_state(qs)
def _job_map_to_list(self) -> List[Dict[str, Any]]: def _job_map_to_list(self) -> List[Dict[str, Any]]:
cur_time = time.time() cur_time = time.time()