sycommon-python-lib 0.1.32__tar.gz → 0.1.33__tar.gz

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.

Files changed (64) hide show
  1. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/PKG-INFO +1 -1
  2. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/pyproject.toml +1 -1
  3. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/rabbitmq/rabbitmq_client.py +58 -73
  4. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/rabbitmq/rabbitmq_service.py +1 -1
  5. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/services.py +4 -0
  6. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon_python_lib.egg-info/PKG-INFO +1 -1
  7. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/README.md +0 -0
  8. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/setup.cfg +0 -0
  9. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/command/cli.py +0 -0
  10. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/__init__.py +0 -0
  11. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/config/Config.py +0 -0
  12. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/config/DatabaseConfig.py +0 -0
  13. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/config/EmbeddingConfig.py +0 -0
  14. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/config/LLMConfig.py +0 -0
  15. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/config/MQConfig.py +0 -0
  16. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/config/RerankerConfig.py +0 -0
  17. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/config/__init__.py +0 -0
  18. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/database/base_db_service.py +0 -0
  19. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/database/database_service.py +0 -0
  20. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/health/__init__.py +0 -0
  21. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/health/health_check.py +0 -0
  22. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/health/metrics.py +0 -0
  23. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/health/ping.py +0 -0
  24. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/logging/__init__.py +0 -0
  25. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/logging/kafka_log.py +0 -0
  26. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/logging/logger_wrapper.py +0 -0
  27. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/logging/sql_logger.py +0 -0
  28. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/__init__.py +0 -0
  29. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/context.py +0 -0
  30. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/cors.py +0 -0
  31. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/docs.py +0 -0
  32. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/exception.py +0 -0
  33. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/middleware.py +0 -0
  34. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/monitor_memory.py +0 -0
  35. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/mq.py +0 -0
  36. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/timeout.py +0 -0
  37. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/middleware/traceid.py +0 -0
  38. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/models/__init__.py +0 -0
  39. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/models/base_http.py +0 -0
  40. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/models/log.py +0 -0
  41. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/models/mqlistener_config.py +0 -0
  42. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/models/mqmsg_model.py +0 -0
  43. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/models/mqsend_config.py +0 -0
  44. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/models/sso_user.py +0 -0
  45. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/rabbitmq/rabbitmq_pool.py +0 -0
  46. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/sse/__init__.py +0 -0
  47. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/sse/event.py +0 -0
  48. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/sse/sse.py +0 -0
  49. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/synacos/__init__.py +0 -0
  50. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/synacos/example.py +0 -0
  51. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/synacos/example2.py +0 -0
  52. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/synacos/feign.py +0 -0
  53. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/synacos/feign_client.py +0 -0
  54. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/synacos/nacos_service.py +0 -0
  55. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/synacos/param.py +0 -0
  56. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/tools/__init__.py +0 -0
  57. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/tools/docs.py +0 -0
  58. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/tools/snowflake.py +0 -0
  59. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon/tools/timing.py +0 -0
  60. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon_python_lib.egg-info/SOURCES.txt +0 -0
  61. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
  62. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
  63. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon_python_lib.egg-info/requires.txt +0 -0
  64. {sycommon_python_lib-0.1.32 → sycommon_python_lib-0.1.33}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.1.32
3
+ Version: 0.1.33
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sycommon-python-lib"
3
- version = "0.1.32"
3
+ version = "0.1.33"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -45,11 +45,6 @@ class RabbitMQClient:
45
45
  prefetch_count: int = 2,
46
46
  consumption_stall_threshold: int = 10
47
47
  ):
48
- """
49
- 初始化RabbitMQ客户端(依赖连接池)
50
-
51
- :param connection_pool: 连接池实例
52
- """
53
48
  # 连接池依赖
54
49
  self.connection_pool = connection_pool
55
50
 
@@ -85,7 +80,7 @@ class RabbitMQClient:
85
80
  self._exchange_exists = False
86
81
  self._queue_exists = False
87
82
  self._queue_bound = False
88
- self._is_consuming = False
83
+ self._is_consuming = False # 核心消费状态标志
89
84
  self._closed = False
90
85
  self._consumer_tag: Optional[ConsumerTag] = None
91
86
  self._last_activity_timestamp = asyncio.get_event_loop().time()
@@ -120,19 +115,23 @@ class RabbitMQClient:
120
115
  """更新最后消息处理时间戳"""
121
116
  self._last_message_processed = asyncio.get_event_loop().time()
122
117
 
118
+ def _set_is_consuming(self, value: bool) -> None:
119
+ """安全更新消费状态并记录日志"""
120
+ if self._is_consuming != value:
121
+ logger.info(f"消费状态变更: {self._is_consuming} → {value}")
122
+ self._is_consuming = value
123
+
123
124
  async def _get_channel(self) -> AbstractChannel:
124
125
  """从通道池获取通道(使用上下文管理器)"""
125
126
  if not self.connection_pool.channel_pool:
126
127
  raise Exception("连接池未初始化,请先调用init_pools")
127
128
 
128
- # 使用async with获取通道,并通过变量返回
129
129
  async with self.connection_pool.channel_pool.acquire() as channel:
130
130
  return channel
131
131
 
132
132
  async def _check_exchange_exists(self, channel: AbstractChannel) -> bool:
133
133
  """检查交换机是否存在"""
134
134
  try:
135
- # 使用被动模式检查交换机
136
135
  await asyncio.wait_for(
137
136
  channel.declare_exchange(
138
137
  name=self.exchange_name,
@@ -150,7 +149,6 @@ class RabbitMQClient:
150
149
  if not self.queue_name:
151
150
  return False
152
151
  try:
153
- # 使用被动模式检查队列
154
152
  await asyncio.wait_for(
155
153
  channel.declare_queue(
156
154
  name=self.queue_name,
@@ -186,19 +184,15 @@ class RabbitMQClient:
186
184
  return False
187
185
 
188
186
  async def connect(self, force_reconnect: bool = False, declare_queue: bool = True) -> None:
189
- """
190
- 从连接池获取资源并初始化(交换机、队列)
191
- """
187
+ """从连接池获取资源并初始化(交换机、队列)"""
192
188
  logger.info(
193
189
  f"连接参数 - force_reconnect={force_reconnect}, "
194
190
  f"declare_queue={declare_queue}, create_if_not_exists={self.create_if_not_exists}"
195
191
  )
196
192
 
197
- # 如果已连接且不强制重连,则直接返回
198
193
  if self.is_connected and not force_reconnect:
199
194
  return
200
195
 
201
- # 取消正在进行的重连任务
202
196
  if self._reconnect_task and not self._reconnect_task.done():
203
197
  self._reconnect_task.cancel()
204
198
 
@@ -206,13 +200,13 @@ class RabbitMQClient:
206
200
  self._exchange_exists = False
207
201
  self._queue_exists = False
208
202
  self._queue_bound = False
203
+ self._set_is_consuming(False) # 连接时先停止消费
209
204
 
210
205
  retries = 0
211
206
  last_exception = None
212
207
 
213
208
  while retries < self.max_reconnection_attempts:
214
209
  try:
215
- # 从池获取通道
216
210
  self.channel = await self._get_channel()
217
211
  await self.channel.set_qos(prefetch_count=self.prefetch_count)
218
212
 
@@ -220,7 +214,6 @@ class RabbitMQClient:
220
214
  exchange_exists = await self._check_exchange_exists(self.channel)
221
215
  if not exchange_exists:
222
216
  if self.create_if_not_exists:
223
- # 创建交换机
224
217
  self.exchange = await asyncio.wait_for(
225
218
  self.channel.declare_exchange(
226
219
  name=self.exchange_name,
@@ -235,7 +228,6 @@ class RabbitMQClient:
235
228
  raise Exception(
236
229
  f"交换机 '{self.exchange_name}' 不存在且不允许自动创建")
237
230
  else:
238
- # 获取已有交换机
239
231
  self.exchange = await self.channel.get_exchange(self.exchange_name)
240
232
  logger.info(f"使用已存在的交换机 '{self.exchange_name}'")
241
233
 
@@ -248,7 +240,6 @@ class RabbitMQClient:
248
240
  raise Exception(
249
241
  f"队列 '{self.queue_name}' 不存在且不允许自动创建")
250
242
 
251
- # 创建队列
252
243
  self.queue = await asyncio.wait_for(
253
244
  self.channel.declare_queue(
254
245
  name=self.queue_name,
@@ -261,7 +252,6 @@ class RabbitMQClient:
261
252
  self.actual_queue_name = self.queue_name
262
253
  logger.info(f"已创建队列 '{self.queue_name}'")
263
254
  else:
264
- # 获取已有队列
265
255
  self.queue = await self.channel.get_queue(self.queue_name)
266
256
  self.actual_queue_name = self.queue_name
267
257
  logger.info(f"使用已存在的队列 '{self.queue_name}'")
@@ -272,31 +262,30 @@ class RabbitMQClient:
272
262
  if not bound:
273
263
  raise Exception(f"队列 '{self.queue_name}' 绑定到交换机失败")
274
264
  else:
275
- # 不声明队列时的状态处理
276
265
  self.queue = None
277
266
  self.actual_queue_name = None
278
267
  logger.info(f"跳过队列 '{self.queue_name}' 的声明和绑定")
279
268
 
280
- # 验证连接状态
281
269
  if not self.is_connected:
282
270
  raise Exception("连接验证失败,状态异常")
283
271
 
284
- # 如果之前在消费,重新开始消费
285
- if self._is_consuming and self.message_handler:
272
+ # 重新开始消费(如果之前在消费)
273
+ if self.message_handler:
286
274
  await self.start_consuming()
287
275
 
288
- # 启动连接监控和保活任务
276
+ # 启动监控和保活任务
289
277
  self._start_monitoring()
290
278
  self._start_keepalive()
291
279
 
292
280
  self._update_activity_timestamp()
281
+ # 清理可能残留的跟踪记录
282
+ self._tracking_messages.clear()
293
283
  logger.info(f"RabbitMQ客户端初始化成功 (队列: {self.actual_queue_name})")
294
284
  return
295
285
 
296
286
  except Exception as e:
297
287
  last_exception = e
298
288
  logger.warning(f"资源初始化失败: {str(e)},重试中...")
299
- # 释放当前通道(放回池并重新获取)
300
289
  self.channel = None
301
290
  retries += 1
302
291
  if retries < self.max_reconnection_attempts:
@@ -320,32 +309,32 @@ class RabbitMQClient:
320
309
  await self._recreate_channel()
321
310
  continue
322
311
 
323
- # 清理已确认的消息记录
312
+ current_time = asyncio.get_event_loop().time()
313
+ # 清理消息跟踪记录
324
314
  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)
315
+ # 1. 清理已确认的消息
316
+ acked_ids = [
317
+ msg_id for msg_id, info in self._tracking_messages.items()
318
+ if info.get('acked', False)
329
319
  ]
330
- # 移除已确认的消息
331
- for msg_id in acked_message_ids:
320
+ for msg_id in acked_ids:
332
321
  del self._tracking_messages[msg_id]
333
- if acked_message_ids:
334
- logger.info(
335
- f"清理了 {len(acked_message_ids)} 条已确认的消息跟踪记录")
322
+ if acked_ids:
323
+ logger.info(f"清理了 {len(acked_ids)} 条已确认消息记录")
336
324
 
337
325
  # 检查消费停滞
338
326
  if self._is_consuming:
339
- current_time = asyncio.get_event_loop().time()
340
327
  if current_time - self._last_message_processed > self.consumption_stall_threshold:
341
328
  if self._tracking_messages:
342
- logger.info(
329
+ logger.warning(
343
330
  f"消费停滞,但有 {len(self._tracking_messages)} 个消息正在处理,暂不重启")
344
331
  else:
345
- # 确实无消息处理,再重启
332
+ # 无有效消息,重启消费
333
+ logger.info("消费停滞且无消息处理,重启消费")
346
334
  await self.stop_consuming()
347
335
  await asyncio.sleep(1)
348
336
  await self.start_consuming()
337
+
349
338
  except Exception as e:
350
339
  logger.error(f"监控任务出错: {str(e)}")
351
340
  await asyncio.sleep(1)
@@ -356,21 +345,18 @@ class RabbitMQClient:
356
345
 
357
346
  async def _recreate_channel(self) -> None:
358
347
  try:
359
- # 无需手动释放,上下文管理器会自动处理
360
348
  self.channel = await self._get_channel()
361
349
  await self.channel.set_qos(prefetch_count=self.prefetch_count)
362
350
 
363
- # 重新获取交换机
351
+ # 重新获取交换机和队列
364
352
  self.exchange = await self.channel.get_exchange(self.exchange_name)
365
-
366
- # 重新绑定队列
367
353
  if self.queue_name:
368
354
  self.queue = await self.channel.get_queue(self.queue_name)
369
355
  if self.queue and self.exchange:
370
356
  await self._bind_queue(self.channel, self.queue, self.exchange)
371
357
 
372
358
  # 重新开始消费
373
- if self._is_consuming and self.message_handler:
359
+ if self.message_handler:
374
360
  await self.start_consuming()
375
361
 
376
362
  logger.info("通道已重建并恢复服务")
@@ -387,10 +373,9 @@ class RabbitMQClient:
387
373
  async def keepalive():
388
374
  while not self._closed and self.is_connected:
389
375
  current_time = asyncio.get_event_loop().time()
390
- # 检查是否超过指定时间无活动
391
- if current_time - self._last_activity_timestamp > self.connection_pool.heartbeat * 1.5:
376
+ if current_time - self._last_activity_timestamp > self.connection_pool.heartbeat * 2:
392
377
  logger.info(
393
- f"连接 {self.connection_pool.heartbeat*1.5}s 无活动,执行保活检查")
378
+ f"连接 {self.connection_pool.heartbeat*2}s 无活动,执行保活检查")
394
379
  try:
395
380
  if self.channel.is_closed:
396
381
  logger.warning("连接已关闭,触发重连")
@@ -411,7 +396,7 @@ class RabbitMQClient:
411
396
  logger.warning(f"保活检查失败: {str(e)},触发重连")
412
397
  await self.connect(force_reconnect=True)
413
398
 
414
- await asyncio.sleep(self.connection_pool.heartbeat / 2)
399
+ await asyncio.sleep(self.connection_pool.heartbeat)
415
400
 
416
401
  self._keepalive_task = asyncio.create_task(keepalive())
417
402
 
@@ -437,7 +422,7 @@ class RabbitMQClient:
437
422
  async def close(self) -> None:
438
423
  """关闭客户端并释放资源"""
439
424
  self._closed = True
440
- self._is_consuming = False
425
+ self._set_is_consuming(False)
441
426
 
442
427
  # 取消所有任务
443
428
  for task in [self._keepalive_task, self._reconnect_task,
@@ -495,14 +480,13 @@ class RabbitMQClient:
495
480
  max_retries = 2
496
481
  while retry_count < max_retries:
497
482
  try:
498
- # 从池获取新通道用于发布(避免长时间占用消费通道)
499
483
  async with self.connection_pool.channel_pool.acquire() as publish_channel:
500
484
  exchange = await publish_channel.get_exchange(self.exchange_name)
501
485
  confirmed = await exchange.publish(
502
486
  message,
503
487
  routing_key=routing_key or self.routing_key or '#',
504
488
  mandatory=True,
505
- timeout=5.0
489
+ timeout=5
506
490
  )
507
491
  if not confirmed:
508
492
  raise Exception("消息未被服务器确认接收")
@@ -510,9 +494,11 @@ class RabbitMQClient:
510
494
  self._update_activity_timestamp()
511
495
  logger.info(f"消息已发布到交换机 '{self.exchange_name}'")
512
496
  return
513
- except (ConnectionClosed, ChannelInvalidStateError):
497
+ except (ConnectionClosed, ChannelInvalidStateError, asyncio.TimeoutError):
498
+ # 覆盖更多异常类型
514
499
  retry_count += 1
515
- logger.warning(f"连接已关闭,尝试重连后重新发布 (重试次数: {retry_count})")
500
+ logger.warning(f"连接异常,尝试重连后重新发布 (重试次数: {retry_count})")
501
+ # 主动刷新连接状态
516
502
  await self.connect(force_reconnect=True)
517
503
  except Exception as e:
518
504
  retry_count += 1
@@ -522,7 +508,6 @@ class RabbitMQClient:
522
508
 
523
509
  raise Exception(f"消息发布失败,经过{retry_count}次重试仍未成功")
524
510
 
525
- # 以下方法(消息消费相关)逻辑与原有保持一致,仅适配连接池
526
511
  def set_message_handler(self, handler):
527
512
  self.message_handler = handler
528
513
 
@@ -531,9 +516,8 @@ class RabbitMQClient:
531
516
  logger.info("已经在消费中,返回现有consumer_tag")
532
517
  if self._consumer_tag:
533
518
  return self._consumer_tag
534
- # 如果_is_consuming为True但无consumer_tag,重置状态并重新启动
535
519
  logger.warning("检测到消费状态异常(无consumer_tag),重置状态后重试")
536
- self._is_consuming = False # 重置状态
520
+ self._set_is_consuming(False)
537
521
 
538
522
  if not self.is_connected:
539
523
  await self.connect()
@@ -544,25 +528,21 @@ class RabbitMQClient:
544
528
  if not self.message_handler:
545
529
  raise Exception("未设置消息处理函数")
546
530
 
547
- self._is_consuming = True
548
- logger.info(f"开始消费队列: {self.actual_queue_name}")
549
-
550
531
  try:
551
- # 调用队列的consume方法,确保获取到consumer_tag
552
532
  self._consumer_tag = await self.queue.consume(
553
533
  self._message_wrapper,
554
534
  no_ack=False # 手动确认消息
555
535
  )
556
536
 
557
- # 确保consumer_tag有效
558
537
  if not self._consumer_tag:
559
538
  raise Exception("未能获取到有效的consumer_tag")
560
539
 
540
+ self._set_is_consuming(True)
561
541
  logger.info(
562
542
  f"消费者已启动,队列: {self.actual_queue_name}, tag: {self._consumer_tag}")
563
543
  return self._consumer_tag
564
544
  except Exception as e:
565
- self._is_consuming = False # 异常时重置状态
545
+ self._set_is_consuming(False)
566
546
  logger.error(f"启动消费失败: {str(e)}", exc_info=True)
567
547
  raise
568
548
 
@@ -585,22 +565,25 @@ class RabbitMQClient:
585
565
  if not self._is_consuming:
586
566
  return
587
567
 
588
- self._is_consuming = False
568
+ self._set_is_consuming(False)
589
569
 
590
570
  if self._consumer_tag and self.queue:
591
571
  await self._safe_cancel_consumer()
592
572
 
593
573
  # 等待所有正在处理的消息完成
594
574
  if self._tracking_messages:
595
- logger.info(
596
- f"等待 {len(self._tracking_messages)} 个正在处理的消息完成...")
575
+ logger.info(f"等待 {len(self._tracking_messages)} 个正在处理的消息完成...")
576
+ wait_start = asyncio.get_event_loop().time()
597
577
  while self._tracking_messages and not self._closed:
578
+ if asyncio.get_event_loop().time() - wait_start > 30: # 最多等30秒
579
+ logger.warning("等待消息处理超时,强制清理跟踪记录")
580
+ self._tracking_messages.clear()
581
+ break
598
582
  await asyncio.sleep(1)
599
583
 
600
584
  # 清理状态
601
585
  self._consumer_tag = None
602
586
  self._tracking_messages.clear()
603
-
604
587
  logger.info(f"已停止消费队列: {self.actual_queue_name}")
605
588
 
606
589
  async def _parse_message(self, message: AbstractIncomingMessage) -> Union[Dict[str, Any], str]:
@@ -620,8 +603,7 @@ class RabbitMQClient:
620
603
 
621
604
  async def _message_wrapper(self, message: AbstractIncomingMessage) -> None:
622
605
  if not self.message_handler or not self._is_consuming:
623
- logger.warning("未设置消息处理器或已停止消费")
624
- # await message.ack()
606
+ logger.warning("未设置消息处理器或已停止消费,拒绝消息,重新放到队列")
625
607
  try:
626
608
  await message.reject(requeue=True)
627
609
  except Exception as e:
@@ -634,21 +616,23 @@ class RabbitMQClient:
634
616
  await message.ack()
635
617
  return
636
618
 
637
- # 记录消息跟踪信息
619
+ start_time = asyncio.get_event_loop().time()
638
620
  self._tracking_messages[message_id] = {
639
621
  'delivery_tag': message.delivery_tag,
640
622
  'acked': False,
641
- 'channel_number': self.channel.number if self.channel else None
623
+ 'channel_number': self.channel.number if self.channel else None,
624
+ 'start_time': start_time
642
625
  }
643
626
 
644
627
  try:
645
628
  logger.info(f"收到队列 {self.actual_queue_name} 的消息: {message_id}")
629
+ print(f"收到队列 {self.actual_queue_name} 的消息: {message_id}")
646
630
 
647
631
  parsed_data = await self._parse_message(message)
648
632
  await self.message_handler(MQMsgModel(** parsed_data), message)
649
633
 
650
634
  await message.ack()
651
- self._tracking_messages[message_id]['acked'] = True # 更新ACK状态
635
+ self._tracking_messages[message_id]['acked'] = True
652
636
  self._update_activity_timestamp()
653
637
  self._update_message_processed_timestamp()
654
638
  logger.info(f"消息 {message_id} 处理完成并确认")
@@ -665,9 +649,9 @@ class RabbitMQClient:
665
649
 
666
650
  if retry_count >= MAX_RETRY_COUNT:
667
651
  logger.error(
668
- f"消息 {message_id} 已达到最大重试次数({MAX_RETRY_COUNT}次),标记为失败")
652
+ f"消息 {message_id} 已达到最大重试次数{MAX_RETRY_COUNT},标记为失败")
669
653
  await message.ack()
670
- self._tracking_messages[message_id]['acked'] = True # 更新ACK状态
654
+ self._tracking_messages[message_id]['acked'] = True
671
655
  self._update_activity_timestamp()
672
656
  return
673
657
 
@@ -682,7 +666,7 @@ class RabbitMQClient:
682
666
  )
683
667
 
684
668
  await message.reject(requeue=False)
685
- self._tracking_messages[message_id]['acked'] = True # 拒绝也算处理完成
669
+ self._tracking_messages[message_id]['acked'] = True
686
670
 
687
671
  if self.exchange:
688
672
  await self.exchange.publish(
@@ -696,6 +680,7 @@ class RabbitMQClient:
696
680
  finally:
697
681
  if message_id in self._tracking_messages:
698
682
  del self._tracking_messages[message_id]
683
+ logger.info(f"已删除消息跟踪信息: {message_id}")
699
684
 
700
685
  async def __aenter__(self):
701
686
  await self.connect()
@@ -105,7 +105,7 @@ class RabbitMQService:
105
105
  )
106
106
 
107
107
  # 初始化连接池
108
- await cls._connection_pool.init_pools()
108
+ await asyncio.wait_for(cls._connection_pool.init_pools(), timeout=30)
109
109
  logger.info("RabbitMQ连接池初始化成功")
110
110
 
111
111
  except Exception as e:
@@ -199,6 +199,10 @@ class Services(metaclass=SingletonMeta):
199
199
  if not sender:
200
200
  raise ValueError(f"发送器 '{queue_name}' 不存在")
201
201
 
202
+ if not (sender.is_connected and sender.channel and not sender.channel.is_closed):
203
+ logging.info(f"发送器 '{queue_name}' 连接无效,强制重连")
204
+ await sender.connect(force_reconnect=True, declare_queue=False)
205
+
202
206
  await RabbitMQService.send_message(data, queue_name, ** kwargs)
203
207
  logging.info(f"消息发送成功(尝试 {attempt+1}/{max_retries})")
204
208
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sycommon-python-lib
3
- Version: 0.1.32
3
+ Version: 0.1.33
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown