qena-shared-lib 0.1.7__py3-none-any.whl → 0.1.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qena_shared_lib/application.py +2 -2
- qena_shared_lib/exception_handlers.py +69 -44
- qena_shared_lib/exceptions.py +187 -85
- qena_shared_lib/http.py +20 -20
- qena_shared_lib/logstash/_base.py +2 -2
- qena_shared_lib/rabbitmq/__init__.py +6 -6
- qena_shared_lib/rabbitmq/_base.py +20 -17
- qena_shared_lib/rabbitmq/_exception_handlers.py +58 -71
- qena_shared_lib/rabbitmq/_listener.py +109 -42
- qena_shared_lib/rabbitmq/_publisher.py +2 -1
- qena_shared_lib/rabbitmq/_rpc_client.py +13 -6
- qena_shared_lib/scheduler.py +5 -0
- qena_shared_lib/security.py +3 -3
- {qena_shared_lib-0.1.7.dist-info → qena_shared_lib-0.1.9.dist-info}/METADATA +155 -22
- qena_shared_lib-0.1.9.dist-info/RECORD +29 -0
- qena_shared_lib/rabbitmq/_exceptions.py +0 -46
- qena_shared_lib-0.1.7.dist-info/RECORD +0 -30
- {qena_shared_lib-0.1.7.dist-info → qena_shared_lib-0.1.9.dist-info}/WHEEL +0 -0
qena_shared_lib/application.py
CHANGED
@@ -9,8 +9,8 @@ from starlette.types import Lifespan
|
|
9
9
|
|
10
10
|
from .exception_handlers import (
|
11
11
|
handle_general_http_exception,
|
12
|
+
handle_http_service_error,
|
12
13
|
handle_request_validation_error,
|
13
|
-
handle_service_exception,
|
14
14
|
)
|
15
15
|
from .exceptions import ServiceException
|
16
16
|
from .http import ControllerBase
|
@@ -153,7 +153,7 @@ class Builder:
|
|
153
153
|
)
|
154
154
|
app.state.container = self._container
|
155
155
|
|
156
|
-
app.exception_handler(ServiceException)(
|
156
|
+
app.exception_handler(ServiceException)(handle_http_service_error)
|
157
157
|
app.exception_handler(RequestValidationError)(
|
158
158
|
handle_request_validation_error
|
159
159
|
)
|
@@ -7,18 +7,23 @@ from fastapi.responses import JSONResponse
|
|
7
7
|
from pydantic_core import to_jsonable_python
|
8
8
|
|
9
9
|
from .dependencies.http import get_service
|
10
|
-
from .exceptions import
|
10
|
+
from .exceptions import (
|
11
|
+
HTTPServiceError,
|
12
|
+
RabbitMQServiceException,
|
13
|
+
ServiceException,
|
14
|
+
Severity,
|
15
|
+
)
|
11
16
|
from .logging import LoggerProvider
|
12
17
|
from .logstash._base import BaseLogstashSender
|
13
18
|
|
14
19
|
__all__ = [
|
15
|
-
"
|
20
|
+
"handle_http_service_error",
|
16
21
|
"handle_request_validation_error",
|
17
22
|
"handle_general_http_exception",
|
18
23
|
]
|
19
24
|
|
20
25
|
|
21
|
-
def
|
26
|
+
def handle_http_service_error(
|
22
27
|
request: Request, exception: ServiceException
|
23
28
|
) -> Response:
|
24
29
|
logstash = get_service(app=request.app, service_key=BaseLogstashSender)
|
@@ -32,20 +37,12 @@ def handle_service_exception(
|
|
32
37
|
request.url.path,
|
33
38
|
exception.__class__.__name__,
|
34
39
|
]
|
35
|
-
|
36
|
-
if exception.tags:
|
37
|
-
exception.tags.extend(tags)
|
38
|
-
|
39
40
|
extra = {
|
40
41
|
"serviceType": "HTTP",
|
41
42
|
"method": request.method,
|
42
43
|
"path": request.url.path,
|
43
44
|
"exception": exception.__class__.__name__,
|
44
45
|
}
|
45
|
-
|
46
|
-
if exception.extra:
|
47
|
-
exception.extra.update(extra)
|
48
|
-
|
49
46
|
exc_info = (
|
50
47
|
(type(exception), exception, exception.__traceback__)
|
51
48
|
if exception.extract_exc_info
|
@@ -64,11 +61,68 @@ def handle_service_exception(
|
|
64
61
|
logstash_logger_method = logstash.error
|
65
62
|
logger_method = logger.error
|
66
63
|
|
64
|
+
content: dict[str, Any] = {
|
65
|
+
"severity": exception_severity.name,
|
66
|
+
"message": message,
|
67
|
+
}
|
68
|
+
status_code = _status_code_from_severity(exception.severity)
|
69
|
+
headers = None
|
70
|
+
|
71
|
+
match exception:
|
72
|
+
case HTTPServiceError() as http_service_error:
|
73
|
+
if http_service_error.body is not None:
|
74
|
+
extra_body = to_jsonable_python(http_service_error.body)
|
75
|
+
is_updated = False
|
76
|
+
|
77
|
+
try:
|
78
|
+
if isinstance(extra_body, Iterable):
|
79
|
+
content.update(extra_body)
|
80
|
+
|
81
|
+
is_updated = True
|
82
|
+
except:
|
83
|
+
pass
|
84
|
+
|
85
|
+
if not is_updated:
|
86
|
+
content["data"] = extra_body
|
87
|
+
|
88
|
+
if http_service_error.response_code is not None:
|
89
|
+
content["code"] = http_service_error.response_code
|
90
|
+
str_response_code = str(http_service_error.response_code)
|
91
|
+
extra["responseCode"] = str_response_code
|
92
|
+
|
93
|
+
tags.append(str_response_code)
|
94
|
+
|
95
|
+
if http_service_error.corrective_action is not None:
|
96
|
+
content["correctiveAction"] = (
|
97
|
+
http_service_error.corrective_action
|
98
|
+
)
|
99
|
+
|
100
|
+
if http_service_error.status_code is not None:
|
101
|
+
status_code = http_service_error.status_code
|
102
|
+
str_status_code = str(status_code)
|
103
|
+
extra["statusCode"] = str_status_code
|
104
|
+
|
105
|
+
tags.append(str_status_code)
|
106
|
+
|
107
|
+
if http_service_error.headers is not None:
|
108
|
+
headers = http_service_error.headers
|
109
|
+
case RabbitMQServiceException() as rabbitmq_service_exception:
|
110
|
+
str_error_code = str(rabbitmq_service_exception.code)
|
111
|
+
extra["code"] = str_error_code
|
112
|
+
|
113
|
+
tags.append(str_error_code)
|
114
|
+
|
115
|
+
if exception.tags:
|
116
|
+
tags.extend(exception.tags)
|
117
|
+
|
118
|
+
if exception.extra:
|
119
|
+
extra.update(exception.extra)
|
120
|
+
|
67
121
|
if exception.logstash_logging:
|
68
122
|
logstash_logger_method(
|
69
123
|
message=exception.message,
|
70
|
-
tags=
|
71
|
-
extra=
|
124
|
+
tags=tags,
|
125
|
+
extra=extra,
|
72
126
|
exception=exception if exception.extract_exc_info else None,
|
73
127
|
)
|
74
128
|
else:
|
@@ -80,39 +134,10 @@ def handle_service_exception(
|
|
80
134
|
exc_info=exc_info,
|
81
135
|
)
|
82
136
|
|
83
|
-
content: dict[str, Any] = {
|
84
|
-
"severity": exception_severity.name
|
85
|
-
if exception_severity
|
86
|
-
else Severity.LOW.name,
|
87
|
-
"message": message,
|
88
|
-
}
|
89
|
-
|
90
|
-
if exception.response_code is not None:
|
91
|
-
content["code"] = exception.response_code
|
92
|
-
|
93
|
-
if exception.corrective_action is not None:
|
94
|
-
content["correctiveAction"] = exception.corrective_action
|
95
|
-
|
96
|
-
if exception.body is not None:
|
97
|
-
extra_body = to_jsonable_python(exception.body)
|
98
|
-
is_updated = False
|
99
|
-
|
100
|
-
try:
|
101
|
-
if isinstance(extra_body, Iterable):
|
102
|
-
content.update(extra_body)
|
103
|
-
|
104
|
-
is_updated = True
|
105
|
-
except:
|
106
|
-
pass
|
107
|
-
|
108
|
-
if not is_updated:
|
109
|
-
content["data"] = extra_body
|
110
|
-
|
111
137
|
return JSONResponse(
|
112
138
|
content=content,
|
113
|
-
status_code=
|
114
|
-
|
115
|
-
headers=exception.headers,
|
139
|
+
status_code=status_code,
|
140
|
+
headers=headers,
|
116
141
|
)
|
117
142
|
|
118
143
|
|
qena_shared_lib/exceptions.py
CHANGED
@@ -2,50 +2,56 @@ from enum import Enum
|
|
2
2
|
from typing import Any
|
3
3
|
|
4
4
|
__all__ = [
|
5
|
-
"
|
6
|
-
"ServiceException",
|
7
|
-
"ClientError",
|
5
|
+
"BadGateway",
|
8
6
|
"BadRequest",
|
9
|
-
"
|
10
|
-
"PaymentRequired",
|
11
|
-
"Forbidden",
|
12
|
-
"NotFound",
|
13
|
-
"MethodNotAllowed",
|
14
|
-
"NotAcceptable",
|
15
|
-
"ProxyAuthenticationRequired",
|
16
|
-
"RequestTimeout",
|
7
|
+
"ClientError",
|
17
8
|
"Conflict",
|
18
|
-
"Gone",
|
19
|
-
"LengthRequired",
|
20
|
-
"PreconditionFailed",
|
21
|
-
"PayloadTooLarge",
|
22
|
-
"URITooLong",
|
23
|
-
"UnsupportedMediaType",
|
24
|
-
"RangeNotSatisfiable",
|
25
9
|
"ExpectationFailed",
|
10
|
+
"FailedDependency",
|
11
|
+
"Forbidden",
|
12
|
+
"GatewayTimeout",
|
13
|
+
"Gone",
|
14
|
+
"HTTPServiceError",
|
15
|
+
"HTTPVersionNotSupported",
|
26
16
|
"IAmATeapot",
|
27
|
-
"
|
28
|
-
"
|
17
|
+
"InsufficientStorage",
|
18
|
+
"InternalServerError",
|
19
|
+
"LengthRequired",
|
29
20
|
"Locked",
|
30
|
-
"
|
31
|
-
"
|
32
|
-
"
|
21
|
+
"LoopDetected",
|
22
|
+
"MethodNotAllowed",
|
23
|
+
"MisdirectedRequest",
|
24
|
+
"NetworkAuthenticationRequired",
|
25
|
+
"NotAcceptable",
|
26
|
+
"NotExtended",
|
27
|
+
"NotFound",
|
28
|
+
"NotImplemented",
|
29
|
+
"PayloadTooLarge",
|
30
|
+
"PaymentRequired",
|
31
|
+
"PreconditionFailed",
|
33
32
|
"PreconditionRequired",
|
34
|
-
"
|
33
|
+
"ProxyAuthenticationRequired",
|
34
|
+
"RabbitMQBlockedError",
|
35
|
+
"RabbitMQConnectionUnhealthyError",
|
36
|
+
"RabbitMQRpcRequestPendingError",
|
37
|
+
"RabbitMQRpcRequestTimeoutError",
|
38
|
+
"RabbitMQServiceException",
|
39
|
+
"RangeNotSatisfiable",
|
35
40
|
"RequestHeaderFieldsTooLarge",
|
36
|
-
"
|
41
|
+
"RequestTimeout",
|
37
42
|
"ServerError",
|
38
|
-
"
|
39
|
-
"NotImplemented",
|
40
|
-
"BadGateway",
|
43
|
+
"ServiceException",
|
41
44
|
"ServiceUnavailable",
|
42
|
-
"
|
43
|
-
"
|
45
|
+
"Severity",
|
46
|
+
"TooEarly",
|
47
|
+
"TooManyRequests",
|
48
|
+
"Unauthorized",
|
49
|
+
"UnavailableForLegalReasons",
|
50
|
+
"UnprocessableEntity",
|
51
|
+
"UnsupportedMediaType",
|
52
|
+
"UpgradeRequired",
|
53
|
+
"URITooLong",
|
44
54
|
"VariantAlsoNegotiates",
|
45
|
-
"InsufficientStorage",
|
46
|
-
"LoopDetected",
|
47
|
-
"NotExtended",
|
48
|
-
"NetworkAuthenticationRequired",
|
49
55
|
]
|
50
56
|
|
51
57
|
|
@@ -56,100 +62,134 @@ class Severity(Enum):
|
|
56
62
|
|
57
63
|
|
58
64
|
class ServiceException(Exception):
|
59
|
-
_GENERAL_EXTRACT_EXC_INFO = None
|
60
65
|
_GENERAL_SEVERITY = None
|
61
|
-
|
66
|
+
_GENERAL_EXTRACT_EXC_INFO = None
|
62
67
|
|
63
68
|
def __init__(
|
64
69
|
self,
|
65
70
|
message: str,
|
66
|
-
body: Any | None = None,
|
67
|
-
corrective_action: str | None = None,
|
68
71
|
severity: Severity | None = None,
|
69
|
-
status_code: int | None = None,
|
70
|
-
response_code: int | None = None,
|
71
72
|
tags: list[str] | None = None,
|
72
73
|
extra: dict[str, str] | None = None,
|
73
|
-
|
74
|
-
|
75
|
-
extract_exc_info: bool = True,
|
74
|
+
logstash_logging: bool | None = None,
|
75
|
+
extract_exc_info: bool | None = None,
|
76
76
|
):
|
77
77
|
self._message = message
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
|
79
|
+
if severity is not None:
|
80
|
+
self._severity = severity
|
81
|
+
else:
|
82
|
+
self._severity = self._GENERAL_SEVERITY
|
83
|
+
|
81
84
|
self._tags = tags
|
82
85
|
self._extra = extra
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
severity if severity is not None else self._GENERAL_SEVERITY
|
94
|
-
)
|
95
|
-
self._status_code = (
|
96
|
-
status_code
|
97
|
-
if status_code is not None
|
98
|
-
else self._GENERAL_STATUS_CODE
|
99
|
-
)
|
86
|
+
|
87
|
+
if logstash_logging is not None:
|
88
|
+
self._logstash_logging = logstash_logging
|
89
|
+
else:
|
90
|
+
self._logstash_logging = True
|
91
|
+
|
92
|
+
if extract_exc_info is not None:
|
93
|
+
self._extract_exc_info = extract_exc_info
|
94
|
+
else:
|
95
|
+
self._extract_exc_info = self._GENERAL_EXTRACT_EXC_INFO
|
100
96
|
|
101
97
|
@property
|
102
98
|
def message(self) -> str:
|
103
99
|
return self._message
|
104
100
|
|
105
101
|
@property
|
106
|
-
def
|
107
|
-
return self.
|
102
|
+
def severity(self) -> Severity | None:
|
103
|
+
return self._severity
|
108
104
|
|
109
105
|
@property
|
110
|
-
def
|
111
|
-
return self.
|
106
|
+
def tags(self) -> list[str] | None:
|
107
|
+
return self._tags
|
112
108
|
|
113
109
|
@property
|
114
|
-
def
|
115
|
-
return self.
|
110
|
+
def extra(self) -> dict[str, str] | None:
|
111
|
+
return self._extra
|
116
112
|
|
117
113
|
@property
|
118
|
-
def
|
119
|
-
return self.
|
114
|
+
def logstash_logging(self) -> bool | None:
|
115
|
+
return self._logstash_logging
|
120
116
|
|
121
117
|
@property
|
122
|
-
def
|
123
|
-
return self.
|
118
|
+
def extract_exc_info(self) -> bool | None:
|
119
|
+
return self._extract_exc_info
|
120
|
+
|
121
|
+
def __str__(self) -> str:
|
122
|
+
return f"message `{self._message}`, tags {self._tags or []}"
|
123
|
+
|
124
|
+
def __repr__(self) -> str:
|
125
|
+
return f"{self.__class__.__name__} ( message: `{self._message}`, tags: {self._tags or []}, extra: {self._extra or {}} )"
|
126
|
+
|
127
|
+
|
128
|
+
class HTTPServiceError(ServiceException):
|
129
|
+
_GENERAL_STATUS_CODE = None
|
130
|
+
|
131
|
+
def __init__(
|
132
|
+
self,
|
133
|
+
message: str,
|
134
|
+
body: Any | None = None,
|
135
|
+
status_code: int | None = None,
|
136
|
+
headers: dict[str, str] | None = None,
|
137
|
+
response_code: int | None = None,
|
138
|
+
corrective_action: str | None = None,
|
139
|
+
severity: Severity | None = None,
|
140
|
+
tags: list[str] | None = None,
|
141
|
+
extra: dict[str, str] | None = None,
|
142
|
+
logstash_logging: bool = True,
|
143
|
+
extract_exc_info: bool = True,
|
144
|
+
):
|
145
|
+
super().__init__(
|
146
|
+
message=message,
|
147
|
+
severity=severity,
|
148
|
+
tags=tags,
|
149
|
+
extra=extra,
|
150
|
+
logstash_logging=logstash_logging,
|
151
|
+
extract_exc_info=extract_exc_info,
|
152
|
+
)
|
153
|
+
|
154
|
+
self._body = body
|
155
|
+
|
156
|
+
if status_code is not None:
|
157
|
+
self._status_code = status_code
|
158
|
+
else:
|
159
|
+
self._status_code = self._GENERAL_STATUS_CODE
|
160
|
+
|
161
|
+
self._headers = headers
|
162
|
+
self._response_code = response_code
|
163
|
+
self._corrective_action = corrective_action
|
124
164
|
|
125
165
|
@property
|
126
|
-
def
|
127
|
-
return self.
|
166
|
+
def body(self) -> Any | None:
|
167
|
+
return self._body
|
128
168
|
|
129
169
|
@property
|
130
|
-
def
|
131
|
-
return self.
|
170
|
+
def status_code(self) -> int | None:
|
171
|
+
return self._status_code
|
132
172
|
|
133
173
|
@property
|
134
174
|
def headers(self) -> dict[str, str] | None:
|
135
175
|
return self._headers
|
136
176
|
|
137
177
|
@property
|
138
|
-
def
|
139
|
-
return self.
|
178
|
+
def response_code(self) -> int | None:
|
179
|
+
return self._response_code
|
140
180
|
|
141
181
|
@property
|
142
|
-
def
|
143
|
-
return self.
|
182
|
+
def corrective_action(self) -> str | None:
|
183
|
+
return self._corrective_action
|
144
184
|
|
145
185
|
def __str__(self) -> str:
|
146
|
-
return f"message `{self._message}`,
|
186
|
+
return f"message `{self._message}`, status_code {self._status_code or 500}, response_code {self._response_code or 0}"
|
147
187
|
|
148
188
|
def __repr__(self) -> str:
|
149
|
-
return f"{self.__class__.__name__} ( message
|
189
|
+
return f"{self.__class__.__name__} ( message: `{self._message}`, status_code: {self._status_code or 500}, response_code: {self._response_code or 0} )"
|
150
190
|
|
151
191
|
|
152
|
-
class ClientError(
|
192
|
+
class ClientError(HTTPServiceError):
|
153
193
|
_GENERAL_EXTRACT_EXC_INFO = False
|
154
194
|
_GENERAL_SEVERITY = Severity.MEDIUM
|
155
195
|
|
@@ -270,7 +310,7 @@ class UnavailableForLegalReasons(ClientError):
|
|
270
310
|
_GENERAL_STATUS_CODE = 451
|
271
311
|
|
272
312
|
|
273
|
-
class ServerError(
|
313
|
+
class ServerError(HTTPServiceError):
|
274
314
|
_GENERAL_EXTRACT_EXC_INFO = True
|
275
315
|
_GENERAL_SEVERITY = Severity.HIGH
|
276
316
|
|
@@ -317,3 +357,65 @@ class NotExtended(ServerError):
|
|
317
357
|
|
318
358
|
class NetworkAuthenticationRequired(ServerError):
|
319
359
|
_GENERAL_STATUS_CODE = 511
|
360
|
+
|
361
|
+
|
362
|
+
class RabbitMQServiceException(ServiceException):
|
363
|
+
_GENERAL_SEVERITY = Severity.HIGH
|
364
|
+
_GENERAL_CODE = None
|
365
|
+
|
366
|
+
def __init__(
|
367
|
+
self,
|
368
|
+
message: str,
|
369
|
+
code: int | None = None,
|
370
|
+
data: Any | None = None,
|
371
|
+
severity: Severity | None = None,
|
372
|
+
tags: list[str] | None = None,
|
373
|
+
extra: dict[str, str] | None = None,
|
374
|
+
logstash_logging: bool | None = None,
|
375
|
+
extract_exc_info: bool | None = None,
|
376
|
+
):
|
377
|
+
super().__init__(
|
378
|
+
message=message,
|
379
|
+
severity=severity,
|
380
|
+
tags=tags,
|
381
|
+
extra=extra,
|
382
|
+
logstash_logging=logstash_logging,
|
383
|
+
extract_exc_info=extract_exc_info,
|
384
|
+
)
|
385
|
+
|
386
|
+
if code is not None:
|
387
|
+
self._code = code
|
388
|
+
else:
|
389
|
+
self._code = self._GENERAL_CODE or 0
|
390
|
+
|
391
|
+
self._data = data
|
392
|
+
|
393
|
+
@property
|
394
|
+
def code(self) -> int:
|
395
|
+
return self._code
|
396
|
+
|
397
|
+
@property
|
398
|
+
def data(self) -> Any | None:
|
399
|
+
return self._data
|
400
|
+
|
401
|
+
def __str__(self) -> str:
|
402
|
+
return f"message `{self.message}`, code {self.code}"
|
403
|
+
|
404
|
+
def __repr__(self) -> str:
|
405
|
+
return f"{self.__class__.__name__} ( message: `{self._message}`, code: {self._code} )"
|
406
|
+
|
407
|
+
|
408
|
+
class RabbitMQBlockedError(Exception):
|
409
|
+
pass
|
410
|
+
|
411
|
+
|
412
|
+
class RabbitMQRpcRequestTimeoutError(Exception):
|
413
|
+
pass
|
414
|
+
|
415
|
+
|
416
|
+
class RabbitMQRpcRequestPendingError(Exception):
|
417
|
+
pass
|
418
|
+
|
419
|
+
|
420
|
+
class RabbitMQConnectionUnhealthyError(Exception):
|
421
|
+
pass
|
qena_shared_lib/http.py
CHANGED
@@ -9,7 +9,7 @@ from fastapi.responses import JSONResponse
|
|
9
9
|
from fastapi.types import IncEx
|
10
10
|
|
11
11
|
__all__ = [
|
12
|
-
"
|
12
|
+
"api_controller",
|
13
13
|
"ControllerBase",
|
14
14
|
"delete",
|
15
15
|
"get",
|
@@ -41,7 +41,7 @@ class HTTPMethods(Enum):
|
|
41
41
|
class RouteHandlerMeta:
|
42
42
|
method: HTTPMethods
|
43
43
|
path: str | None = None
|
44
|
-
response_model: Any | None =
|
44
|
+
response_model: Any | None = None
|
45
45
|
status_code: int | None = None
|
46
46
|
tags: list[str | Enum] | None = None
|
47
47
|
dependencies: Sequence[Depends] | None = None
|
@@ -57,25 +57,24 @@ class RouteHandlerMeta:
|
|
57
57
|
response_model_exclude_defaults: bool = False
|
58
58
|
response_model_exclude_none: bool = False
|
59
59
|
include_in_schema: bool = True
|
60
|
-
response_class: type[Response] =
|
60
|
+
response_class: type[Response] = JSONResponse
|
61
61
|
name: str | None = None
|
62
62
|
openapi_extra: dict[str, Any] | None = None
|
63
63
|
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
self._api_router = APIRouter(
|
65
|
+
def api_controller(
|
66
|
+
prefix: str | None = None,
|
67
|
+
*,
|
68
|
+
tags: list[str | Enum] | None = None,
|
69
|
+
dependencies: Sequence[Depends] | None = None,
|
70
|
+
default_response_class: type[Response] = JSONResponse,
|
71
|
+
responses: dict[int | str, dict[str, Any]] | None = None,
|
72
|
+
redirect_slashes: bool = True,
|
73
|
+
deprecated: bool | None = None,
|
74
|
+
include_in_schema: bool = True,
|
75
|
+
) -> Callable[["ControllerBase"], "ControllerBase"]:
|
76
|
+
def annotate_class(api_controller_class: ControllerBase):
|
77
|
+
router = APIRouter(
|
79
78
|
prefix=prefix or "",
|
80
79
|
tags=tags,
|
81
80
|
dependencies=dependencies,
|
@@ -86,10 +85,11 @@ class ApiController:
|
|
86
85
|
include_in_schema=include_in_schema,
|
87
86
|
)
|
88
87
|
|
89
|
-
|
90
|
-
|
88
|
+
setattr(api_controller_class, API_CONTROLLER_ATTRIBUTE, router)
|
89
|
+
|
90
|
+
return api_controller_class
|
91
91
|
|
92
|
-
|
92
|
+
return annotate_class
|
93
93
|
|
94
94
|
|
95
95
|
def get(
|
@@ -102,13 +102,13 @@ class LogstashLogRecord:
|
|
102
102
|
self, exception: BaseException
|
103
103
|
) -> dict[str, str]:
|
104
104
|
causes = {}
|
105
|
-
cause = exception.__cause__
|
105
|
+
cause = exception.__cause__ or exception.__context__
|
106
106
|
cause_depth = 0
|
107
107
|
|
108
108
|
while cause is not None:
|
109
109
|
cause_depth += 1
|
110
110
|
causes[self._depth_to_cause(cause_depth)] = cause.__class__.__name__
|
111
|
-
cause = cause.__cause__
|
111
|
+
cause = cause.__cause__ or cause.__context__
|
112
112
|
|
113
113
|
return causes
|
114
114
|
|
@@ -2,11 +2,9 @@ from ._base import AbstractRabbitMQService, RabbitMqManager
|
|
2
2
|
from ._channel import BaseChannel
|
3
3
|
from ._exception_handlers import (
|
4
4
|
handle_general_mq_exception,
|
5
|
-
|
6
|
-
handle_rabbitmq_exception,
|
5
|
+
handle_rabbit_mq_service_exception,
|
7
6
|
handle_validation_error,
|
8
7
|
)
|
9
|
-
from ._exceptions import RabbitMQException
|
10
8
|
from ._listener import (
|
11
9
|
CONSUMER_ATTRIBUTE,
|
12
10
|
LISTENER_ATTRIBUTE,
|
@@ -20,7 +18,9 @@ from ._listener import (
|
|
20
18
|
RetryPolicy,
|
21
19
|
RpcWorker,
|
22
20
|
consume,
|
21
|
+
consumer,
|
23
22
|
execute,
|
23
|
+
rpc_worker,
|
24
24
|
)
|
25
25
|
from ._publisher import Publisher
|
26
26
|
from ._rpc_client import RpcClient
|
@@ -31,22 +31,22 @@ __all__ = [
|
|
31
31
|
"BaseChannel",
|
32
32
|
"consume",
|
33
33
|
"CONSUMER_ATTRIBUTE",
|
34
|
+
"consumer",
|
34
35
|
"Consumer",
|
35
36
|
"execute",
|
36
37
|
"FixedRetryDelay",
|
37
38
|
"handle_general_mq_exception",
|
38
|
-
"
|
39
|
-
"handle_rabbitmq_exception",
|
39
|
+
"handle_rabbit_mq_service_exception",
|
40
40
|
"handle_validation_error",
|
41
41
|
"LISTENER_ATTRIBUTE",
|
42
42
|
"ListenerBase",
|
43
43
|
"ListenerContext",
|
44
44
|
"Publisher",
|
45
|
-
"RabbitMQException",
|
46
45
|
"RabbitMqManager",
|
47
46
|
"RetryDelayJitter",
|
48
47
|
"RetryPolicy",
|
49
48
|
"RPC_WORKER_ATTRIBUTE",
|
49
|
+
"rpc_worker",
|
50
50
|
"RpcClient",
|
51
51
|
"RpcWorker",
|
52
52
|
]
|