|
1 | 1 | """Defines the different exceptions that may arise in the catalog subpackage""" |
2 | 2 |
|
| 3 | +import logging |
| 4 | + |
| 5 | +from aiohttp import web |
| 6 | +from common_library.error_codes import create_error_code |
| 7 | +from models_library.rest_error import ErrorGet |
3 | 8 | from servicelib.aiohttp import status |
| 9 | +from servicelib.logging_errors import create_troubleshotting_log_kwargs |
4 | 10 | from servicelib.rabbitmq.rpc_interfaces.catalog.errors import ( |
5 | 11 | CatalogForbiddenError, |
6 | 12 | CatalogItemNotFoundError, |
7 | 13 | ) |
8 | 14 |
|
9 | 15 | from ..exception_handling import ( |
| 16 | + ExceptionHandlersMap, |
10 | 17 | ExceptionToHttpErrorMap, |
11 | 18 | HttpErrorInfo, |
| 19 | + create_error_context_from_request, |
| 20 | + create_error_response, |
12 | 21 | exception_handling_decorator, |
13 | 22 | to_exceptions_handlers_map, |
14 | 23 | ) |
15 | 24 | from ..resource_usage.errors import DefaultPricingPlanNotFoundError |
16 | | -from .errors import DefaultPricingUnitForServiceNotFoundError |
| 25 | +from ._constants import MSG_CATALOG_SERVICE_NOT_FOUND, MSG_CATALOG_SERVICE_UNAVAILABLE |
| 26 | +from .errors import ( |
| 27 | + CatalogConnectionError, |
| 28 | + CatalogResponseError, |
| 29 | + DefaultPricingUnitForServiceNotFoundError, |
| 30 | +) |
17 | 31 |
|
18 | 32 | # mypy: disable-error-code=truthy-function |
19 | 33 | assert CatalogForbiddenError # nosec |
20 | 34 | assert CatalogItemNotFoundError # nosec |
21 | 35 |
|
22 | 36 |
|
| 37 | +_logger = logging.getLogger(__name__) |
| 38 | + |
| 39 | + |
| 40 | +async def _handler_catalog_response_errors( |
| 41 | + request: web.Request, exception: Exception |
| 42 | +) -> web.Response: |
| 43 | + |
| 44 | + assert isinstance( # nosec |
| 45 | + exception, CatalogResponseError | CatalogConnectionError |
| 46 | + ), f"check mapping, got {exception=}" |
| 47 | + |
| 48 | + if ( |
| 49 | + isinstance(exception, CatalogResponseError) |
| 50 | + and exception.status == status.HTTP_404_NOT_FOUND |
| 51 | + ): |
| 52 | + error = ErrorGet( |
| 53 | + status=status.HTTP_404_NOT_FOUND, |
| 54 | + message=MSG_CATALOG_SERVICE_NOT_FOUND, |
| 55 | + ) |
| 56 | + |
| 57 | + else: |
| 58 | + # NOTE: The remaining errors are mapped to 503 |
| 59 | + status_code = status.HTTP_503_SERVICE_UNAVAILABLE |
| 60 | + user_msg = MSG_CATALOG_SERVICE_UNAVAILABLE |
| 61 | + |
| 62 | + # Log for further investigation |
| 63 | + oec = create_error_code(exception) |
| 64 | + _logger.exception( |
| 65 | + **create_troubleshotting_log_kwargs( |
| 66 | + user_msg, |
| 67 | + error=exception, |
| 68 | + error_code=oec, |
| 69 | + error_context={ |
| 70 | + **create_error_context_from_request(request), |
| 71 | + "error_code": oec, |
| 72 | + }, |
| 73 | + ) |
| 74 | + ) |
| 75 | + error = ErrorGet.model_construct( |
| 76 | + message=user_msg, support_id=oec, status=status_code |
| 77 | + ) |
| 78 | + |
| 79 | + return create_error_response(error, status_code=error.status) |
| 80 | + |
| 81 | + |
23 | 82 | _TO_HTTP_ERROR_MAP: ExceptionToHttpErrorMap = { |
24 | 83 | CatalogItemNotFoundError: HttpErrorInfo( |
25 | 84 | status.HTTP_404_NOT_FOUND, |
|
37 | 96 | ), |
38 | 97 | } |
39 | 98 |
|
| 99 | + |
| 100 | +_exceptions_handlers_map: ExceptionHandlersMap = { |
| 101 | + CatalogResponseError: _handler_catalog_response_errors, |
| 102 | + CatalogConnectionError: _handler_catalog_response_errors, |
| 103 | +} |
| 104 | +_exceptions_handlers_map.update(to_exceptions_handlers_map(_TO_HTTP_ERROR_MAP)) |
| 105 | + |
40 | 106 | handle_plugin_requests_exceptions = exception_handling_decorator( |
41 | | - to_exceptions_handlers_map(_TO_HTTP_ERROR_MAP) |
| 107 | + _exceptions_handlers_map |
42 | 108 | ) |
43 | 109 |
|
44 | 110 |
|
|
0 commit comments