sycommon-python-lib 0.1.32__py3-none-any.whl → 0.1.34__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 +108 -92
- sycommon/rabbitmq/rabbitmq_service.py +2 -2
- sycommon/services.py +4 -0
- {sycommon_python_lib-0.1.32.dist-info → sycommon_python_lib-0.1.34.dist-info}/METADATA +1 -1
- {sycommon_python_lib-0.1.32.dist-info → sycommon_python_lib-0.1.34.dist-info}/RECORD +8 -8
- {sycommon_python_lib-0.1.32.dist-info → sycommon_python_lib-0.1.34.dist-info}/WHEEL +0 -0
- {sycommon_python_lib-0.1.32.dist-info → sycommon_python_lib-0.1.34.dist-info}/entry_points.txt +0 -0
- {sycommon_python_lib-0.1.32.dist-info → sycommon_python_lib-0.1.34.dist-info}/top_level.txt +0 -0
|
@@ -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
|
|
|
@@ -103,6 +98,8 @@ class RabbitMQClient:
|
|
|
103
98
|
|
|
104
99
|
# 消息处理跟踪
|
|
105
100
|
self._tracking_messages: Dict[str, Dict[str, Any]] = {}
|
|
101
|
+
# 状态保护锁
|
|
102
|
+
self._state_lock = asyncio.Lock()
|
|
106
103
|
|
|
107
104
|
@property
|
|
108
105
|
def is_connected(self) -> bool:
|
|
@@ -120,19 +117,24 @@ class RabbitMQClient:
|
|
|
120
117
|
"""更新最后消息处理时间戳"""
|
|
121
118
|
self._last_message_processed = asyncio.get_event_loop().time()
|
|
122
119
|
|
|
120
|
+
async def _set_is_consuming(self, value: bool) -> None:
|
|
121
|
+
"""安全更新消费状态并记录日志(带锁保护)"""
|
|
122
|
+
async with self._state_lock:
|
|
123
|
+
if self._is_consuming != value:
|
|
124
|
+
logger.info(f"消费状态变更: {self._is_consuming} → {value}")
|
|
125
|
+
self._is_consuming = value
|
|
126
|
+
|
|
123
127
|
async def _get_channel(self) -> AbstractChannel:
|
|
124
128
|
"""从通道池获取通道(使用上下文管理器)"""
|
|
125
129
|
if not self.connection_pool.channel_pool:
|
|
126
130
|
raise Exception("连接池未初始化,请先调用init_pools")
|
|
127
131
|
|
|
128
|
-
# 使用async with获取通道,并通过变量返回
|
|
129
132
|
async with self.connection_pool.channel_pool.acquire() as channel:
|
|
130
133
|
return channel
|
|
131
134
|
|
|
132
135
|
async def _check_exchange_exists(self, channel: AbstractChannel) -> bool:
|
|
133
136
|
"""检查交换机是否存在"""
|
|
134
137
|
try:
|
|
135
|
-
# 使用被动模式检查交换机
|
|
136
138
|
await asyncio.wait_for(
|
|
137
139
|
channel.declare_exchange(
|
|
138
140
|
name=self.exchange_name,
|
|
@@ -150,7 +152,6 @@ class RabbitMQClient:
|
|
|
150
152
|
if not self.queue_name:
|
|
151
153
|
return False
|
|
152
154
|
try:
|
|
153
|
-
# 使用被动模式检查队列
|
|
154
155
|
await asyncio.wait_for(
|
|
155
156
|
channel.declare_queue(
|
|
156
157
|
name=self.queue_name,
|
|
@@ -186,19 +187,15 @@ class RabbitMQClient:
|
|
|
186
187
|
return False
|
|
187
188
|
|
|
188
189
|
async def connect(self, force_reconnect: bool = False, declare_queue: bool = True) -> None:
|
|
189
|
-
"""
|
|
190
|
-
从连接池获取资源并初始化(交换机、队列)
|
|
191
|
-
"""
|
|
190
|
+
"""从连接池获取资源并初始化(交换机、队列)"""
|
|
192
191
|
logger.info(
|
|
193
192
|
f"连接参数 - force_reconnect={force_reconnect}, "
|
|
194
193
|
f"declare_queue={declare_queue}, create_if_not_exists={self.create_if_not_exists}"
|
|
195
194
|
)
|
|
196
195
|
|
|
197
|
-
# 如果已连接且不强制重连,则直接返回
|
|
198
196
|
if self.is_connected and not force_reconnect:
|
|
199
197
|
return
|
|
200
198
|
|
|
201
|
-
# 取消正在进行的重连任务
|
|
202
199
|
if self._reconnect_task and not self._reconnect_task.done():
|
|
203
200
|
self._reconnect_task.cancel()
|
|
204
201
|
|
|
@@ -206,13 +203,13 @@ class RabbitMQClient:
|
|
|
206
203
|
self._exchange_exists = False
|
|
207
204
|
self._queue_exists = False
|
|
208
205
|
self._queue_bound = False
|
|
206
|
+
await self._set_is_consuming(False)
|
|
209
207
|
|
|
210
208
|
retries = 0
|
|
211
209
|
last_exception = None
|
|
212
210
|
|
|
213
211
|
while retries < self.max_reconnection_attempts:
|
|
214
212
|
try:
|
|
215
|
-
# 从池获取通道
|
|
216
213
|
self.channel = await self._get_channel()
|
|
217
214
|
await self.channel.set_qos(prefetch_count=self.prefetch_count)
|
|
218
215
|
|
|
@@ -220,7 +217,6 @@ class RabbitMQClient:
|
|
|
220
217
|
exchange_exists = await self._check_exchange_exists(self.channel)
|
|
221
218
|
if not exchange_exists:
|
|
222
219
|
if self.create_if_not_exists:
|
|
223
|
-
# 创建交换机
|
|
224
220
|
self.exchange = await asyncio.wait_for(
|
|
225
221
|
self.channel.declare_exchange(
|
|
226
222
|
name=self.exchange_name,
|
|
@@ -235,7 +231,6 @@ class RabbitMQClient:
|
|
|
235
231
|
raise Exception(
|
|
236
232
|
f"交换机 '{self.exchange_name}' 不存在且不允许自动创建")
|
|
237
233
|
else:
|
|
238
|
-
# 获取已有交换机
|
|
239
234
|
self.exchange = await self.channel.get_exchange(self.exchange_name)
|
|
240
235
|
logger.info(f"使用已存在的交换机 '{self.exchange_name}'")
|
|
241
236
|
|
|
@@ -248,7 +243,6 @@ class RabbitMQClient:
|
|
|
248
243
|
raise Exception(
|
|
249
244
|
f"队列 '{self.queue_name}' 不存在且不允许自动创建")
|
|
250
245
|
|
|
251
|
-
# 创建队列
|
|
252
246
|
self.queue = await asyncio.wait_for(
|
|
253
247
|
self.channel.declare_queue(
|
|
254
248
|
name=self.queue_name,
|
|
@@ -261,7 +255,6 @@ class RabbitMQClient:
|
|
|
261
255
|
self.actual_queue_name = self.queue_name
|
|
262
256
|
logger.info(f"已创建队列 '{self.queue_name}'")
|
|
263
257
|
else:
|
|
264
|
-
# 获取已有队列
|
|
265
258
|
self.queue = await self.channel.get_queue(self.queue_name)
|
|
266
259
|
self.actual_queue_name = self.queue_name
|
|
267
260
|
logger.info(f"使用已存在的队列 '{self.queue_name}'")
|
|
@@ -272,31 +265,30 @@ class RabbitMQClient:
|
|
|
272
265
|
if not bound:
|
|
273
266
|
raise Exception(f"队列 '{self.queue_name}' 绑定到交换机失败")
|
|
274
267
|
else:
|
|
275
|
-
# 不声明队列时的状态处理
|
|
276
268
|
self.queue = None
|
|
277
269
|
self.actual_queue_name = None
|
|
278
270
|
logger.info(f"跳过队列 '{self.queue_name}' 的声明和绑定")
|
|
279
271
|
|
|
280
|
-
# 验证连接状态
|
|
281
272
|
if not self.is_connected:
|
|
282
273
|
raise Exception("连接验证失败,状态异常")
|
|
283
274
|
|
|
284
|
-
#
|
|
285
|
-
if self.
|
|
275
|
+
# 重新开始消费(如果之前在消费)
|
|
276
|
+
if self.message_handler:
|
|
286
277
|
await self.start_consuming()
|
|
287
278
|
|
|
288
|
-
#
|
|
279
|
+
# 启动监控和保活任务
|
|
289
280
|
self._start_monitoring()
|
|
290
281
|
self._start_keepalive()
|
|
291
282
|
|
|
292
283
|
self._update_activity_timestamp()
|
|
284
|
+
# 清理可能残留的跟踪记录
|
|
285
|
+
self._tracking_messages.clear()
|
|
293
286
|
logger.info(f"RabbitMQ客户端初始化成功 (队列: {self.actual_queue_name})")
|
|
294
287
|
return
|
|
295
288
|
|
|
296
289
|
except Exception as e:
|
|
297
290
|
last_exception = e
|
|
298
291
|
logger.warning(f"资源初始化失败: {str(e)},重试中...")
|
|
299
|
-
# 释放当前通道(放回池并重新获取)
|
|
300
292
|
self.channel = None
|
|
301
293
|
retries += 1
|
|
302
294
|
if retries < self.max_reconnection_attempts:
|
|
@@ -320,63 +312,75 @@ class RabbitMQClient:
|
|
|
320
312
|
await self._recreate_channel()
|
|
321
313
|
continue
|
|
322
314
|
|
|
323
|
-
|
|
315
|
+
current_time = asyncio.get_event_loop().time()
|
|
316
|
+
# 清理消息跟踪记录
|
|
324
317
|
if self._tracking_messages:
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
if msg_info.get('acked', False)
|
|
318
|
+
acked_ids = [
|
|
319
|
+
msg_id for msg_id, info in self._tracking_messages.items()
|
|
320
|
+
if info.get('acked', False)
|
|
329
321
|
]
|
|
330
|
-
|
|
331
|
-
for msg_id in acked_message_ids:
|
|
322
|
+
for msg_id in acked_ids:
|
|
332
323
|
del self._tracking_messages[msg_id]
|
|
333
|
-
if
|
|
334
|
-
logger.info(
|
|
335
|
-
f"清理了 {len(acked_message_ids)} 条已确认的消息跟踪记录")
|
|
324
|
+
if acked_ids:
|
|
325
|
+
logger.info(f"清理了 {len(acked_ids)} 条已确认消息记录")
|
|
336
326
|
|
|
337
|
-
#
|
|
327
|
+
# 检查消费停滞(仅当消费状态为 True 时才处理)
|
|
338
328
|
if self._is_consuming:
|
|
339
|
-
current_time = asyncio.get_event_loop().time()
|
|
340
329
|
if current_time - self._last_message_processed > self.consumption_stall_threshold:
|
|
341
330
|
if self._tracking_messages:
|
|
342
|
-
logger.
|
|
331
|
+
logger.warning(
|
|
343
332
|
f"消费停滞,但有 {len(self._tracking_messages)} 个消息正在处理,暂不重启")
|
|
344
333
|
else:
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
334
|
+
logger.info("消费停滞且无消息处理,重启消费")
|
|
335
|
+
# 重启消费时增加异常捕获,确保状态回滚
|
|
336
|
+
try:
|
|
337
|
+
await self.stop_consuming()
|
|
338
|
+
await asyncio.sleep(1)
|
|
339
|
+
# 重启前检查处理器是否存在
|
|
340
|
+
if self.message_handler:
|
|
341
|
+
await self.start_consuming()
|
|
342
|
+
else:
|
|
343
|
+
logger.error("消费处理器已丢失,无法重启消费")
|
|
344
|
+
except Exception as e:
|
|
345
|
+
logger.error(
|
|
346
|
+
f"重启消费失败: {str(e)}", exc_info=True)
|
|
347
|
+
# 回滚状态:标记为未消费,避免一直拒绝消息
|
|
348
|
+
await self._set_is_consuming(False)
|
|
349
349
|
except Exception as e:
|
|
350
|
-
logger.error(f"监控任务出错: {str(e)}")
|
|
351
|
-
await asyncio.sleep(1)
|
|
350
|
+
logger.error(f"监控任务出错: {str(e)}", exc_info=True)
|
|
352
351
|
|
|
353
352
|
await asyncio.sleep(60)
|
|
354
353
|
|
|
355
354
|
self._monitor_task = asyncio.create_task(monitor())
|
|
356
355
|
|
|
357
356
|
async def _recreate_channel(self) -> None:
|
|
357
|
+
# 重建前先标记为未消费
|
|
358
|
+
await self._set_is_consuming(False)
|
|
358
359
|
try:
|
|
359
|
-
# 无需手动释放,上下文管理器会自动处理
|
|
360
360
|
self.channel = await self._get_channel()
|
|
361
361
|
await self.channel.set_qos(prefetch_count=self.prefetch_count)
|
|
362
362
|
|
|
363
|
-
#
|
|
363
|
+
# 重新获取交换机和队列
|
|
364
364
|
self.exchange = await self.channel.get_exchange(self.exchange_name)
|
|
365
|
-
|
|
366
|
-
# 重新绑定队列
|
|
367
365
|
if self.queue_name:
|
|
368
366
|
self.queue = await self.channel.get_queue(self.queue_name)
|
|
369
367
|
if self.queue and self.exchange:
|
|
370
|
-
await self._bind_queue(self.channel, self.queue, self.exchange)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
368
|
+
bound = await self._bind_queue(self.channel, self.queue, self.exchange)
|
|
369
|
+
if not bound:
|
|
370
|
+
raise Exception("队列绑定失败,通道重建不完整")
|
|
371
|
+
|
|
372
|
+
# 重新开始消费(确保状态正确恢复)
|
|
373
|
+
async with self._state_lock:
|
|
374
|
+
has_handler = self.message_handler is not None
|
|
375
|
+
if has_handler:
|
|
374
376
|
await self.start_consuming()
|
|
375
377
|
|
|
376
378
|
logger.info("通道已重建并恢复服务")
|
|
377
379
|
self._update_activity_timestamp()
|
|
378
380
|
except Exception as e:
|
|
379
|
-
logger.error(f"通道重建失败: {str(e)},触发重连")
|
|
381
|
+
logger.error(f"通道重建失败: {str(e)},触发重连", exc_info=True)
|
|
382
|
+
# 重建失败时,确保消费状态为 False
|
|
383
|
+
await self._set_is_consuming(False)
|
|
380
384
|
await self.connect(force_reconnect=True)
|
|
381
385
|
|
|
382
386
|
def _start_keepalive(self) -> None:
|
|
@@ -387,10 +391,9 @@ class RabbitMQClient:
|
|
|
387
391
|
async def keepalive():
|
|
388
392
|
while not self._closed and self.is_connected:
|
|
389
393
|
current_time = asyncio.get_event_loop().time()
|
|
390
|
-
|
|
391
|
-
if current_time - self._last_activity_timestamp > self.connection_pool.heartbeat * 1.5:
|
|
394
|
+
if current_time - self._last_activity_timestamp > self.connection_pool.heartbeat * 2:
|
|
392
395
|
logger.info(
|
|
393
|
-
f"连接 {self.connection_pool.heartbeat*
|
|
396
|
+
f"连接 {self.connection_pool.heartbeat*2}s 无活动,执行保活检查")
|
|
394
397
|
try:
|
|
395
398
|
if self.channel.is_closed:
|
|
396
399
|
logger.warning("连接已关闭,触发重连")
|
|
@@ -411,7 +414,7 @@ class RabbitMQClient:
|
|
|
411
414
|
logger.warning(f"保活检查失败: {str(e)},触发重连")
|
|
412
415
|
await self.connect(force_reconnect=True)
|
|
413
416
|
|
|
414
|
-
await asyncio.sleep(self.connection_pool.heartbeat
|
|
417
|
+
await asyncio.sleep(self.connection_pool.heartbeat)
|
|
415
418
|
|
|
416
419
|
self._keepalive_task = asyncio.create_task(keepalive())
|
|
417
420
|
|
|
@@ -437,7 +440,7 @@ class RabbitMQClient:
|
|
|
437
440
|
async def close(self) -> None:
|
|
438
441
|
"""关闭客户端并释放资源"""
|
|
439
442
|
self._closed = True
|
|
440
|
-
self.
|
|
443
|
+
await self._set_is_consuming(False)
|
|
441
444
|
|
|
442
445
|
# 取消所有任务
|
|
443
446
|
for task in [self._keepalive_task, self._reconnect_task,
|
|
@@ -495,14 +498,13 @@ class RabbitMQClient:
|
|
|
495
498
|
max_retries = 2
|
|
496
499
|
while retry_count < max_retries:
|
|
497
500
|
try:
|
|
498
|
-
# 从池获取新通道用于发布(避免长时间占用消费通道)
|
|
499
501
|
async with self.connection_pool.channel_pool.acquire() as publish_channel:
|
|
500
502
|
exchange = await publish_channel.get_exchange(self.exchange_name)
|
|
501
503
|
confirmed = await exchange.publish(
|
|
502
504
|
message,
|
|
503
505
|
routing_key=routing_key or self.routing_key or '#',
|
|
504
506
|
mandatory=True,
|
|
505
|
-
timeout=5
|
|
507
|
+
timeout=5
|
|
506
508
|
)
|
|
507
509
|
if not confirmed:
|
|
508
510
|
raise Exception("消息未被服务器确认接收")
|
|
@@ -510,9 +512,11 @@ class RabbitMQClient:
|
|
|
510
512
|
self._update_activity_timestamp()
|
|
511
513
|
logger.info(f"消息已发布到交换机 '{self.exchange_name}'")
|
|
512
514
|
return
|
|
513
|
-
except (ConnectionClosed, ChannelInvalidStateError):
|
|
515
|
+
except (ConnectionClosed, ChannelInvalidStateError, asyncio.TimeoutError):
|
|
516
|
+
# 覆盖更多异常类型
|
|
514
517
|
retry_count += 1
|
|
515
|
-
logger.warning(f"
|
|
518
|
+
logger.warning(f"连接异常,尝试重连后重新发布 (重试次数: {retry_count})")
|
|
519
|
+
# 主动刷新连接状态
|
|
516
520
|
await self.connect(force_reconnect=True)
|
|
517
521
|
except Exception as e:
|
|
518
522
|
retry_count += 1
|
|
@@ -522,18 +526,18 @@ class RabbitMQClient:
|
|
|
522
526
|
|
|
523
527
|
raise Exception(f"消息发布失败,经过{retry_count}次重试仍未成功")
|
|
524
528
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
529
|
+
async def set_message_handler(self, handler):
|
|
530
|
+
async with self._state_lock:
|
|
531
|
+
self.message_handler = handler
|
|
528
532
|
|
|
529
533
|
async def start_consuming(self) -> ConsumerTag:
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
534
|
+
async with self._state_lock:
|
|
535
|
+
if self._is_consuming:
|
|
536
|
+
logger.info("已经在消费中,返回现有consumer_tag")
|
|
537
|
+
if self._consumer_tag:
|
|
538
|
+
return self._consumer_tag
|
|
539
|
+
logger.warning("检测到消费状态异常(无consumer_tag),重置状态后重试")
|
|
540
|
+
self._is_consuming = False
|
|
537
541
|
|
|
538
542
|
if not self.is_connected:
|
|
539
543
|
await self.connect()
|
|
@@ -541,28 +545,26 @@ class RabbitMQClient:
|
|
|
541
545
|
if not self.queue:
|
|
542
546
|
raise Exception("队列未初始化,无法开始消费")
|
|
543
547
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
self._is_consuming = True
|
|
548
|
-
logger.info(f"开始消费队列: {self.actual_queue_name}")
|
|
548
|
+
async with self._state_lock:
|
|
549
|
+
if not self.message_handler:
|
|
550
|
+
raise Exception("未设置消息处理函数")
|
|
549
551
|
|
|
550
552
|
try:
|
|
551
|
-
# 调用队列的consume方法,确保获取到consumer_tag
|
|
552
553
|
self._consumer_tag = await self.queue.consume(
|
|
553
554
|
self._message_wrapper,
|
|
554
555
|
no_ack=False # 手动确认消息
|
|
555
556
|
)
|
|
556
557
|
|
|
557
|
-
# 确保consumer_tag有效
|
|
558
558
|
if not self._consumer_tag:
|
|
559
559
|
raise Exception("未能获取到有效的consumer_tag")
|
|
560
560
|
|
|
561
|
+
await self._set_is_consuming(True)
|
|
561
562
|
logger.info(
|
|
562
563
|
f"消费者已启动,队列: {self.actual_queue_name}, tag: {self._consumer_tag}")
|
|
563
564
|
return self._consumer_tag
|
|
564
565
|
except Exception as e:
|
|
565
|
-
|
|
566
|
+
# 异常时强制设置为未消费
|
|
567
|
+
await self._set_is_consuming(False)
|
|
566
568
|
logger.error(f"启动消费失败: {str(e)}", exc_info=True)
|
|
567
569
|
raise
|
|
568
570
|
|
|
@@ -585,22 +587,25 @@ class RabbitMQClient:
|
|
|
585
587
|
if not self._is_consuming:
|
|
586
588
|
return
|
|
587
589
|
|
|
588
|
-
self.
|
|
590
|
+
await self._set_is_consuming(False)
|
|
589
591
|
|
|
590
592
|
if self._consumer_tag and self.queue:
|
|
591
593
|
await self._safe_cancel_consumer()
|
|
592
594
|
|
|
593
595
|
# 等待所有正在处理的消息完成
|
|
594
596
|
if self._tracking_messages:
|
|
595
|
-
logger.info(
|
|
596
|
-
|
|
597
|
+
logger.info(f"等待 {len(self._tracking_messages)} 个正在处理的消息完成...")
|
|
598
|
+
wait_start = asyncio.get_event_loop().time()
|
|
597
599
|
while self._tracking_messages and not self._closed:
|
|
600
|
+
if asyncio.get_event_loop().time() - wait_start > 30: # 最多等30秒
|
|
601
|
+
logger.warning("等待消息处理超时,强制清理跟踪记录")
|
|
602
|
+
self._tracking_messages.clear()
|
|
603
|
+
break
|
|
598
604
|
await asyncio.sleep(1)
|
|
599
605
|
|
|
600
606
|
# 清理状态
|
|
601
607
|
self._consumer_tag = None
|
|
602
608
|
self._tracking_messages.clear()
|
|
603
|
-
|
|
604
609
|
logger.info(f"已停止消费队列: {self.actual_queue_name}")
|
|
605
610
|
|
|
606
611
|
async def _parse_message(self, message: AbstractIncomingMessage) -> Union[Dict[str, Any], str]:
|
|
@@ -619,11 +624,19 @@ class RabbitMQClient:
|
|
|
619
624
|
return message.body.decode('utf-8')
|
|
620
625
|
|
|
621
626
|
async def _message_wrapper(self, message: AbstractIncomingMessage) -> None:
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
627
|
+
# 先通过锁获取当前状态,避免并发修改导致的判断错误
|
|
628
|
+
async with self._state_lock:
|
|
629
|
+
has_handler = self.message_handler is not None
|
|
630
|
+
is_consuming = self._is_consuming
|
|
631
|
+
|
|
632
|
+
if not has_handler or not is_consuming:
|
|
633
|
+
logger.warning(
|
|
634
|
+
f"拒绝消息: message_handler={'存在' if has_handler else '不存在'}, "
|
|
635
|
+
f"is_consuming={is_consuming},消息ID: {message.message_id or str(id(message))}"
|
|
636
|
+
)
|
|
625
637
|
try:
|
|
626
638
|
await message.reject(requeue=True)
|
|
639
|
+
await asyncio.sleep(3)
|
|
627
640
|
except Exception as e:
|
|
628
641
|
logger.error(f"拒绝消息失败: {e}")
|
|
629
642
|
return
|
|
@@ -634,21 +647,23 @@ class RabbitMQClient:
|
|
|
634
647
|
await message.ack()
|
|
635
648
|
return
|
|
636
649
|
|
|
637
|
-
|
|
650
|
+
start_time = asyncio.get_event_loop().time()
|
|
638
651
|
self._tracking_messages[message_id] = {
|
|
639
652
|
'delivery_tag': message.delivery_tag,
|
|
640
653
|
'acked': False,
|
|
641
|
-
'channel_number': self.channel.number if self.channel else None
|
|
654
|
+
'channel_number': self.channel.number if self.channel else None,
|
|
655
|
+
'start_time': start_time
|
|
642
656
|
}
|
|
643
657
|
|
|
644
658
|
try:
|
|
645
659
|
logger.info(f"收到队列 {self.actual_queue_name} 的消息: {message_id}")
|
|
660
|
+
print(f"收到队列 {self.actual_queue_name} 的消息: {message_id}")
|
|
646
661
|
|
|
647
662
|
parsed_data = await self._parse_message(message)
|
|
648
663
|
await self.message_handler(MQMsgModel(** parsed_data), message)
|
|
649
664
|
|
|
650
665
|
await message.ack()
|
|
651
|
-
self._tracking_messages[message_id]['acked'] = True
|
|
666
|
+
self._tracking_messages[message_id]['acked'] = True
|
|
652
667
|
self._update_activity_timestamp()
|
|
653
668
|
self._update_message_processed_timestamp()
|
|
654
669
|
logger.info(f"消息 {message_id} 处理完成并确认")
|
|
@@ -665,9 +680,9 @@ class RabbitMQClient:
|
|
|
665
680
|
|
|
666
681
|
if retry_count >= MAX_RETRY_COUNT:
|
|
667
682
|
logger.error(
|
|
668
|
-
f"消息 {message_id} 已达到最大重试次数
|
|
683
|
+
f"消息 {message_id} 已达到最大重试次数{MAX_RETRY_COUNT},标记为失败")
|
|
669
684
|
await message.ack()
|
|
670
|
-
self._tracking_messages[message_id]['acked'] = True
|
|
685
|
+
self._tracking_messages[message_id]['acked'] = True
|
|
671
686
|
self._update_activity_timestamp()
|
|
672
687
|
return
|
|
673
688
|
|
|
@@ -682,7 +697,7 @@ class RabbitMQClient:
|
|
|
682
697
|
)
|
|
683
698
|
|
|
684
699
|
await message.reject(requeue=False)
|
|
685
|
-
self._tracking_messages[message_id]['acked'] = True
|
|
700
|
+
self._tracking_messages[message_id]['acked'] = True
|
|
686
701
|
|
|
687
702
|
if self.exchange:
|
|
688
703
|
await self.exchange.publish(
|
|
@@ -696,6 +711,7 @@ class RabbitMQClient:
|
|
|
696
711
|
finally:
|
|
697
712
|
if message_id in self._tracking_messages:
|
|
698
713
|
del self._tracking_messages[message_id]
|
|
714
|
+
logger.info(f"已删除消息跟踪信息: {message_id}")
|
|
699
715
|
|
|
700
716
|
async def __aenter__(self):
|
|
701
717
|
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:
|
|
@@ -443,7 +443,7 @@ class RabbitMQService:
|
|
|
443
443
|
handler = cls.default_message_handler
|
|
444
444
|
|
|
445
445
|
# 设置消息处理器
|
|
446
|
-
client.set_message_handler(handler)
|
|
446
|
+
await client.set_message_handler(handler)
|
|
447
447
|
|
|
448
448
|
# 确保客户端已连接
|
|
449
449
|
start_time = asyncio.get_event_loop().time()
|
sycommon/services.py
CHANGED
|
@@ -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
|
command/cli.py,sha256=bP2LCLkRvfETIwWkVD70q5xFxMI4D3BpH09Ws1f-ENc,5849
|
|
2
2
|
sycommon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
sycommon/services.py,sha256=
|
|
3
|
+
sycommon/services.py,sha256=cPLqMtTHMhCrvdrYJWyVAMrl4G8Wc9w4vFkgYcTz7LQ,9463
|
|
4
4
|
sycommon/config/Config.py,sha256=9yO5b8WfvEDvkyrGrlwrLFasgh_-MjcEvGF20Gz5Xo4,3041
|
|
5
5
|
sycommon/config/DatabaseConfig.py,sha256=ILiUuYT9_xJZE2W-RYuC3JCt_YLKc1sbH13-MHIOPhg,804
|
|
6
6
|
sycommon/config/EmbeddingConfig.py,sha256=gPKwiDYbeu1GpdIZXMmgqM7JqBIzCXi0yYuGRLZooMI,362
|
|
@@ -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=n3c1W31S1NAOkQO2UDpQYgE7Ex8N2hyZrqwPpyxEijU,29733
|
|
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=5BrqF_3PwEMbqs8AVhSqFpqzo3GrIftafMX_tCmFv8E,30199
|
|
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.34.dist-info/METADATA,sha256=8m47X4r_A5oq9e1CjQaBkt5gdRTblwW7qyln8kQzC0c,7037
|
|
56
|
+
sycommon_python_lib-0.1.34.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
57
|
+
sycommon_python_lib-0.1.34.dist-info/entry_points.txt,sha256=q_h2nbvhhmdnsOUZEIwpuoDjaNfBF9XqppDEmQn9d_A,46
|
|
58
|
+
sycommon_python_lib-0.1.34.dist-info/top_level.txt,sha256=98CJ-cyM2WIKxLz-Pf0AitWLhJyrfXvyY8slwjTXNuc,17
|
|
59
|
+
sycommon_python_lib-0.1.34.dist-info/RECORD,,
|
|
File without changes
|
{sycommon_python_lib-0.1.32.dist-info → sycommon_python_lib-0.1.34.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|