file_manager: use the job queue to start gcode uploads

If a print cannot be started then it will be queued.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2021-10-04 11:29:20 -04:00 committed by Eric Callahan
parent b135f48867
commit 7a8aeae673
1 changed files with 32 additions and 23 deletions

View File

@ -30,6 +30,7 @@ from typing import (
TypeVar, TypeVar,
cast, cast,
) )
if TYPE_CHECKING: if TYPE_CHECKING:
from inotify_simple import Event as InotifyEvent from inotify_simple import Event as InotifyEvent
from moonraker import Server from moonraker import Server
@ -38,6 +39,7 @@ if TYPE_CHECKING:
from components import database from components import database
from components import klippy_apis from components import klippy_apis
from components import shell_command from components import shell_command
from components.job_queue import JobQueue
DBComp = database.MoonrakerDatabase DBComp = database.MoonrakerDatabase
APIComp = klippy_apis.KlippyAPI APIComp = klippy_apis.KlippyAPI
SCMDComp = shell_command.ShellCommandFactory SCMDComp = shell_command.ShellCommandFactory
@ -65,6 +67,8 @@ class FileManager:
self.write_mutex = asyncio.Lock() self.write_mutex = asyncio.Lock()
self.notify_sync_lock: Optional[NotifySyncLock] = None self.notify_sync_lock: Optional[NotifySyncLock] = None
self.fixed_path_args: Dict[str, Any] = {} self.fixed_path_args: Dict[str, Any] = {}
self.queue_gcodes: bool = config.getboolean('queue_gcode_uploads',
False)
# Register file management endpoints # Register file management endpoints
self.server.register_endpoint( self.server.register_endpoint(
@ -287,21 +291,21 @@ class FileManager:
# Get virtual_sdcard status # Get virtual_sdcard status
kapis: APIComp = self.server.lookup_component('klippy_apis') kapis: APIComp = self.server.lookup_component('klippy_apis')
result: Dict[str, Any] result: Dict[str, Any]
result = await kapis.query_objects({'print_stats': None}) result = await kapis.query_objects({'print_stats': None}, {})
pstats = result.get('print_stats', {}) pstats = result.get('print_stats', {})
loaded_file: str = pstats.get('filename', "") loaded_file: str = pstats.get('filename', "")
state: str = pstats.get('state', "") state: str = pstats.get('state', "")
gc_path = self.file_paths.get('gcodes', "") gc_path = self.file_paths.get('gcodes', "")
full_path = os.path.join(gc_path, loaded_file) full_path = os.path.join(gc_path, loaded_file)
if loaded_file and state != "complete": is_printing = state in ["printing", "paused"]
if loaded_file and is_printing:
if os.path.isdir(requested_path): if os.path.isdir(requested_path):
# Check to see of the loaded file is in the request # Check to see of the loaded file is in the request
if full_path.startswith(requested_path): if full_path.startswith(requested_path):
raise self.server.error("File currently in use", 403) raise self.server.error("File currently in use", 403)
elif full_path == requested_path: elif full_path == requested_path:
raise self.server.error("File currently in use", 403) raise self.server.error("File currently in use", 403)
ongoing = state in ["printing", "paused"] return not is_printing
return ongoing
def _convert_request_path(self, request_path: str) -> Tuple[str, str]: def _convert_request_path(self, request_path: str) -> Tuple[str, str]:
# Parse the root, relative path, and disk path from a remote request # Parse the root, relative path, and disk path from a remote request
@ -504,43 +508,48 @@ class FileManager:
async def _finish_gcode_upload(self, async def _finish_gcode_upload(self,
upload_info: Dict[str, Any] upload_info: Dict[str, Any]
) -> Dict[str, Any]: ) -> Dict[str, Any]:
print_ongoing: bool = False
start_print: bool = upload_info['start_print']
# Verify that the operation can be done if attempting to upload a gcode # Verify that the operation can be done if attempting to upload a gcode
can_start: bool = False
try: try:
check_path: str = upload_info['dest_path'] check_path: str = upload_info['dest_path']
print_ongoing = await self._handle_operation_check( can_start = await self._handle_operation_check(check_path)
check_path)
except self.server.error as e: except self.server.error as e:
if e.status_code == 403: if e.status_code == 403:
raise self.server.error( raise self.server.error(
"File is loaded, upload not permitted", 403) "File is loaded, upload not permitted", 403)
else:
# Couldn't reach Klippy, so it should be safe
# to permit the upload but not start
start_print = False
# Don't start if another print is currently in progress
start_print = start_print and not print_ongoing
self.notify_sync_lock = NotifySyncLock(upload_info['dest_path']) self.notify_sync_lock = NotifySyncLock(upload_info['dest_path'])
finfo = await self._process_uploaded_file(upload_info) finfo = await self._process_uploaded_file(upload_info)
await self.gcode_metadata.parse_metadata( await self.gcode_metadata.parse_metadata(
upload_info['filename'], finfo).wait() upload_info['filename'], finfo).wait()
if start_print: started: bool = False
# Make a Klippy Request to "Start Print" queued: bool = False
kapis: APIComp = self.server.lookup_component('klippy_apis') if upload_info['start_print']:
try: if self.queue_gcodes:
await kapis.start_print(upload_info['filename']) job_queue: JobQueue = self.server.lookup_component('job_queue')
except self.server.error: started = await job_queue.queue_job(
# Attempt to start print failed upload_info['filename'], check_exists=False)
start_print = False queued = not started
elif can_start:
kapis: APIComp = self.server.lookup_component('klippy_apis')
try:
await kapis.start_print(upload_info['filename'])
except self.server.error:
# Attempt to start print failed
pass
else:
started = True
await self.notify_sync_lock.wait(300.) await self.notify_sync_lock.wait(300.)
self.notify_sync_lock = None self.notify_sync_lock = None
if queued:
self.server.send_event("file_manager:upload_queued",
upload_info['filename'])
return { return {
'item': { 'item': {
'path': upload_info['filename'], 'path': upload_info['filename'],
'root': "gcodes" 'root': "gcodes"
}, },
'print_started': start_print, 'print_started': started,
'print_queued': queued,
'action': "create_file" 'action': "create_file"
} }