sycommon-python-lib 0.1.31__py3-none-any.whl → 0.1.32__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.
Potentially problematic release.
This version of sycommon-python-lib might be problematic. Click here for more details.
- sycommon/rabbitmq/rabbitmq_client.py +45 -23
- sycommon/rabbitmq/rabbitmq_service.py +12 -12
- {sycommon_python_lib-0.1.31.dist-info → sycommon_python_lib-0.1.32.dist-info}/METADATA +1 -1
- {sycommon_python_lib-0.1.31.dist-info → sycommon_python_lib-0.1.32.dist-info}/RECORD +7 -7
- {sycommon_python_lib-0.1.31.dist-info → sycommon_python_lib-0.1.32.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.1.31.dist-info → sycommon_python_lib-0.1.32.dist-info}/entry_points.txt +0 -0
- {sycommon_python_lib-0.1.31.dist-info → sycommon_python_lib-0.1.32.dist-info}/top_level.txt +0 -0
|
@@ -102,7 +102,7 @@ class RabbitMQClient:
|
|
|
102
102
|
self._monitor_task: Optional[asyncio.Task] = None
|
|
103
103
|
|
|
104
104
|
# 消息处理跟踪
|
|
105
|
-
self.
|
|
105
|
+
self._tracking_messages: Dict[str, Dict[str, Any]] = {}
|
|
106
106
|
|
|
107
107
|
@property
|
|
108
108
|
def is_connected(self) -> bool:
|
|
@@ -189,7 +189,7 @@ class RabbitMQClient:
|
|
|
189
189
|
"""
|
|
190
190
|
从连接池获取资源并初始化(交换机、队列)
|
|
191
191
|
"""
|
|
192
|
-
logger.
|
|
192
|
+
logger.info(
|
|
193
193
|
f"连接参数 - force_reconnect={force_reconnect}, "
|
|
194
194
|
f"declare_queue={declare_queue}, create_if_not_exists={self.create_if_not_exists}"
|
|
195
195
|
)
|
|
@@ -275,7 +275,7 @@ class RabbitMQClient:
|
|
|
275
275
|
# 不声明队列时的状态处理
|
|
276
276
|
self.queue = None
|
|
277
277
|
self.actual_queue_name = None
|
|
278
|
-
logger.
|
|
278
|
+
logger.info(f"跳过队列 '{self.queue_name}' 的声明和绑定")
|
|
279
279
|
|
|
280
280
|
# 验证连接状态
|
|
281
281
|
if not self.is_connected:
|
|
@@ -320,13 +320,27 @@ class RabbitMQClient:
|
|
|
320
320
|
await self._recreate_channel()
|
|
321
321
|
continue
|
|
322
322
|
|
|
323
|
+
# 清理已确认的消息记录
|
|
324
|
+
if self._tracking_messages:
|
|
325
|
+
# 收集所有已确认的消息ID
|
|
326
|
+
acked_message_ids = [
|
|
327
|
+
msg_id for msg_id, msg_info in self._tracking_messages.items()
|
|
328
|
+
if msg_info.get('acked', False)
|
|
329
|
+
]
|
|
330
|
+
# 移除已确认的消息
|
|
331
|
+
for msg_id in acked_message_ids:
|
|
332
|
+
del self._tracking_messages[msg_id]
|
|
333
|
+
if acked_message_ids:
|
|
334
|
+
logger.info(
|
|
335
|
+
f"清理了 {len(acked_message_ids)} 条已确认的消息跟踪记录")
|
|
336
|
+
|
|
323
337
|
# 检查消费停滞
|
|
324
338
|
if self._is_consuming:
|
|
325
339
|
current_time = asyncio.get_event_loop().time()
|
|
326
340
|
if current_time - self._last_message_processed > self.consumption_stall_threshold:
|
|
327
|
-
if self.
|
|
328
|
-
logger.
|
|
329
|
-
f"消费停滞,但有 {len(self.
|
|
341
|
+
if self._tracking_messages:
|
|
342
|
+
logger.info(
|
|
343
|
+
f"消费停滞,但有 {len(self._tracking_messages)} 个消息正在处理,暂不重启")
|
|
330
344
|
else:
|
|
331
345
|
# 确实无消息处理,再重启
|
|
332
346
|
await self.stop_consuming()
|
|
@@ -336,7 +350,7 @@ class RabbitMQClient:
|
|
|
336
350
|
logger.error(f"监控任务出错: {str(e)}")
|
|
337
351
|
await asyncio.sleep(1)
|
|
338
352
|
|
|
339
|
-
await asyncio.sleep(
|
|
353
|
+
await asyncio.sleep(60)
|
|
340
354
|
|
|
341
355
|
self._monitor_task = asyncio.create_task(monitor())
|
|
342
356
|
|
|
@@ -375,7 +389,7 @@ class RabbitMQClient:
|
|
|
375
389
|
current_time = asyncio.get_event_loop().time()
|
|
376
390
|
# 检查是否超过指定时间无活动
|
|
377
391
|
if current_time - self._last_activity_timestamp > self.connection_pool.heartbeat * 1.5:
|
|
378
|
-
logger.
|
|
392
|
+
logger.info(
|
|
379
393
|
f"连接 {self.connection_pool.heartbeat*1.5}s 无活动,执行保活检查")
|
|
380
394
|
try:
|
|
381
395
|
if self.channel.is_closed:
|
|
@@ -440,7 +454,7 @@ class RabbitMQClient:
|
|
|
440
454
|
self.exchange = None
|
|
441
455
|
self.queue = None
|
|
442
456
|
self._consumer_tag = None
|
|
443
|
-
self.
|
|
457
|
+
self._tracking_messages.clear()
|
|
444
458
|
|
|
445
459
|
logger.info("RabbitMQ客户端已关闭")
|
|
446
460
|
|
|
@@ -488,13 +502,13 @@ class RabbitMQClient:
|
|
|
488
502
|
message,
|
|
489
503
|
routing_key=routing_key or self.routing_key or '#',
|
|
490
504
|
mandatory=True,
|
|
491
|
-
timeout=
|
|
505
|
+
timeout=5.0
|
|
492
506
|
)
|
|
493
507
|
if not confirmed:
|
|
494
508
|
raise Exception("消息未被服务器确认接收")
|
|
495
509
|
|
|
496
510
|
self._update_activity_timestamp()
|
|
497
|
-
logger.
|
|
511
|
+
logger.info(f"消息已发布到交换机 '{self.exchange_name}'")
|
|
498
512
|
return
|
|
499
513
|
except (ConnectionClosed, ChannelInvalidStateError):
|
|
500
514
|
retry_count += 1
|
|
@@ -514,7 +528,7 @@ class RabbitMQClient:
|
|
|
514
528
|
|
|
515
529
|
async def start_consuming(self) -> ConsumerTag:
|
|
516
530
|
if self._is_consuming:
|
|
517
|
-
logger.
|
|
531
|
+
logger.info("已经在消费中,返回现有consumer_tag")
|
|
518
532
|
if self._consumer_tag:
|
|
519
533
|
return self._consumer_tag
|
|
520
534
|
# 如果_is_consuming为True但无consumer_tag,重置状态并重新启动
|
|
@@ -577,15 +591,15 @@ class RabbitMQClient:
|
|
|
577
591
|
await self._safe_cancel_consumer()
|
|
578
592
|
|
|
579
593
|
# 等待所有正在处理的消息完成
|
|
580
|
-
if self.
|
|
594
|
+
if self._tracking_messages:
|
|
581
595
|
logger.info(
|
|
582
|
-
f"等待 {len(self.
|
|
583
|
-
while self.
|
|
584
|
-
await asyncio.sleep(
|
|
596
|
+
f"等待 {len(self._tracking_messages)} 个正在处理的消息完成...")
|
|
597
|
+
while self._tracking_messages and not self._closed:
|
|
598
|
+
await asyncio.sleep(1)
|
|
585
599
|
|
|
586
600
|
# 清理状态
|
|
587
601
|
self._consumer_tag = None
|
|
588
|
-
self.
|
|
602
|
+
self._tracking_messages.clear()
|
|
589
603
|
|
|
590
604
|
logger.info(f"已停止消费队列: {self.actual_queue_name}")
|
|
591
605
|
|
|
@@ -615,23 +629,29 @@ class RabbitMQClient:
|
|
|
615
629
|
return
|
|
616
630
|
|
|
617
631
|
message_id = message.message_id or str(id(message))
|
|
618
|
-
if message_id in self.
|
|
632
|
+
if message_id in self._tracking_messages:
|
|
619
633
|
logger.warning(f"检测到重复处理的消息ID: {message_id},直接确认")
|
|
620
634
|
await message.ack()
|
|
621
635
|
return
|
|
622
636
|
|
|
623
|
-
|
|
637
|
+
# 记录消息跟踪信息
|
|
638
|
+
self._tracking_messages[message_id] = {
|
|
639
|
+
'delivery_tag': message.delivery_tag,
|
|
640
|
+
'acked': False,
|
|
641
|
+
'channel_number': self.channel.number if self.channel else None
|
|
642
|
+
}
|
|
624
643
|
|
|
625
644
|
try:
|
|
626
|
-
logger.
|
|
645
|
+
logger.info(f"收到队列 {self.actual_queue_name} 的消息: {message_id}")
|
|
627
646
|
|
|
628
647
|
parsed_data = await self._parse_message(message)
|
|
629
648
|
await self.message_handler(MQMsgModel(** parsed_data), message)
|
|
630
649
|
|
|
631
650
|
await message.ack()
|
|
651
|
+
self._tracking_messages[message_id]['acked'] = True # 更新ACK状态
|
|
632
652
|
self._update_activity_timestamp()
|
|
633
653
|
self._update_message_processed_timestamp()
|
|
634
|
-
logger.
|
|
654
|
+
logger.info(f"消息 {message_id} 处理完成并确认")
|
|
635
655
|
|
|
636
656
|
except Exception as e:
|
|
637
657
|
current_headers = message.headers or {}
|
|
@@ -647,6 +667,7 @@ class RabbitMQClient:
|
|
|
647
667
|
logger.error(
|
|
648
668
|
f"消息 {message_id} 已达到最大重试次数({MAX_RETRY_COUNT}次),标记为失败")
|
|
649
669
|
await message.ack()
|
|
670
|
+
self._tracking_messages[message_id]['acked'] = True # 更新ACK状态
|
|
650
671
|
self._update_activity_timestamp()
|
|
651
672
|
return
|
|
652
673
|
|
|
@@ -661,6 +682,7 @@ class RabbitMQClient:
|
|
|
661
682
|
)
|
|
662
683
|
|
|
663
684
|
await message.reject(requeue=False)
|
|
685
|
+
self._tracking_messages[message_id]['acked'] = True # 拒绝也算处理完成
|
|
664
686
|
|
|
665
687
|
if self.exchange:
|
|
666
688
|
await self.exchange.publish(
|
|
@@ -672,8 +694,8 @@ class RabbitMQClient:
|
|
|
672
694
|
self._update_activity_timestamp()
|
|
673
695
|
logger.info(f"消息 {message_id} 已重新发布,当前重试次数: {retry_count}")
|
|
674
696
|
finally:
|
|
675
|
-
if message_id in self.
|
|
676
|
-
self.
|
|
697
|
+
if message_id in self._tracking_messages:
|
|
698
|
+
del self._tracking_messages[message_id]
|
|
677
699
|
|
|
678
700
|
async def __aenter__(self):
|
|
679
701
|
await self.connect()
|
|
@@ -142,7 +142,7 @@ class RabbitMQService:
|
|
|
142
142
|
else:
|
|
143
143
|
logger.info(f"监听器队列已包含app-name: {processed_queue_name}")
|
|
144
144
|
|
|
145
|
-
logger.
|
|
145
|
+
logger.info(
|
|
146
146
|
f"创建客户端 - 队列: {processed_queue_name}, 发送器: {is_sender}, "
|
|
147
147
|
f"允许创建: {create_if_not_exists}"
|
|
148
148
|
)
|
|
@@ -161,7 +161,7 @@ class RabbitMQService:
|
|
|
161
161
|
auto_parse_json=kwargs.get('auto_parse_json', True),
|
|
162
162
|
create_if_not_exists=create_if_not_exists,
|
|
163
163
|
connection_timeout=kwargs.get('connection_timeout', 10),
|
|
164
|
-
rpc_timeout=kwargs.get('rpc_timeout',
|
|
164
|
+
rpc_timeout=kwargs.get('rpc_timeout', 10),
|
|
165
165
|
reconnection_delay=kwargs.get('reconnection_delay', 1),
|
|
166
166
|
max_reconnection_attempts=kwargs.get(
|
|
167
167
|
'max_reconnection_attempts', 5),
|
|
@@ -207,12 +207,12 @@ class RabbitMQService:
|
|
|
207
207
|
if client.is_connected:
|
|
208
208
|
# 如果是监听器但队列未初始化,重新连接
|
|
209
209
|
if not is_sender and not client.queue:
|
|
210
|
-
logger.
|
|
210
|
+
logger.info(f"客户端 '{client_name}' 队列未初始化,重新连接")
|
|
211
211
|
client.create_if_not_exists = True
|
|
212
212
|
await client.connect(force_reconnect=True, declare_queue=True)
|
|
213
213
|
return client
|
|
214
214
|
else:
|
|
215
|
-
logger.
|
|
215
|
+
logger.info(f"客户端 '{client_name}' 连接已关闭,重新连接")
|
|
216
216
|
if not is_sender:
|
|
217
217
|
client.create_if_not_exists = True
|
|
218
218
|
await client.connect(declare_queue=not is_sender)
|
|
@@ -240,7 +240,7 @@ class RabbitMQService:
|
|
|
240
240
|
|
|
241
241
|
# 检查队列是否已初始化
|
|
242
242
|
if initial_queue_name in cls._initialized_queues:
|
|
243
|
-
logger.
|
|
243
|
+
logger.info(f"队列 '{initial_queue_name}' 已初始化,直接创建客户端")
|
|
244
244
|
client = await cls._create_client(
|
|
245
245
|
initial_queue_name, ** kwargs
|
|
246
246
|
)
|
|
@@ -296,11 +296,11 @@ class RabbitMQService:
|
|
|
296
296
|
normalized_name = queue_name
|
|
297
297
|
if app_name and normalized_name.endswith(f".{app_name}"):
|
|
298
298
|
normalized_name = normalized_name[:-len(f".{app_name}")]
|
|
299
|
-
logger.
|
|
299
|
+
logger.info(f"发送器队列名称移除app-name后缀: {normalized_name}")
|
|
300
300
|
|
|
301
301
|
# 检查是否已初始化
|
|
302
302
|
if normalized_name in cls._sender_client_names:
|
|
303
|
-
logger.
|
|
303
|
+
logger.info(f"发送客户端 '{normalized_name}' 已存在,跳过")
|
|
304
304
|
continue
|
|
305
305
|
|
|
306
306
|
# 获取或创建客户端
|
|
@@ -405,7 +405,7 @@ class RabbitMQService:
|
|
|
405
405
|
raise ValueError("RabbitMQService尚未初始化,请先调用init方法")
|
|
406
406
|
|
|
407
407
|
if queue_name in cls._message_handlers:
|
|
408
|
-
logger.
|
|
408
|
+
logger.info(f"监听器 '{queue_name}' 已存在,跳过重复添加")
|
|
409
409
|
return
|
|
410
410
|
|
|
411
411
|
# 创建并初始化客户端
|
|
@@ -429,7 +429,7 @@ class RabbitMQService:
|
|
|
429
429
|
async def start_consumer(cls, client_name: str) -> None:
|
|
430
430
|
"""启动指定客户端的消费者"""
|
|
431
431
|
if client_name in cls._consumer_tasks and not cls._consumer_tasks[client_name].done():
|
|
432
|
-
logger.
|
|
432
|
+
logger.info(f"消费者 '{client_name}' 已在运行中,无需重复启动")
|
|
433
433
|
return
|
|
434
434
|
|
|
435
435
|
if client_name not in cls._clients:
|
|
@@ -451,7 +451,7 @@ class RabbitMQService:
|
|
|
451
451
|
if asyncio.get_event_loop().time() - start_time > cls.CONSUMER_START_TIMEOUT:
|
|
452
452
|
raise TimeoutError(f"等待客户端 '{client_name}' 连接超时")
|
|
453
453
|
|
|
454
|
-
logger.
|
|
454
|
+
logger.info(f"等待客户端 '{client_name}' 连接就绪...")
|
|
455
455
|
await asyncio.sleep(1)
|
|
456
456
|
|
|
457
457
|
# 创建停止事件
|
|
@@ -557,7 +557,7 @@ class RabbitMQService:
|
|
|
557
557
|
if app_name and f"{queue_name}.{app_name}" in cls._sender_client_names:
|
|
558
558
|
return cls._clients.get(f"{queue_name}.{app_name}")
|
|
559
559
|
|
|
560
|
-
logger.
|
|
560
|
+
logger.info(f"未找到发送器 '{queue_name}'")
|
|
561
561
|
return None
|
|
562
562
|
|
|
563
563
|
@classmethod
|
|
@@ -651,7 +651,7 @@ class RabbitMQService:
|
|
|
651
651
|
raise
|
|
652
652
|
|
|
653
653
|
@classmethod
|
|
654
|
-
async def shutdown(cls, timeout: float =
|
|
654
|
+
async def shutdown(cls, timeout: float = 15.0) -> None:
|
|
655
655
|
"""优雅关闭所有资源(新增连接池关闭逻辑)"""
|
|
656
656
|
start_time = asyncio.get_event_loop().time()
|
|
657
657
|
logger.info("开始关闭RabbitMQ服务...")
|
|
@@ -35,9 +35,9 @@ sycommon/models/mqlistener_config.py,sha256=vXp2uMmd0XQ5B9noSRXWHewTy-juQ2y7IsWt
|
|
|
35
35
|
sycommon/models/mqmsg_model.py,sha256=cxn0M5b0utQK6crMYmL-1waeGYHvK3AlGaRy23clqTE,277
|
|
36
36
|
sycommon/models/mqsend_config.py,sha256=NQX9dc8PpuquMG36GCVhJe8omAW1KVXXqr6lSRU6D7I,268
|
|
37
37
|
sycommon/models/sso_user.py,sha256=i1WAN6k5sPcPApQEdtjpWDy7VrzWLpOrOQewGLGoGIw,2702
|
|
38
|
-
sycommon/rabbitmq/rabbitmq_client.py,sha256=
|
|
38
|
+
sycommon/rabbitmq/rabbitmq_client.py,sha256=TSeUItuPLbCCkQhsc81Cz3qcGATiTaZhtkiRxdhi72o,28407
|
|
39
39
|
sycommon/rabbitmq/rabbitmq_pool.py,sha256=_NMOO4CZy-I_anMqpzfYinz-8373_rg5FM9eqzdjGyU,3598
|
|
40
|
-
sycommon/rabbitmq/rabbitmq_service.py,sha256=
|
|
40
|
+
sycommon/rabbitmq/rabbitmq_service.py,sha256=1htwoA27uRVU-Vzgezonq95iBE1tGVi4poRw8qX2-ls,30163
|
|
41
41
|
sycommon/sse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
42
|
sycommon/sse/event.py,sha256=k_rBJy23R7crtzQeetT0Q73D8o5-5p-eESGSs_BPOj0,2797
|
|
43
43
|
sycommon/sse/sse.py,sha256=__CfWEcYxOxQ-HpLor4LTZ5hLWqw9-2X7CngqbVHsfw,10128
|
|
@@ -52,8 +52,8 @@ sycommon/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
52
52
|
sycommon/tools/docs.py,sha256=OPj2ETheuWjXLyaXtaZPbwmJKfJaYXV5s4XMVAUNrms,1607
|
|
53
53
|
sycommon/tools/snowflake.py,sha256=DdEj3T5r5OEvikp3puxqmmmz6BrggxomoSlnsRFb5dM,1174
|
|
54
54
|
sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
|
|
55
|
-
sycommon_python_lib-0.1.
|
|
56
|
-
sycommon_python_lib-0.1.
|
|
57
|
-
sycommon_python_lib-0.1.
|
|
58
|
-
sycommon_python_lib-0.1.
|
|
59
|
-
sycommon_python_lib-0.1.
|
|
55
|
+
sycommon_python_lib-0.1.32.dist-info/METADATA,sha256=0a2NR7XmC94hHtEK3o0ipLLcROts-tv4anODwKYUUrY,7037
|
|
56
|
+
sycommon_python_lib-0.1.32.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
57
|
+
sycommon_python_lib-0.1.32.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
|
|
58
|
+
sycommon_python_lib-0.1.32.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
|
|
59
|
+
sycommon_python_lib-0.1.32.dist-info/RECORD,,
|
|
File without changes
|
{sycommon_python_lib-0.1.31.dist-info → sycommon_python_lib-0.1.32.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|