Files
QYZH.InteractiveMagazine/QYZH.InteractiveMagazine.Infrastructure/RabbitMQ/RabbitMQService.cs
glz e493c85d08 refactor,feat: 批量代码重构与新增业务模块
1. 重命名枚举项与实体字段,修正类型引用
2. 新增IsNull扩展方法与多项字符串处理扩展
3. 新增大量业务DTO、服务接口与枚举定义
4. 重构RabbitMQ服务实现,替换旧版消息队列组件
5. 优化签到服务的宠物喂养事务逻辑
6. 移除冗余的项目引用与旧版消息队列代码
7. 新增Excel导出、导入模板相关工具方法
2026-06-11 17:01:24 +08:00

158 lines
6.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
namespace QYZH.InteractiveMagazine.Infrastructure.RabbitMQ
{
public class RabbitMQService : IRabbitMQService
{
private readonly IRabbitMQConnection _connection;
private readonly JsonSerializerOptions options = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
public RabbitMQService(IRabbitMQConnection connection)
{
_connection = connection ?? throw new ArgumentNullException(nameof(connection));
}
public async Task<bool> SendAsync(RabbitMQSendParam param, CancellationToken cancellationToken = default)
{
try
{
using var channel = await _connection.CreateChannel();
// 启用发布者确认
//var channelOpts = new CreateChannelOptions
//(
// publisherConfirmationsEnabled: true,
// publisherConfirmationTrackingEnabled: true,
// outstandingPublisherConfirmationsRateLimiter: new ThrottlingRateLimiter(MAX_OUTSTANDING_CONFIRMS)
//);
// 声明队列(持久化)
await channel.QueueDeclareAsync(queue: param.RoutingKey, durable: true, exclusive: false, autoDelete: false, arguments: null);
// 清空队列
if (param.Purge) await channel.QueuePurgeAsync(param.RoutingKey);
// 消息序列化
var mesjson = JsonSerializer.Serialize(param.Data, options);
var body = Encoding.UTF8.GetBytes(mesjson);
var properties = new BasicProperties
{
Persistent = true // 设置消息持久化
};
await channel.BasicPublishAsync(param.Exchange, param.RoutingKey, false, properties, body, cancellationToken);
return true;
}
catch (OperationCanceledException ex)
{
Console.WriteLine($"Operation was canceled: {ex.Message}");
return false;
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
return false;
}
}
public async Task<bool> SendBatchAsync(IEnumerable<RabbitMQSendParam> @params, CancellationToken cancellationToken = default)
{
IChannel channel = null;
try
{
channel = await _connection.CreateChannel();
// 开启事务
await channel.TxSelectAsync();
var properties = new BasicProperties
{
Persistent = true // 设置消息持久化
};
// 批量发送消息到不同的 routingKey
var declaredExchanges = new HashSet<string>();
foreach (var param in @params)
{
// 声明 Exchange持久化
if (declaredExchanges.Add(param.Exchange))
{
await channel.ExchangeDeclareAsync(exchange: param.Exchange, type: "direct", durable: true, autoDelete: false, arguments: null);
}
// 声明队列(持久化)
await channel.QueueDeclareAsync(queue: param.Queue, durable: true, exclusive: false, autoDelete: false, arguments: null);
// 绑定队列到 Exchange
await channel.QueueBindAsync(queue: param.Queue, exchange: param.Exchange, routingKey: param.RoutingKey, arguments: null);
// 清空队列
if (param.Purge) await channel.QueuePurgeAsync(param.Queue);
// 消息序列化
var mesjson = JsonSerializer.Serialize(param.Data, options);
var body = Encoding.UTF8.GetBytes(mesjson);
// 发布消息
await channel.BasicPublishAsync(param.Exchange, param.RoutingKey, false, properties, body, cancellationToken);
}
// 提交事务 - 确保所有消息都发送成功
await channel.TxCommitAsync();
return true;
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
// 回滚事务
try { await channel?.TxRollbackAsync(); } catch { /* 忽略回滚异常 */ }
return false;
}
finally
{
if (channel != null && !channel.IsClosed)
{
await channel.CloseAsync();
}
}
}
public async Task ReceiveAsync(string queueName, Func<IChannel, BasicDeliverEventArgs, Task> callback, CancellationToken cancellationToken = default)
{
var channel = await _connection.CreateChannel();
//await channel.BasicQosAsync(0, 10, false); // 一次最多接收10条未确认的消息
await channel.QueueDeclareAsync(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
var consumer = new AsyncEventingBasicConsumer(channel);
consumer.ReceivedAsync += async (model, ea) =>
{
//var body = ea.Body.ToArray();
try
{
// 直接传递 model 和 body 给 callback不需要转换
await callback(channel, ea);
}
finally
{
//await channel.BasicAckAsync(ea.DeliveryTag, false, cancellationToken);
}
};
await channel.BasicConsumeAsync(queue: queueName, autoAck: false, consumer: consumer, cancellationToken: cancellationToken);
// Prevent the method from returning immediately
await Task.Delay(-1, cancellationToken);
}
}
}