qena-shared-lib 0.1.10__py3-none-any.whl → 0.1.12__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 +16 -11
- qena_shared_lib/background.py +14 -11
- qena_shared_lib/dependencies/http.py +3 -3
- qena_shared_lib/exception_handlers.py +4 -0
- qena_shared_lib/exceptions.py +59 -49
- qena_shared_lib/http.py +57 -3
- qena_shared_lib/logging.py +3 -3
- qena_shared_lib/logstash/_base.py +31 -30
- qena_shared_lib/logstash/_http_sender.py +1 -1
- qena_shared_lib/logstash/_tcp_sender.py +9 -9
- qena_shared_lib/rabbitmq/__init__.py +2 -0
- qena_shared_lib/rabbitmq/_base.py +32 -26
- qena_shared_lib/rabbitmq/_channel.py +24 -14
- qena_shared_lib/rabbitmq/_exception_handlers.py +3 -3
- qena_shared_lib/rabbitmq/_listener.py +46 -47
- qena_shared_lib/rabbitmq/_pool.py +2 -2
- qena_shared_lib/rabbitmq/_publisher.py +3 -3
- qena_shared_lib/rabbitmq/_rpc_client.py +28 -22
- qena_shared_lib/scheduler.py +20 -18
- qena_shared_lib/security.py +2 -2
- qena_shared_lib/utils.py +5 -22
- {qena_shared_lib-0.1.10.dist-info → qena_shared_lib-0.1.12.dist-info}/METADATA +2 -2
- qena_shared_lib-0.1.12.dist-info/RECORD +29 -0
- qena_shared_lib-0.1.10.dist-info/RECORD +0 -29
- {qena_shared_lib-0.1.10.dist-info → qena_shared_lib-0.1.12.dist-info}/WHEEL +0 -0
@@ -42,11 +42,11 @@ class LogstashLogRecord:
|
|
42
42
|
self._service_name = service_name
|
43
43
|
self._log_level = log_level
|
44
44
|
self._log_logger = log_logger
|
45
|
-
self._tags = None
|
46
|
-
self._labels = None
|
47
|
-
self._error_type = None
|
48
|
-
self._error_message = None
|
49
|
-
self._error_stack_trace = None
|
45
|
+
self._tags: list[str] | None = None
|
46
|
+
self._labels: dict[str, str] | None = None
|
47
|
+
self._error_type: str | None = None
|
48
|
+
self._error_message: str | None = None
|
49
|
+
self._error_stack_trace: str | None = None
|
50
50
|
self._log_retries = 0
|
51
51
|
|
52
52
|
@property
|
@@ -70,7 +70,7 @@ class LogstashLogRecord:
|
|
70
70
|
return self._tags
|
71
71
|
|
72
72
|
@tags.setter
|
73
|
-
def tags(self, tags: list[str]):
|
73
|
+
def tags(self, tags: list[str]) -> None:
|
74
74
|
self._tags = tags
|
75
75
|
|
76
76
|
@property
|
@@ -78,15 +78,14 @@ class LogstashLogRecord:
|
|
78
78
|
return self._labels
|
79
79
|
|
80
80
|
@labels.setter
|
81
|
-
def labels(self, labels: dict[str, str]):
|
81
|
+
def labels(self, labels: dict[str, str]) -> None:
|
82
82
|
self._labels = labels
|
83
83
|
|
84
84
|
@property
|
85
85
|
def error(self) -> tuple[str | None, str | None, str | None]:
|
86
86
|
return self._error_type, self._error_message, self._error_stack_trace
|
87
87
|
|
88
|
-
|
89
|
-
def error(self, exception: BaseException):
|
88
|
+
def error_from_exception(self, exception: BaseException) -> None:
|
90
89
|
self._error_type = type(exception).__name__
|
91
90
|
self._error_message = str(exception)
|
92
91
|
|
@@ -159,7 +158,7 @@ class LogstashLogRecord:
|
|
159
158
|
return self._log_retries
|
160
159
|
|
161
160
|
@log_retries.setter
|
162
|
-
def log_retries(self, log_retries: int):
|
161
|
+
def log_retries(self, log_retries: int) -> None:
|
163
162
|
self._log_retries = log_retries
|
164
163
|
|
165
164
|
def to_dict(self) -> dict:
|
@@ -222,7 +221,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
222
221
|
max_log_retry: int = 5,
|
223
222
|
log_queue_size: int = 1000,
|
224
223
|
failed_log_queue_size: int = 1000,
|
225
|
-
):
|
224
|
+
) -> None:
|
226
225
|
self._sender = f"qena_shared_lib.logstash.{self.__class__.__name__}"
|
227
226
|
self._service_name = service_name
|
228
227
|
self._max_log_retry = max_log_retry
|
@@ -239,7 +238,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
239
238
|
f"logstash.{self.__class__.__name__.lower()}"
|
240
239
|
)
|
241
240
|
|
242
|
-
async def start(self):
|
241
|
+
async def start(self) -> None:
|
243
242
|
if self._started:
|
244
243
|
raise RuntimeError("logstash sender already started")
|
245
244
|
|
@@ -260,13 +259,13 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
260
259
|
)
|
261
260
|
self.LOGSTASH_SENDER_STATE.state("running")
|
262
261
|
|
263
|
-
def _hook_on_start(self):
|
262
|
+
def _hook_on_start(self) -> None:
|
264
263
|
pass
|
265
264
|
|
266
|
-
async def _hook_on_start_async(self):
|
265
|
+
async def _hook_on_start_async(self) -> None:
|
267
266
|
pass
|
268
267
|
|
269
|
-
def _on_log_flusher_closed(self, task: Task):
|
268
|
+
def _on_log_flusher_closed(self, task: Task) -> None:
|
270
269
|
if task.cancelled():
|
271
270
|
self._close_future.set_result(None)
|
272
271
|
|
@@ -284,7 +283,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
284
283
|
self._hook_on_stop_async(),
|
285
284
|
).add_done_callback(self._on_close_hook_done)
|
286
285
|
|
287
|
-
def _on_close_hook_done(self, task_or_future: Task | Future):
|
286
|
+
def _on_close_hook_done(self, task_or_future: Task | Future) -> None:
|
288
287
|
if task_or_future.cancelled():
|
289
288
|
self._close_future.set_result(None)
|
290
289
|
|
@@ -319,16 +318,18 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
319
318
|
|
320
319
|
return self._close_future
|
321
320
|
|
322
|
-
def _on_close_future_done(self,
|
321
|
+
def _on_close_future_done(self, future: Future) -> None:
|
322
|
+
del future
|
323
|
+
|
323
324
|
self.LOGSTASH_SENDER_STATE.state("stopped")
|
324
325
|
|
325
|
-
def _hook_on_stop(self):
|
326
|
+
def _hook_on_stop(self) -> None:
|
326
327
|
pass
|
327
328
|
|
328
|
-
async def _hook_on_stop_async(self):
|
329
|
+
async def _hook_on_stop_async(self) -> None:
|
329
330
|
pass
|
330
331
|
|
331
|
-
async def _flush_logs(self):
|
332
|
+
async def _flush_logs(self) -> None:
|
332
333
|
while (
|
333
334
|
not self._closed
|
334
335
|
or not self._log_queue.empty()
|
@@ -400,7 +401,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
400
401
|
|
401
402
|
raise NotImplementedError()
|
402
403
|
|
403
|
-
def _put_to_dead_letter_log_queue(self, log: LogstashLogRecord):
|
404
|
+
def _put_to_dead_letter_log_queue(self, log: LogstashLogRecord) -> None:
|
404
405
|
if self._closed:
|
405
406
|
self._logger.error(
|
406
407
|
"%s logger closed, falling back to stdout or stderr.\n%r",
|
@@ -425,7 +426,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
425
426
|
tags: list[str] | None = None,
|
426
427
|
extra: dict[str, str] | None = None,
|
427
428
|
exception: BaseException | None = None,
|
428
|
-
):
|
429
|
+
) -> None:
|
429
430
|
self._enqueue_log(
|
430
431
|
level=level,
|
431
432
|
message=message,
|
@@ -440,7 +441,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
440
441
|
tags: list[str] | None = None,
|
441
442
|
extra: dict[str, str] | None = None,
|
442
443
|
exception: BaseException | None = None,
|
443
|
-
):
|
444
|
+
) -> None:
|
444
445
|
self._enqueue_log(
|
445
446
|
level=LogLevel.DEBUG,
|
446
447
|
message=message,
|
@@ -455,7 +456,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
455
456
|
tags: list[str] | None = None,
|
456
457
|
extra: dict[str, str] | None = None,
|
457
458
|
exception: BaseException | None = None,
|
458
|
-
):
|
459
|
+
) -> None:
|
459
460
|
self._enqueue_log(
|
460
461
|
level=LogLevel.INFO,
|
461
462
|
message=message,
|
@@ -470,7 +471,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
470
471
|
tags: list[str] | None = None,
|
471
472
|
extra: dict[str, str] | None = None,
|
472
473
|
exception: BaseException | None = None,
|
473
|
-
):
|
474
|
+
) -> None:
|
474
475
|
self._enqueue_log(
|
475
476
|
level=LogLevel.WARNING,
|
476
477
|
message=message,
|
@@ -485,7 +486,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
485
486
|
tags: list[str] | None = None,
|
486
487
|
extra: dict[str, str] | None = None,
|
487
488
|
exception: BaseException | None = None,
|
488
|
-
):
|
489
|
+
) -> None:
|
489
490
|
self._enqueue_log(
|
490
491
|
level=LogLevel.ERROR,
|
491
492
|
message=message,
|
@@ -500,7 +501,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
500
501
|
tags: list[str] | None = None,
|
501
502
|
extra: dict[str, str] | None = None,
|
502
503
|
exception: BaseException | None = None,
|
503
|
-
):
|
504
|
+
) -> None:
|
504
505
|
if exception is None:
|
505
506
|
_, exception, _ = exc_info()
|
506
507
|
|
@@ -511,7 +512,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
511
512
|
exception=exception,
|
512
513
|
)
|
513
514
|
|
514
|
-
def set_level(self, level: LogLevel):
|
515
|
+
def set_level(self, level: LogLevel) -> None:
|
515
516
|
self._level = level
|
516
517
|
|
517
518
|
def _enqueue_log(
|
@@ -521,7 +522,7 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
521
522
|
tags: list[str] | None = None,
|
522
523
|
extra: dict[str, str] | None = None,
|
523
524
|
exception: BaseException | None = None,
|
524
|
-
):
|
525
|
+
) -> None:
|
525
526
|
if self._closed:
|
526
527
|
self._logger.warning("Logstash http logger is already close")
|
527
528
|
|
@@ -568,6 +569,6 @@ class BaseLogstashSender(AsyncEventLoopMixin):
|
|
568
569
|
log.labels = extra
|
569
570
|
|
570
571
|
if exception:
|
571
|
-
log.
|
572
|
+
log.error_from_exception(exception)
|
572
573
|
|
573
574
|
return log
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from asyncio import open_connection
|
1
|
+
from asyncio import StreamWriter, open_connection
|
2
2
|
|
3
3
|
from pydantic_core import to_json
|
4
4
|
|
@@ -33,21 +33,21 @@ class TCPSender(BaseLogstashSender):
|
|
33
33
|
|
34
34
|
return SenderResponse(sent=True)
|
35
35
|
|
36
|
-
async def _hook_on_start_async(self):
|
36
|
+
async def _hook_on_start_async(self) -> None:
|
37
37
|
await self._client.open()
|
38
38
|
|
39
|
-
async def _hook_on_stop_async(self):
|
39
|
+
async def _hook_on_stop_async(self) -> None:
|
40
40
|
await self._client.close()
|
41
41
|
|
42
42
|
|
43
43
|
class AsyncTcpClient:
|
44
|
-
def __init__(self, host: str, port: int):
|
44
|
+
def __init__(self, host: str, port: int) -> None:
|
45
45
|
self._host = host
|
46
46
|
self._port = port
|
47
|
-
self._writer = None
|
47
|
+
self._writer: StreamWriter | None = None
|
48
48
|
self._client_closed = False
|
49
49
|
|
50
|
-
async def write(self, json: dict):
|
50
|
+
async def write(self, json: dict) -> None:
|
51
51
|
if self._client_closed:
|
52
52
|
raise RuntimeError("async tcp client already closed")
|
53
53
|
|
@@ -64,10 +64,10 @@ class AsyncTcpClient:
|
|
64
64
|
except ConnectionResetError:
|
65
65
|
await self._connect()
|
66
66
|
|
67
|
-
async def open(self):
|
67
|
+
async def open(self) -> None:
|
68
68
|
await self._connect()
|
69
69
|
|
70
|
-
async def close(self):
|
70
|
+
async def close(self) -> None:
|
71
71
|
if not self._writer_closed() and self._writer is not None:
|
72
72
|
self._writer.write_eof()
|
73
73
|
await self._writer.drain()
|
@@ -78,7 +78,7 @@ class AsyncTcpClient:
|
|
78
78
|
def _writer_closed(self) -> bool:
|
79
79
|
return self._writer is None or self._writer.is_closing()
|
80
80
|
|
81
|
-
async def _connect(self):
|
81
|
+
async def _connect(self) -> None:
|
82
82
|
_, self._writer = await open_connection(
|
83
83
|
host=self._host, port=self._port
|
84
84
|
)
|
@@ -22,6 +22,7 @@ from ._listener import (
|
|
22
22
|
execute,
|
23
23
|
rpc_worker,
|
24
24
|
)
|
25
|
+
from ._pool import ChannelPool
|
25
26
|
from ._publisher import Publisher
|
26
27
|
from ._rpc_client import RpcClient
|
27
28
|
|
@@ -29,6 +30,7 @@ __all__ = [
|
|
29
30
|
"AbstractRabbitMQService",
|
30
31
|
"BackoffRetryDelay",
|
31
32
|
"BaseChannel",
|
33
|
+
"ChannelPool",
|
32
34
|
"consume",
|
33
35
|
"CONSUMER_ATTRIBUTE",
|
34
36
|
"consumer",
|
@@ -10,6 +10,7 @@ from functools import partial
|
|
10
10
|
from inspect import Parameter, signature
|
11
11
|
from random import uniform
|
12
12
|
from typing import (
|
13
|
+
Any,
|
13
14
|
Awaitable,
|
14
15
|
Callable,
|
15
16
|
Concatenate,
|
@@ -61,6 +62,7 @@ ExceptionHandler = (
|
|
61
62
|
Callable[Concatenate[ListenerContext, E, P], None]
|
62
63
|
| Callable[Concatenate[ListenerContext, E, P], Awaitable]
|
63
64
|
)
|
65
|
+
R = TypeVar("R")
|
64
66
|
|
65
67
|
|
66
68
|
class AbstractRabbitMQService(ABC):
|
@@ -113,11 +115,11 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
113
115
|
self._reconnect_delay_jitter = reconnect_delay_jitter
|
114
116
|
self._container = container or Container()
|
115
117
|
self._listener_global_retry_policy = listener_global_retry_policy
|
116
|
-
self._connection = None
|
118
|
+
self._connection: AsyncioConnection | None = None
|
117
119
|
self._connected = False
|
118
120
|
self._disconnected = False
|
119
121
|
self._connection_blocked = False
|
120
|
-
self._services = []
|
122
|
+
self._services: list[AbstractRabbitMQService] = []
|
121
123
|
self._exception_handlers: dict[
|
122
124
|
type[Exception], ExceptionHandlerContainer
|
123
125
|
] = {}
|
@@ -146,7 +148,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
146
148
|
|
147
149
|
def wrapper(
|
148
150
|
handler: ExceptionHandler,
|
149
|
-
):
|
151
|
+
) -> ExceptionHandler:
|
150
152
|
if not callable(handler):
|
151
153
|
raise TypeError(f"handler not a callable, got {type(handler)}")
|
152
154
|
|
@@ -201,7 +203,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
201
203
|
|
202
204
|
return True, None
|
203
205
|
|
204
|
-
def include_listener(self, listener: Listener | type[ListenerBase]):
|
206
|
+
def include_listener(self, listener: Listener | type[ListenerBase]) -> None:
|
205
207
|
if isinstance(listener, Listener):
|
206
208
|
self._listeners.append(listener)
|
207
209
|
|
@@ -216,7 +218,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
216
218
|
f"listener is {type(listener)}, expected instance of type or subclass of `Listener` or `type[ListenerBase]`"
|
217
219
|
)
|
218
220
|
|
219
|
-
def _register_listener_classes(self, listener_class: type):
|
221
|
+
def _register_listener_classes(self, listener_class: type) -> None:
|
220
222
|
inner_listener = getattr(listener_class, LISTENER_ATTRIBUTE, None)
|
221
223
|
|
222
224
|
if inner_listener is None:
|
@@ -239,7 +241,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
239
241
|
self,
|
240
242
|
rabbit_mq_service: AbstractRabbitMQService
|
241
243
|
| type[AbstractRabbitMQService],
|
242
|
-
):
|
244
|
+
) -> None:
|
243
245
|
if not isinstance(rabbit_mq_service, AbstractRabbitMQService) and (
|
244
246
|
not isinstance(rabbit_mq_service, type)
|
245
247
|
or not issubclass(rabbit_mq_service, AbstractRabbitMQService)
|
@@ -276,13 +278,13 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
276
278
|
|
277
279
|
return self._connected_future
|
278
280
|
|
279
|
-
def _resolve_listener_classes(self):
|
281
|
+
def _resolve_listener_classes(self) -> None:
|
280
282
|
self._listeners.extend(
|
281
283
|
listener.register_listener_methods()
|
282
284
|
for listener in self._container.resolve_all(ListenerBase)
|
283
285
|
)
|
284
286
|
|
285
|
-
def _resolve_service_classes(self):
|
287
|
+
def _resolve_service_classes(self) -> None:
|
286
288
|
self._services.extend(
|
287
289
|
self._container.resolve_all(AbstractRabbitMQService)
|
288
290
|
)
|
@@ -323,9 +325,9 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
323
325
|
exchange: str | None = None,
|
324
326
|
procedure: str | None = None,
|
325
327
|
headers: dict[str, str] | None = None,
|
326
|
-
return_type: type | None = None,
|
327
|
-
timeout: float =
|
328
|
-
) -> RpcClient:
|
328
|
+
return_type: type[R] | None = None,
|
329
|
+
timeout: float = 15,
|
330
|
+
) -> RpcClient[R]:
|
329
331
|
if timeout == 0:
|
330
332
|
self._logger.warning(
|
331
333
|
"rpc call with 0 seconds timeout may never return back"
|
@@ -355,7 +357,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
355
357
|
and not self._connection.is_closed
|
356
358
|
)
|
357
359
|
|
358
|
-
def disconnect(self):
|
360
|
+
def disconnect(self) -> None:
|
359
361
|
if self._disconnected:
|
360
362
|
raise RuntimeError("already disconnected from rabbitmq")
|
361
363
|
|
@@ -372,7 +374,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
372
374
|
|
373
375
|
self.RABBITMQ_CONNECTION_STATE.state("disconnected")
|
374
376
|
|
375
|
-
def _on_connection_opened(self, connection: AsyncioConnection):
|
377
|
+
def _on_connection_opened(self, connection: AsyncioConnection) -> None:
|
376
378
|
self._connection = connection
|
377
379
|
self._connection_blocked = False
|
378
380
|
|
@@ -394,7 +396,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
394
396
|
self._channel_pool.fill(self._connection)
|
395
397
|
).add_done_callback(self._channel_pool_filled)
|
396
398
|
|
397
|
-
def _channel_pool_drained(self, task: Task):
|
399
|
+
def _channel_pool_drained(self, task: Task) -> None:
|
398
400
|
if task.cancelled():
|
399
401
|
if not self._connected and not self._connected_future.done():
|
400
402
|
_ = self._connected_future.cancel(None)
|
@@ -422,7 +424,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
422
424
|
|
423
425
|
def _on_connection_blocked(
|
424
426
|
self, connection: AsyncioConnection, method: Method
|
425
|
-
):
|
427
|
+
) -> None:
|
426
428
|
del connection, method
|
427
429
|
|
428
430
|
self._connection_blocked = True
|
@@ -434,7 +436,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
434
436
|
|
435
437
|
def _on_connection_unblocked(
|
436
438
|
self, connection: AsyncioConnection, method: Method
|
437
|
-
):
|
439
|
+
) -> None:
|
438
440
|
del connection, method
|
439
441
|
|
440
442
|
self._connection_blocked = False
|
@@ -445,7 +447,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
445
447
|
def _is_connection_blocked(self) -> bool:
|
446
448
|
return self._connection_blocked
|
447
449
|
|
448
|
-
def _channel_pool_filled(self, task: Task):
|
450
|
+
def _channel_pool_filled(self, task: Task) -> None:
|
449
451
|
if task.cancelled():
|
450
452
|
if not self._connected and not self._connected_future.done():
|
451
453
|
_ = self._connected_future.cancel(None)
|
@@ -502,7 +504,9 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
502
504
|
|
503
505
|
return [listener_configuration_error_future]
|
504
506
|
|
505
|
-
def _initialize_services(self) -> list[
|
507
|
+
def _initialize_services(self) -> list[Future]:
|
508
|
+
assert self._connection is not None
|
509
|
+
|
506
510
|
try:
|
507
511
|
return [
|
508
512
|
service.initialize(self._connection, self._channel_pool)
|
@@ -515,7 +519,9 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
515
519
|
|
516
520
|
return [service_initialization_error_future]
|
517
521
|
|
518
|
-
def _listener_and_service_config_and_init_done(
|
522
|
+
def _listener_and_service_config_and_init_done(
|
523
|
+
self, future: Future
|
524
|
+
) -> None:
|
519
525
|
if future.cancelled():
|
520
526
|
if not self._connected and not self._connected_future.done():
|
521
527
|
_ = self._connected_future.cancel(None)
|
@@ -564,7 +570,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
564
570
|
|
565
571
|
def _on_connection_open_error(
|
566
572
|
self, connection: AsyncioConnection, exception: BaseException
|
567
|
-
):
|
573
|
+
) -> None:
|
568
574
|
del connection
|
569
575
|
|
570
576
|
if not self._connected and not self._connected_future.done():
|
@@ -629,8 +635,8 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
629
635
|
return True
|
630
636
|
|
631
637
|
def _on_exception_handler_done(
|
632
|
-
self, context: ListenerContext, task_or_future: Task | Future
|
633
|
-
):
|
638
|
+
self, context: ListenerContext, task_or_future: Task[Any] | Future[Any]
|
639
|
+
) -> None:
|
634
640
|
if task_or_future.cancelled():
|
635
641
|
return
|
636
642
|
|
@@ -646,7 +652,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
646
652
|
|
647
653
|
def _on_connection_closed(
|
648
654
|
self, connection: AsyncioConnection, exception: BaseException
|
649
|
-
):
|
655
|
+
) -> None:
|
650
656
|
del connection
|
651
657
|
|
652
658
|
if not self._connected and not self._connected_future.done():
|
@@ -661,7 +667,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
661
667
|
)
|
662
668
|
self._reconnect()
|
663
669
|
|
664
|
-
def _reconnect(self):
|
670
|
+
def _reconnect(self) -> None:
|
665
671
|
self.RABBITMQ_CONNECTION_STATE.state("reconnecting")
|
666
672
|
self.loop.call_later(
|
667
673
|
delay=self._reconnect_delay
|
@@ -669,7 +675,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
669
675
|
callback=self._on_time_to_reconnect,
|
670
676
|
)
|
671
677
|
|
672
|
-
def _on_time_to_reconnect(self):
|
678
|
+
def _on_time_to_reconnect(self) -> None:
|
673
679
|
try:
|
674
680
|
connected_future = self.connect()
|
675
681
|
except Exception as e:
|
@@ -689,7 +695,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
|
|
689
695
|
|
690
696
|
connected_future.add_done_callback(self._on_reconnect_done)
|
691
697
|
|
692
|
-
def _on_reconnect_done(self, future: Future):
|
698
|
+
def _on_reconnect_done(self, future: Future[None]) -> None:
|
693
699
|
if future.cancelled():
|
694
700
|
return
|
695
701
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from asyncio import Future
|
2
|
+
from inspect import Traceback
|
2
3
|
from random import uniform
|
3
4
|
from uuid import UUID, uuid4
|
4
5
|
|
@@ -26,7 +27,7 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
26
27
|
self._reopen_delay_jitter = reopen_delay_jitter
|
27
28
|
self._failed_reopen_threshold = failed_reopen_threshold
|
28
29
|
self._completion_future = self.loop.create_future()
|
29
|
-
self._channel = None
|
30
|
+
self._channel: Channel | None = None
|
30
31
|
self._channel_id = uuid4()
|
31
32
|
self._reopen_failures = 0
|
32
33
|
self._reserved = False
|
@@ -51,13 +52,13 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
51
52
|
|
52
53
|
return self._completion_future
|
53
54
|
|
54
|
-
def reserve(self):
|
55
|
+
def reserve(self) -> None:
|
55
56
|
self._reserved = True
|
56
57
|
|
57
|
-
def release(self):
|
58
|
+
def release(self) -> None:
|
58
59
|
self._reserved = False
|
59
60
|
|
60
|
-
def _on_channel_opened(self, channel: Channel):
|
61
|
+
def _on_channel_opened(self, channel: Channel) -> None:
|
61
62
|
self._channel = channel
|
62
63
|
|
63
64
|
try:
|
@@ -66,7 +67,7 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
66
67
|
if not self._completion_future.done():
|
67
68
|
self._completion_future.set_exception(e)
|
68
69
|
else:
|
69
|
-
if not self.channel_closed():
|
70
|
+
if self._channel is not None and not self.channel_closed():
|
70
71
|
self._channel.close()
|
71
72
|
|
72
73
|
self._reopen()
|
@@ -78,7 +79,7 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
78
79
|
|
79
80
|
self._completion_future.set_result(self._channel_id)
|
80
81
|
|
81
|
-
def _hook_on_channel_opened(self):
|
82
|
+
def _hook_on_channel_opened(self) -> None:
|
82
83
|
pass
|
83
84
|
|
84
85
|
def channel_closed(self) -> bool:
|
@@ -87,7 +88,7 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
87
88
|
|
88
89
|
return self._channel.is_closing or self._channel.is_closed
|
89
90
|
|
90
|
-
def _on_cancelled(self, method: Basic.Cancel):
|
91
|
+
def _on_cancelled(self, method: Basic.Cancel) -> None:
|
91
92
|
del method
|
92
93
|
|
93
94
|
if not self._completion_future.done():
|
@@ -102,10 +103,12 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
102
103
|
except:
|
103
104
|
self._logger.exception("error occured on invoking cancel hook")
|
104
105
|
|
105
|
-
def _hook_on_cancelled(self):
|
106
|
+
def _hook_on_cancelled(self) -> None:
|
106
107
|
pass
|
107
108
|
|
108
|
-
def _on_channel_closed(
|
109
|
+
def _on_channel_closed(
|
110
|
+
self, channel: Channel, error: BaseException
|
111
|
+
) -> None:
|
109
112
|
del channel
|
110
113
|
|
111
114
|
try:
|
@@ -118,10 +121,10 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
118
121
|
if not isinstance(error, ChannelClosedByClient):
|
119
122
|
self._reopen()
|
120
123
|
|
121
|
-
def _hook_on_channel_closed(self, error: BaseException):
|
124
|
+
def _hook_on_channel_closed(self, error: BaseException) -> None:
|
122
125
|
del error
|
123
126
|
|
124
|
-
def _reopen(self):
|
127
|
+
def _reopen(self) -> None:
|
125
128
|
if (
|
126
129
|
self._failed_reopen_threshold is not None
|
127
130
|
and self._reopen_failures >= self._failed_reopen_threshold
|
@@ -135,7 +138,7 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
135
138
|
callback=self._on_time_to_reopen,
|
136
139
|
)
|
137
140
|
|
138
|
-
def _on_time_to_reopen(self):
|
141
|
+
def _on_time_to_reopen(self) -> None:
|
139
142
|
if self._connection.is_closing or self._connection.is_closed:
|
140
143
|
self._can_be_disposed = True
|
141
144
|
|
@@ -151,7 +154,7 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
151
154
|
)
|
152
155
|
self._reopen()
|
153
156
|
|
154
|
-
def __enter__(self):
|
157
|
+
def __enter__(self) -> Channel:
|
155
158
|
if not self._reserved:
|
156
159
|
self.reserve()
|
157
160
|
|
@@ -160,7 +163,14 @@ class BaseChannel(AsyncEventLoopMixin):
|
|
160
163
|
|
161
164
|
return self._channel
|
162
165
|
|
163
|
-
def __exit__(
|
166
|
+
def __exit__(
|
167
|
+
self,
|
168
|
+
exception_type: type[Exception],
|
169
|
+
exception_value: Exception,
|
170
|
+
exception_traceback: Traceback,
|
171
|
+
) -> None:
|
172
|
+
del exception_type, exception_value, exception_traceback
|
173
|
+
|
164
174
|
self.release()
|
165
175
|
|
166
176
|
@property
|
@@ -27,7 +27,7 @@ def handle_rabbit_mq_service_exception(
|
|
27
27
|
exception: ServiceException,
|
28
28
|
logstash: Annotated[BaseLogstashSender, DependsOn(BaseLogstashSender)],
|
29
29
|
logger_provider: Annotated[LoggerProvider, DependsOn(LoggerProvider)],
|
30
|
-
):
|
30
|
+
) -> None:
|
31
31
|
logger = logger_provider.get_logger(RABBITMQ_EXCEPTION_HANDLER_LOGGER_NAME)
|
32
32
|
tags = [
|
33
33
|
"RabbitMQ",
|
@@ -105,7 +105,7 @@ def handle_validation_error(
|
|
105
105
|
context: ListenerContext,
|
106
106
|
exception: ValidationError,
|
107
107
|
logstash: Annotated[BaseLogstashSender, DependsOn(BaseLogstashSender)],
|
108
|
-
):
|
108
|
+
) -> None:
|
109
109
|
logstash.error(
|
110
110
|
message=f"invalid rabbitmq request data at queue `{context.queue}` and listener `{context.listener_name}`",
|
111
111
|
tags=[
|
@@ -128,7 +128,7 @@ def handle_general_mq_exception(
|
|
128
128
|
context: ListenerContext,
|
129
129
|
exception: Exception,
|
130
130
|
logstash: Annotated[BaseLogstashSender, DependsOn(BaseLogstashSender)],
|
131
|
-
):
|
131
|
+
) -> None:
|
132
132
|
logstash.error(
|
133
133
|
message=f"something went wrong while consuming message on queue `{context.queue}` and listener `{context.listener_name}`",
|
134
134
|
tags=[
|