Server: updated server_exception_handler.py and also error_codes.py to cover all custom exceptions
This commit is contained in:
@@ -30,6 +30,27 @@ class AuthErrorCode(StrEnum):
|
||||
|
||||
class DAQErrorCode(StrEnum):
|
||||
BEAMLINE_BUSY = "BEAMLINE_BUSY"
|
||||
MOUNTING_FAILED = "MOUNTING_FAILED"
|
||||
UNMOUNTING_FAILED = "UNMOUNTING_FAILED"
|
||||
LOOP_CENTERING_FAILED = "LOOP_CENTERING_FAILED"
|
||||
AXC_FAILED = "AXC_FAILED"
|
||||
TRANSFORMATION_INVALID = "TRANSFORMATION_INVALID"
|
||||
SAMPLE_NOT_FOUND = "SAMPLE_NOT_FOUND"
|
||||
DATA_COLLECTION_FAILED = "DATA_COLLECTION_FAILED"
|
||||
RASTER_SCAN_FAILED = "RASTER_SCAN_FAILED"
|
||||
TELL_WARNING = "TELL_WARNING"
|
||||
TELL_CRITICAL = "TELL_CRITICAL"
|
||||
SMARGON_UNAVAILABLE = "SMARGON_UNAVAILABLE"
|
||||
TELL_UNAVAILABLE = "TELL_UNAVAILABLE"
|
||||
TELL_CONNECTION_ERROR = "TELL_CONNECTION_ERROR"
|
||||
TELL_MOUNT_FAILED = "TELL_MOUNT_FAILED"
|
||||
TELL_BUSY = "TELL_BUSY"
|
||||
MANUAL_MOUNT_REQUIRED = "MANUAL_MOUNT_REQUIRED"
|
||||
SMART_MAGNET_FAULT = "SMART_MAGNET_FAULT"
|
||||
JFJOCH_UNAVAILABLE = "JFJOCH_UNAVAILABLE"
|
||||
AEROTECH_UNAVAILABLE = "AEROTECH_UNAVAILABLE"
|
||||
AAREDB_UNAVAILABLE = "AAREDB_UNAVAILABLE"
|
||||
MAGNET_POSITION_SENSOR_ERROR = "MAGNET_POSITION_SENSOR_ERROR"
|
||||
|
||||
_ERROR_CODE_HELP: dict[str, str] = {
|
||||
# Auth/JWT
|
||||
@@ -73,7 +94,70 @@ _ERROR_CODE_HELP: dict[str, str] = {
|
||||
"Beamline state is set to Busy by prior action. If this state persists an additional error may have occurred, "
|
||||
"preventing the state from being released, this should timeout within 10 minutes."
|
||||
"If this occurs please seek assistance from your local contact."
|
||||
)
|
||||
),
|
||||
DAQErrorCode.MOUNTING_FAILED: (
|
||||
"The requested sample could not be mounted. Check TELL/robot state, sample location, and hardware readiness."
|
||||
),
|
||||
DAQErrorCode.UNMOUNTING_FAILED: (
|
||||
"The mounted sample could not be unmounted. Check robot state and whether the sample changer is ready."
|
||||
),
|
||||
DAQErrorCode.LOOP_CENTERING_FAILED: (
|
||||
"Automatic loop centering failed to locate or position the sample reliably."
|
||||
),
|
||||
DAQErrorCode.AXC_FAILED: (
|
||||
"Automatic X-ray centering failed. Verify sample visibility, alignment, and detector/beam conditions."
|
||||
),
|
||||
DAQErrorCode.TRANSFORMATION_INVALID: (
|
||||
"The requested beamline state transition is not allowed from the current state."
|
||||
),
|
||||
DAQErrorCode.SAMPLE_NOT_FOUND: (
|
||||
"The requested sample could not be found in the available sample lists."
|
||||
),
|
||||
DAQErrorCode.DATA_COLLECTION_FAILED: (
|
||||
"Rotation/data collection failed before a valid result was produced."
|
||||
),
|
||||
DAQErrorCode.RASTER_SCAN_FAILED: (
|
||||
"Raster scan failed before a valid result was produced."
|
||||
),
|
||||
DAQErrorCode.TELL_WARNING: (
|
||||
"TELL reported a warning condition. The request may not have completed cleanly."
|
||||
),
|
||||
DAQErrorCode.TELL_CRITICAL: (
|
||||
"TELL reported a critical error condition requiring operator attention."
|
||||
),
|
||||
DAQErrorCode.SMARGON_UNAVAILABLE: (
|
||||
"Smargon communication failed or the controller is unavailable."
|
||||
),
|
||||
DAQErrorCode.TELL_UNAVAILABLE: (
|
||||
"TELL communication failed or the service is unavailable."
|
||||
),
|
||||
DAQErrorCode.TELL_CONNECTION_ERROR: (
|
||||
"The server could not establish or maintain a connection to TELL."
|
||||
),
|
||||
DAQErrorCode.TELL_MOUNT_FAILED: (
|
||||
"TELL reported that the mount/unmount operation failed."
|
||||
),
|
||||
DAQErrorCode.TELL_BUSY: (
|
||||
"A TELL command was requested while TELL was still busy processing another action."
|
||||
),
|
||||
DAQErrorCode.MANUAL_MOUNT_REQUIRED: (
|
||||
"Automatic mounting could not proceed and manual intervention is required."
|
||||
),
|
||||
DAQErrorCode.SMART_MAGNET_FAULT: (
|
||||
"The smart magnet system reported a fault or unsafe condition."
|
||||
),
|
||||
DAQErrorCode.JFJOCH_UNAVAILABLE: (
|
||||
"JFJoch detector communication failed or the detector service is unavailable."
|
||||
),
|
||||
DAQErrorCode.AEROTECH_UNAVAILABLE: (
|
||||
"Aerotech communication failed or the motion controller is unavailable."
|
||||
),
|
||||
DAQErrorCode.AAREDB_UNAVAILABLE: (
|
||||
"AareDB communication failed or the database service is unavailable."
|
||||
),
|
||||
DAQErrorCode.MAGNET_POSITION_SENSOR_ERROR: (
|
||||
"The magnet position sensor reported an invalid or unsafe state."
|
||||
),
|
||||
}
|
||||
|
||||
def error_code_help(code: str) -> str | None:
|
||||
|
||||
@@ -21,6 +21,17 @@ from aare.common.exception_handler import (
|
||||
TellCommunicationError,
|
||||
JFJochCommunicationError,
|
||||
AerotechCommunicationError,
|
||||
DataCollectionException,
|
||||
RasterScanException,
|
||||
UnmountingFailed,
|
||||
AXCFailed,
|
||||
AareDBCommunicationError,
|
||||
MagnetPositionSensorErorr,
|
||||
ManualMountException,
|
||||
SmartMagnetFaultException,
|
||||
TellMountFailedException,
|
||||
TellCommandWhileBusyException,
|
||||
TellConnectionException,
|
||||
)
|
||||
|
||||
logger = setup_logger("aareDAQ")
|
||||
@@ -56,6 +67,13 @@ def register_exception_handlers(app) -> None:
|
||||
content=_error_payload(code="MOUNTING_FAILED", message=str(exc)),
|
||||
)
|
||||
|
||||
@app.exception_handler(UnmountingFailed)
|
||||
async def unmounting_failed_handler(request: Request, exc: UnmountingFailed) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content=_error_payload(code="UNMOUNTING_FAILED", message=str(exc) or "Failed to unmount sample"),
|
||||
)
|
||||
|
||||
@app.exception_handler(WarningTellException)
|
||||
async def warning_tell_handler(request: Request, exc: WarningTellException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
@@ -77,6 +95,13 @@ def register_exception_handlers(app) -> None:
|
||||
content=_error_payload(code="LOOP_CENTERING_FAILED", message=str(exc)),
|
||||
)
|
||||
|
||||
@app.exception_handler(AXCFailed)
|
||||
async def axc_failed_handler(request: Request, exc: AXCFailed) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content=_error_payload(code="AXC_FAILED", message=str(exc) or "Auto X-ray centering failed"),
|
||||
)
|
||||
|
||||
@app.exception_handler(TransformationInvalidException)
|
||||
async def transformation_invalid_handler(request: Request, exc: TransformationInvalidException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
@@ -91,6 +116,20 @@ def register_exception_handlers(app) -> None:
|
||||
content=_error_payload(code="BEAMLINE_BUSY", message=str(exc) or "Beamline is busy"),
|
||||
)
|
||||
|
||||
@app.exception_handler(DataCollectionException)
|
||||
async def data_collection_failed_handler(request: Request, exc: DataCollectionException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content=_error_payload(code="DATA_COLLECTION_FAILED", message=str(exc) or "Data collection failed"),
|
||||
)
|
||||
|
||||
@app.exception_handler(RasterScanException)
|
||||
async def raster_scan_failed_handler(request: Request, exc: RasterScanException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content=_error_payload(code="RASTER_SCAN_FAILED", message=str(exc) or "Raster scan failed"),
|
||||
)
|
||||
|
||||
@app.exception_handler(AuthenticationException)
|
||||
async def authentication_exception_handler(request: Request, exc: AuthenticationException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
@@ -120,6 +159,41 @@ def register_exception_handlers(app) -> None:
|
||||
content=_error_payload(code="SAMPLE_NOT_FOUND", message=str(exc) or "Sample not found"),
|
||||
)
|
||||
|
||||
@app.exception_handler(ManualMountException)
|
||||
async def manual_mount_handler(request: Request, exc: ManualMountException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_409_CONFLICT,
|
||||
content=_error_payload(code="MANUAL_MOUNT_REQUIRED", message=str(exc) or "Manual mount intervention required"),
|
||||
)
|
||||
|
||||
@app.exception_handler(SmartMagnetFaultException)
|
||||
async def smart_magnet_fault_handler(request: Request, exc: SmartMagnetFaultException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
content=_error_payload(code="SMART_MAGNET_FAULT", message=str(exc) or "Smart magnet fault"),
|
||||
)
|
||||
|
||||
@app.exception_handler(TellMountFailedException)
|
||||
async def tell_mount_failed_handler(request: Request, exc: TellMountFailedException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_409_CONFLICT,
|
||||
content=_error_payload(code="TELL_MOUNT_FAILED", message=str(exc) or "TELL mount failed"),
|
||||
)
|
||||
|
||||
@app.exception_handler(TellCommandWhileBusyException)
|
||||
async def tell_busy_handler(request: Request, exc: TellCommandWhileBusyException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_409_CONFLICT,
|
||||
content=_error_payload(code="TELL_BUSY", message=str(exc) or "TELL is busy"),
|
||||
)
|
||||
|
||||
@app.exception_handler(TellConnectionException)
|
||||
async def tell_connection_error_handler(request: Request, exc: TellConnectionException) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
content=_error_payload(code="TELL_CONNECTION_ERROR", message=str(exc) or "TELL connection error"),
|
||||
)
|
||||
|
||||
@app.exception_handler(SmargonCommunicationError)
|
||||
async def smargon_comm_handler(request: Request, exc: SmargonCommunicationError) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
@@ -134,6 +208,21 @@ def register_exception_handlers(app) -> None:
|
||||
),
|
||||
)
|
||||
|
||||
@app.exception_handler(AareDBCommunicationError)
|
||||
async def aaredb_comm_handler(request: Request, exc: AareDBCommunicationError) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
content=_error_payload(
|
||||
code="AAREDB_UNAVAILABLE",
|
||||
message=str(exc) or "AareDB is unavailable",
|
||||
extra={
|
||||
"operation": getattr(exc, "operation", None),
|
||||
"endpoint": getattr(exc, "endpoint", None),
|
||||
"base_url": getattr(exc, "base_url", None),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
@app.exception_handler(TellCommunicationError)
|
||||
async def tell_comm_handler(request: Request, exc: TellCommunicationError) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
@@ -178,6 +267,16 @@ def register_exception_handlers(app) -> None:
|
||||
),
|
||||
)
|
||||
|
||||
@app.exception_handler(MagnetPositionSensorErorr)
|
||||
async def magnet_position_sensor_handler(request: Request, exc: MagnetPositionSensorErorr) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=api_status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
content=_error_payload(
|
||||
code="MAGNET_POSITION_SENSOR_ERROR",
|
||||
message=str(exc) or "Magnet position sensor error",
|
||||
),
|
||||
)
|
||||
|
||||
@app.exception_handler(Exception)
|
||||
async def unhandled_exception_handler(request: Request, exc: Exception) -> JSONResponse:
|
||||
logger.exception(f"Unhandled server exception: {exc}")
|
||||
|
||||
Reference in New Issue
Block a user