sycommon-python-lib 0.2.0b1__py3-none-any.whl → 0.2.0b2__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.
@@ -28,62 +28,86 @@ class RabbitMQClientManager(RabbitMQCoreService):
28
28
 
29
29
  @classmethod
30
30
  async def _clean_client_resources(cls, client: RabbitMQClient) -> None:
31
- """清理客户端无效资源(支持显式关闭独立通道)"""
31
+ """
32
+ 清理客户端无效资源(修正版:只清理消费行为,不关闭 Channel)
33
+
34
+ 重要变更:
35
+ - 移除了 await client._channel.close() 调用。
36
+ - 原因:关闭 Channel 可能会触发底层连接的 close_callback,导致重连死锁或冲突。
37
+ - Channel 的关闭应该由 RabbitMQClient.connect() 内部的重建逻辑接管。
38
+ """
32
39
  try:
33
- # 1. 先尝试正常停止消费
40
+ # 1. 尝试正常停止消费(发送 basic_cancel)
34
41
  if client._consumer_tag:
35
42
  await client.stop_consuming()
36
43
  except Exception as e:
37
44
  logger.warning(f"停止消费逻辑异常: {str(e)}")
38
45
 
46
+ # 注意:这里不再显式关闭 client._channel
47
+ # 原因:
48
+ # 1. 如果是消费者独立通道,关闭它是安全的,但不如交给 connect() 统一处理(重建前关闭)。
49
+ # 2. 如果是生产者主通道(由 Pool 缓存),绝对不能在这里关闭!否则会影响其他生产者。
50
+ # 3. connect() 方法已经包含了 "显式关闭旧 Channel" 的逻辑,这里重复操作是多余的且危险的。
51
+
39
52
  try:
40
- # 2. 【关键】显式关闭 Channel
41
- # 在我们的新架构中,消费者持有独立通道,必须在这里显式关闭。
42
- # 生产者持有的主通道虽然通常由 Pool 管理,但这里为了彻底清理,
43
- # 可以尝试关闭(Pool 内部会有保护,或者接受主通道被关闭后重新创建)。
44
- if client._channel and not client._channel.is_closed:
45
- try:
46
- await client._channel.close()
47
- logger.debug(f"清理资源:已关闭客户端通道")
48
- except Exception as e:
49
- logger.warning(f"清理资源:关闭通道异常: {e}")
50
- except Exception as e:
51
- logger.warning(f"清理资源过程发生异常: {str(e)}")
52
- finally:
53
- # 3. 强制重置客户端状态
54
- # 注意:不要将 _channel_conn 置空,因为它是连接池的引用,置空后可能导致逻辑判断出错
55
- # 但为了彻底断开,置空也是安全的,因为 connect 会重新获取。
53
+ # 2. 重置客户端状态引用(为后续 connect() 扫清障碍)
54
+ # 注意:虽然清理了状态,但不要清空 _message_handler!
56
55
  client._channel = None
57
56
  client._channel_conn = None
58
57
  client._exchange = None
59
58
  client._queue = None
60
59
  client._consumer_tag = None
60
+ except Exception as e:
61
+ logger.warning(f"重置客户端状态异常: {str(e)}")
61
62
 
62
63
  @classmethod
63
64
  async def _reconnect_client(cls, client_name: str, client: RabbitMQClient) -> bool:
64
- """客户端重连"""
65
+ """客户端重连(修正版:保存与恢复 Handler,确保消费可恢复)"""
65
66
  if cls._is_shutdown or not (cls._connection_pool and await cls._connection_pool.is_alive):
66
67
  return False
67
68
 
68
69
  # 重连冷却
69
70
  await asyncio.sleep(cls.RECONNECT_INTERVAL)
70
71
 
72
+ # 【关键修复 1】状态快照
73
+ # 在清理资源前,保存关键状态,因为 _clean_client_resources 不会清空它,
74
+ # 但为了防御性编程,以及后续逻辑的清晰,我们显式保存。
75
+ saved_handler = client._message_handler
76
+ saved_queue_name = client.queue_name
77
+
71
78
  try:
72
- # 清理旧资源
79
+ # 1. 清理旧资源
80
+ # 修正后的版本:只停止消费,不关闭 Channel
73
81
  await cls._clean_client_resources(client)
74
82
 
75
- # 执行重连
83
+ # 2. 【关键修复 2】立即恢复 MessageHandler
84
+ # connect() 方法依赖 self._message_handler 来判断是否执行 "was_consuming" 的恢复逻辑。
85
+ # 如果不恢复,connect() 虽然会连上,但会跳过 start_consuming。
86
+ if saved_handler:
87
+ client._message_handler = saved_handler
88
+
89
+ # 防御性恢复队列名
90
+ if saved_queue_name:
91
+ client.queue_name = saved_queue_name
92
+
93
+ # 3. 执行重连
94
+ # 此时 client 处于“空资源但有 Handler”的状态,正是 connect() 期望的状态
76
95
  await client.connect()
77
96
 
78
97
  # 验证重连结果
79
98
  if await client.is_connected:
80
- logger.info(f"客户端 '{client_name}' 重连成功")
99
+ logger.info(f"客户端 '{client_name}' 重连成功")
81
100
  return True
82
101
  else:
83
- logger.warning(f"客户端 '{client_name}' 重连失败:资源未完全初始化")
102
+ logger.warning(f"⚠️ 客户端 '{client_name}' 重连失败:资源未完全初始化")
84
103
  return False
104
+
85
105
  except Exception as e:
86
- logger.error(f"客户端 '{client_name}' 重连失败: {str(e)}", exc_info=True)
106
+ logger.error(
107
+ f"❌ 客户端 '{client_name}' 重连失败: {str(e)}", exc_info=True)
108
+ # 异常情况下也尝试恢复 handler,以便下次重试能成功
109
+ if saved_handler:
110
+ client._message_handler = saved_handler
87
111
  return False
88
112
 
89
113
  @classmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.2.0b1
3
+ Version: 0.2.0b2
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -54,7 +54,7 @@ sycommon/notice/uvicorn_monitor.py,sha256=PrC-OFRE71mL8TcbfdkJRKbjwGAbgsWtyBPWIw
54
54
  sycommon/rabbitmq/rabbitmq_client.py,sha256=MC4QNSZpfYSPHY8-iW3RRuZAs0MZcNGWJD9EzCLc68k,22115
55
55
  sycommon/rabbitmq/rabbitmq_pool.py,sha256=igQ4Yh96oZyM8UEhNa_rljhZcitHwske3UsjPtBuj8c,18946
56
56
  sycommon/rabbitmq/rabbitmq_service.py,sha256=XSHo9HuIJ_lq-vizRh4xJVdZr_2zLqeLhot09qb0euA,2025
57
- sycommon/rabbitmq/rabbitmq_service_client_manager.py,sha256=O4zVL7lY2eaN_hUajwB5Ai6nnW-bevRBXysxSMhfVqw,9005
57
+ sycommon/rabbitmq/rabbitmq_service_client_manager.py,sha256=NrJI4JKyItrMwQUFVZu0GWAx8krUdgUeyessFuUWhjo,10280
58
58
  sycommon/rabbitmq/rabbitmq_service_connection_monitor.py,sha256=uvoMuJDzJ9i63uVRq1NKFV10CvkbGnTMyEoq2rgjQx8,3013
59
59
  sycommon/rabbitmq/rabbitmq_service_consumer_manager.py,sha256=489r1RKd5WrTNMAcWCxUZpt9yWGrNunZlLCCp-M_rzM,11497
60
60
  sycommon/rabbitmq/rabbitmq_service_core.py,sha256=6RMvIf78DmEOZmN8dA0duA9oy4ieNswdGrOeyJdD6tU,4753
@@ -84,8 +84,8 @@ sycommon/tools/merge_headers.py,sha256=u9u8_1ZIuGIminWsw45YJ5qnsx9MB-Fot0VPge7it
84
84
  sycommon/tools/snowflake.py,sha256=xQlYXwYnI85kSJ1rZ89gMVBhzemP03xrMPVX9vVa3MY,9228
85
85
  sycommon/tools/syemail.py,sha256=BDFhgf7WDOQeTcjxJEQdu0dQhnHFPO_p3eI0-Ni3LhQ,5612
86
86
  sycommon/tools/timing.py,sha256=OiiE7P07lRoMzX9kzb8sZU9cDb0zNnqIlY5pWqHcnkY,2064
87
- sycommon_python_lib-0.2.0b1.dist-info/METADATA,sha256=5MhM3eTt-f3-du7nf8tlpH8wDKIU3_4z6nIRURL6Rg4,7372
88
- sycommon_python_lib-0.2.0b1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
89
- sycommon_python_lib-0.2.0b1.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
90
- sycommon_python_lib-0.2.0b1.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
91
- sycommon_python_lib-0.2.0b1.dist-info/RECORD,,
87
+ sycommon_python_lib-0.2.0b2.dist-info/METADATA,sha256=YydQcYEWv2QGklHoJKu2z1mn8UT-Xtr8V_m0xW0Ig00,7372
88
+ sycommon_python_lib-0.2.0b2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
89
+ sycommon_python_lib-0.2.0b2.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
90
+ sycommon_python_lib-0.2.0b2.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
91
+ sycommon_python_lib-0.2.0b2.dist-info/RECORD,,