@@ -96,10 +96,6 @@ def _is_modeler_batch(resource_id: str) -> bool:
9696 return BatchTask .is_batch (resource_id )
9797
9898
99- def _batch_detail (resource_id : str ) -> BatchDetail :
100- return BatchTask (resource_id ).detail ()
101-
102-
10399def _batch_detail_error (resource_id : str ) -> Optional [WebError ]:
104100 """Processes a failed batch job to generate a detailed error.
105101
@@ -759,14 +755,7 @@ def _get_batch_detail_handle_error_status(task_id: TaskId) -> str:
759755 detail = batch .detail ()
760756 status = detail .status .lower ()
761757 if status in ERROR_STATES :
762- try :
763- # TODO Try to obtain the error message
764- error_msg = "Error message could not be obtained, please contact customer support."
765- except Exception :
766- # If the error message could not be obtained, raise a generic error message
767- error_msg = "Error message could not be obtained, please contact customer support."
768-
769- raise WebError (f"Error running task { task_id } ! { error_msg } " )
758+ _batch_detail_error (task_id )
770759 return detail
771760
772761
@@ -1003,9 +992,9 @@ def abort(task_id: TaskId) -> Optional[TaskInfo]:
1003992 )
1004993 if _is_modeler_batch (task_id ):
1005994 detail = task .detail ()
1006- return TaskInfo (** {"taskId" : detail . batch_id , "taskType" : "RF" , ** detail .dict ()})
995+ return TaskInfo (** {"taskId" : task_id , "taskType" : "RF" , ** detail .dict ()})
1007996 else :
1008- return TaskInfo (** {"taskId" : task . task_id , ** task .dict ()})
997+ return TaskInfo (** {"taskId" : task_id , ** task .dict ()})
1009998
1010999
10111000@wait_for_connection
@@ -1211,7 +1200,7 @@ def load(
12111200 if verbose and task_id is not None :
12121201 console = get_logging_console ()
12131202 if _is_modeler_batch (task_id ):
1214- console .log (f"loading component modeler data from { path } " )
1203+ console .log (f"Loading component modeler data from { path } " )
12151204 else :
12161205 console .log (f"Loading simulation from { path } " )
12171206
@@ -1243,36 +1232,37 @@ def load(
12431232 return stub_data
12441233
12451234
1235+ def _status_to_stage (status : str ) -> tuple [str , int ]:
1236+ """Map task status to monotonic stage for progress bars."""
1237+ s = (status or "" ).lower ()
1238+ # Map a broader set of states to monotonic stages for progress bars
1239+ if s in ("draft" , "created" ):
1240+ return ("draft" , 0 )
1241+ if s in ("queue" , "queued" ):
1242+ return ("queued" , 1 )
1243+ if s in ("preprocess" , "preprocessing" ):
1244+ return ("preprocess" , 1 )
1245+ if s in ("validating" ,):
1246+ return ("validating" , 2 )
1247+ if s in ("validate_success" , "validate_warn" ):
1248+ return ("validate" , 3 )
1249+ if s in ("running" , "preprocess_success" ):
1250+ return ("running" , 4 )
1251+ if s in ("run_success" , "postprocess" ):
1252+ return ("postprocess" , 5 )
1253+ if s in ("success" , "postprocess_success" ):
1254+ return ("success" , 6 )
1255+ # Unknown states map to earliest stage to avoid showing 100% prematurely
1256+ return (s or "unknown" , 0 )
1257+
1258+
12461259def _monitor_modeler_batch (
12471260 batch_id : str ,
12481261 verbose : bool = True ,
12491262 max_detail_tasks : int = 20 ,
12501263) -> None :
12511264 """Monitor modeler batch progress with aggregate and per-task views."""
12521265 console = get_logging_console () if verbose else None
1253-
1254- def _status_to_stage (status : str ) -> tuple [str , int ]:
1255- s = (status or "" ).lower ()
1256- # Map a broader set of states to monotonic stages for progress bars
1257- if s in ("draft" , "created" ):
1258- return ("draft" , 0 )
1259- if s in ("queue" , "queued" ):
1260- return ("queued" , 1 )
1261- if s in ("preprocess" ,):
1262- return ("preprocess" , 1 )
1263- if s in ("validating" ,):
1264- return ("validating" , 2 )
1265- if s in ("validate_success" , "validate_warn" ):
1266- return ("validate" , 3 )
1267- if s in ("running" , "preprocess_success" ):
1268- return ("running" , 4 )
1269- if s in ("postprocess" ,):
1270- return ("postprocess" , 5 )
1271- if s in ("run_success" , "success" , "postprocess_success" ):
1272- return ("success" , 6 )
1273- # Unknown states map to earliest stage to avoid showing 100% prematurely
1274- return (s or "unknown" , 0 )
1275-
12761266 detail = _get_batch_detail_handle_error_status (batch_id )
12771267 name = detail .name or "modeler_batch"
12781268 group_id = detail .groupId
@@ -1312,7 +1302,7 @@ def _status_to_stage(status: str) -> tuple[str, int]:
13121302 r = detail .runSuccess or 0
13131303 if status != prev_status :
13141304 prev_status = status
1315- console .log (f"Batch status = { status } " )
1305+ console .log (f"Batch status = { _status_to_stage ( status )[ 0 ] } " )
13161306
13171307 # Create per-task bars as soon as tasks appear
13181308 if total and total <= max_detail_tasks and detail .tasks :
@@ -1636,42 +1626,24 @@ def real_cost(task_id: str, verbose: bool = True) -> float | None:
16361626 )
16371627
16381628 console = get_logging_console () if verbose else None
1639- if _is_modeler_batch (task_id ):
1640- status = _batch_detail (task_id ).status .lower ()
1641- flex_unit = _batch_detail (task_id ).realFlexUnit or None
1642- if (status not in ["success" , "run_success" ]) or (flex_unit is None ):
1643- log .warning (
1644- f"Billed FlexCredit for task '{ task_id } ' is not available. If the task has been "
1645- "successfully run, it should be available shortly. If this issue persists, contact customer support."
1646- )
1647- else :
1648- if verbose :
1629+ task_info = get_info (task_id )
1630+ flex_unit = task_info .realFlexUnit
1631+ ori_flex_unit = getattr (task_info , "oriRealFlexUnit" , flex_unit )
1632+ if not flex_unit :
1633+ log .warning (
1634+ f"Billed FlexCredit for task '{ task_id } ' is not available. If the task has been "
1635+ "successfully run, it should be available shortly."
1636+ )
1637+ else :
1638+ if verbose :
1639+ console .log (f"Billed flex credit cost: { flex_unit :1.3f} ." )
1640+ if flex_unit != ori_flex_unit and task_info .taskType == "FDTD" :
16491641 console .log (
1650- f"Billed FlexCredit cost: { flex_unit :1.3f } . Minimum cost depends on "
1651- "task execution details. Use 'web.real_cost(task_id)' to get the billed FlexCredit "
1652- "cost after a simulation run ."
1642+ "Note: the task cost pro-rated due to early shutoff was below the minimum "
1643+ "threshold, due to fast shutoff. Decreasing the simulation 'run_time' should "
1644+ "decrease the estimated, and correspondingly the billed cost of such tasks ."
16531645 )
1654-
1655- return flex_unit
1656- else :
1657- task_info = get_info (task_id )
1658- flex_unit = task_info .realFlexUnit
1659- ori_flex_unit = task_info .oriRealFlexUnit
1660- if not flex_unit :
1661- log .warning (
1662- f"Billed FlexCredit for task '{ task_id } ' is not available. If the task has been "
1663- "successfully run, it should be available shortly."
1664- )
1665- else :
1666- if verbose :
1667- console .log (f"Billed flex credit cost: { flex_unit :1.3f} ." )
1668- if flex_unit != ori_flex_unit and task_info .taskType == "FDTD" :
1669- console .log (
1670- "Note: the task cost pro-rated due to early shutoff was below the minimum "
1671- "threshold, due to fast shutoff. Decreasing the simulation 'run_time' should "
1672- "decrease the estimated, and correspondingly the billed cost of such tasks."
1673- )
1674- return flex_unit
1646+ return flex_unit
16751647
16761648
16771649@wait_for_connection
0 commit comments