Просмотр исходного кода

Improve error-handling per printer

We can now know which printers failed to sync and which succeeded.

Contributes to issue CURA-8609.
Ghostkeeper 3 лет назад
Родитель
Сommit
54d51536b0
1 измененных файлов с 28 добавлено и 17 удалено
  1. 28 17
      cura/PrinterOutput/UploadMaterialsJob.py

+ 28 - 17
cura/PrinterOutput/UploadMaterialsJob.py

@@ -18,13 +18,14 @@ from UM.Signal import Signal
 from UM.TaskManagement.HttpRequestManager import HttpRequestManager  # To call the API.
 from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope
 
-catalog = i18nCatalog("cura")
-
 from typing import Optional, TYPE_CHECKING
 if TYPE_CHECKING:
     from PyQt5.QtNetwork import QNetworkReply
     from cura.UltimakerCloud.CloudMaterialSync import CloudMaterialSync
 
+catalog = i18nCatalog("cura")
+
+
 class UploadMaterialsJob(Job):
     """
     Job that uploads a set of materials to the Digital Factory.
@@ -43,6 +44,9 @@ class UploadMaterialsJob(Job):
         self._scope = JsonDecoratorScope(UltimakerCloudScope(cura.CuraApplication.CuraApplication.getInstance()))  # type: JsonDecoratorScope
         self._archive_filename = None  # type: Optional[str]
         self._archive_remote_id = None  # type: Optional[str]  # ID that the server gives to this archive. Used to communicate about the archive to the server.
+        self._num_synced_printers = 0
+        self._completed_printers = set()  # The printers that have successfully completed the upload.
+        self._failed_printers = set()
 
     uploadCompleted = Signal()
     uploadProgressChanged = Signal()
@@ -111,13 +115,15 @@ class UploadMaterialsJob(Job):
             self.uploadCompleted.emit(self.getResult(), self.getError())
             return
 
-        for container_stack in CuraContainerRegistry.getInstance().findContainerStacksMetadata(type = "machine"):
-            if container_stack.get("connection_type", -1) != 3:  # Not a cloud printer.
-                continue  # Only upload to cloud printers.
-            if not container_stack.get("is_online", False):  # Not online.
-                continue  # Only upload to online printers.
-            if "host_guid" not in container_stack or "um_cloud_cluster_id" not in container_stack:
-                continue  # Incomplete information about cloud printer.
+        online_cloud_printers = CuraContainerRegistry.getInstance().findContainerStacksMetadata(
+            type = "machine",
+            connection_type = 3,  # Only cloud printers.
+            is_online = True,  # Only online printers. Otherwise the server gives an error.
+            host_guid = "*",  # Required metadata field. Otherwise we get a KeyError.
+            um_cloud_cluster_id = "*"  # Required metadata field. Otherwise we get a KeyError.
+        )
+        self._num_synced_printers = len(online_cloud_printers)
+        for container_stack in online_cloud_printers:
             cluster_id = container_stack["um_cloud_cluster_id"]
             printer_id = container_stack["host_guid"]
 
@@ -125,20 +131,24 @@ class UploadMaterialsJob(Job):
             http.get(
                 url = self.UPLOAD_CONFIRM_URL.format(cluster_id = cluster_id, cluster_printer_id = printer_id),
                 callback = functools.partialmethod(self.onUploadConfirmed, printer_id),
-                error_callback = self.onError,
+                error_callback = functools.partialmethod(self.onUploadConfirmed, printer_id),  # Let this same function handle the error too.
                 scope = self._scope
             )
 
     def onUploadConfirmed(self, printer_id: str, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"]) -> None:
         if error is not None:
             Logger.error(f"Failed to confirm uploading material archive to printer {printer_id}: {error}")
-            self.setError(UploadMaterialsError(catalog.i18nc("@text:error", "Failed to connect to Digital Factory.")))
-            self.setResult(self.Result.FAILED)
+            self._failed_printers.add(printer_id)
+        else:
+            self._completed_printers.add(printer_id)
+
+        if len(self._completed_printers) + len(self._failed_printers) >= self._num_synced_printers:  # This is the last response to be processed.
+            if self._failed_printers:
+                self.setResult(self.Result.FAILED)
+                self.setError(UploadMaterialsError(catalog.i18nc("@text:error", "Failed to connect to Digital Factory to sync materials with some of the printers.")))
+            else:
+                self.setResult(self.Result.SUCCESS)
             self.uploadCompleted.emit(self.getResult(), self.getError())
-            return
-
-        self.setResult(self.Result.SUCCCESS)
-        self.uploadCompleted.emit(self.getResult(), self.getError())
 
     def onError(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"]):
         Logger.error(f"Failed to upload material archive: {error}")
@@ -146,8 +156,9 @@ class UploadMaterialsJob(Job):
         self.setError(UploadMaterialsError(catalog.i18nc("@text:error", "Failed to connect to Digital Factory.")))
         self.uploadCompleted.emit(self.getResult(), self.getError())
 
+
 class UploadMaterialsError(Exception):
     """
     Marker class to indicate something went wrong while uploading.
     """
-    pass
+    pass