From d78ddd6c1748765bc7ab8cd5a712737f7500478f Mon Sep 17 00:00:00 2001 From: jelle Spijker Date: Mon, 12 Oct 2020 16:55:57 +0200 Subject: [PATCH 1/3] Created Print job upload Queue Full Message This message is shown to the user in Cura when the digital factory returns a 409, because the queue is full CURA-7760 sending multiple printjobs notifications --- .../PrintJobUploadQueueFullMessage.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadQueueFullMessage.py diff --git a/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadQueueFullMessage.py b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadQueueFullMessage.py new file mode 100644 index 0000000000..dc910e9e1b --- /dev/null +++ b/plugins/UM3NetworkPrinting/src/Messages/PrintJobUploadQueueFullMessage.py @@ -0,0 +1,19 @@ +# Copyright (c) 2020 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM import i18nCatalog +from UM.Message import Message + + +I18N_CATALOG = i18nCatalog("cura") + + +class PrintJobUploadQueueFullMessage(Message): + """Message shown when uploading a print job to a cluster and the print queue is full.""" + + def __init__(self) -> None: + super().__init__( + text = I18N_CATALOG.i18nc("@info:status", "Print job queue is full. The printer can't accept a new job."), + title = I18N_CATALOG.i18nc("@info:title", "Queue Full"), + lifetime = 10 + ) From 0e14eef47df4e21f6a6a1779648295ebb5b410e5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Oct 2020 17:31:53 +0200 Subject: [PATCH 2/3] Allow for a callback when the HttpRequestManager doesn't catch the error There are really two types of errors that the HttpRequestManager can throw: Errors that it understands and errors that it doesn't understand. We must now intercept an error that it doesn't understand. Contributes to issue CURA-7760. --- plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py index 713ee25170..7b8be4b2c2 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py @@ -127,12 +127,16 @@ class CloudApiClient: # \param cluster_id: The ID of the cluster. # \param job_id: The ID of the print job. # \param on_finished: The function to be called after the result is parsed. - def requestPrint(self, cluster_id: str, job_id: str, on_finished: Callable[[CloudPrintResponse], Any]) -> None: + # \param on_error: A function to be called if there was a server-side problem uploading. Generic errors (not + # specific to sending print jobs) such as lost connection, unparsable responses, etc. are not returned here, but + # handled in a generic way by the CloudApiClient. + def requestPrint(self, cluster_id: str, job_id: str, on_finished: Callable[[CloudPrintResponse], Any], on_error) -> None: url = "{}/clusters/{}/print/{}".format(self.CLUSTER_API_ROOT, cluster_id, job_id) self._http.post(url, scope = self._scope, data = b"", callback = self._parseCallback(on_finished, CloudPrintResponse), + error_callback = on_error, timeout = self.DEFAULT_REQUEST_TIMEOUT) def doPrintJobAction(self, cluster_id: str, cluster_job_id: str, action: str, From bcb30caf982581a4051fc2d2ccb5fc30a0c1237e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 13 Oct 2020 17:32:47 +0200 Subject: [PATCH 3/3] Show error message when print job queue is full on the printer Implements issue CURA-7760. --- .../src/Cloud/CloudOutputDevice.py | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 63c11ba484..9314e067a2 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -3,10 +3,11 @@ from time import time import os -from typing import List, Optional, cast +from typing import cast, List, Optional, TYPE_CHECKING from PyQt5.QtCore import QObject, QUrl, pyqtProperty, pyqtSignal, pyqtSlot from PyQt5.QtGui import QDesktopServices +from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest # Parse errors specific to print job uploading. from UM import i18nCatalog from UM.Backend.Backend import BackendState @@ -23,6 +24,7 @@ from ..ExportFileJob import ExportFileJob from ..UltimakerNetworkedPrinterOutputDevice import UltimakerNetworkedPrinterOutputDevice from ..Messages.PrintJobUploadBlockedMessage import PrintJobUploadBlockedMessage from ..Messages.PrintJobUploadErrorMessage import PrintJobUploadErrorMessage +from ..Messages.PrintJobUploadQueueFullMessage import PrintJobUploadQueueFullMessage from ..Messages.PrintJobUploadSuccessMessage import PrintJobUploadSuccessMessage from ..Models.Http.CloudClusterResponse import CloudClusterResponse from ..Models.Http.CloudClusterStatus import CloudClusterStatus @@ -194,7 +196,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): # The mesh didn't change, let's not upload it to the cloud again. # Note that self.writeFinished is called in _onPrintUploadCompleted as well. if self._uploaded_print_job: - self._api.requestPrint(self.key, self._uploaded_print_job.job_id, self._onPrintUploadCompleted) + self._api.requestPrint(self.key, self._uploaded_print_job.job_id, self._onPrintUploadCompleted, self._onPrintUploadSpecificError) return # Export the scene to the correct file type. @@ -240,7 +242,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): if not print_job: # It's possible that another print job is requested in the meanwhile, which then fails to upload with an error, which sets self._uploaded_print_job to `None`. # TODO: Maybe _onUploadError shouldn't set the _uploaded_print_job to None or we need to prevent such asynchronous cases. return # Prevent a crash. - self._api.requestPrint(self.key, print_job.job_id, self._onPrintUploadCompleted) + self._api.requestPrint(self.key, print_job.job_id, self._onPrintUploadCompleted, self._onPrintUploadSpecificError) def _onPrintUploadCompleted(self, response: CloudPrintResponse) -> None: """Shows a message when the upload has succeeded @@ -251,9 +253,23 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): PrintJobUploadSuccessMessage().show() self.writeFinished.emit() - def _onUploadError(self, message: str = None) -> None: - """Displays the given message if uploading the mesh has failed + def _onPrintUploadSpecificError(self, reply: "QNetworkReply", _: "QNetworkReply.NetworkError"): + """ + Displays a message when an error occurs specific to uploading print job (i.e. queue is full). + """ + error_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) + if error_code == 409: + PrintJobUploadQueueFullMessage().show() + else: + PrintJobUploadErrorMessage(I18N_CATALOG.i18nc("@error:send", "Unknown error code when uploading print job: {0}", error_code)).show() + self._progress.hide() + self._uploaded_print_job = None + self.writeError.emit() + + def _onUploadError(self, message: str = None) -> None: + """ + Displays the given message if uploading the mesh has failed due to a generic error (i.e. lost connection). :param message: The message to display. """ self._progress.hide()