You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
9.1 KiB

using CoreAgent.WebSocketTransport.Interfaces;
using CoreAgent.WebSocketTransport.Models;
using Microsoft.Extensions.Logging;
namespace CoreAgent.WebSocketTransport.Services;
/// <summary>
/// 消息通道管理器实现
/// 单一职责:管理所有消息通道
/// </summary>
public class MessageChannelManager : IMessageChannelManager
{
private readonly ILogger<MessageChannelManager> _logger;
private volatile bool _disposed;
private readonly object _disposeLock = new object();
private IMessageChannel<ProtocolMessage> _sendChannel;
private IMessageChannel<object> _receiveChannel;
private IMessageChannel<HeartbeatMessage> _priorityChannel;
public IMessageChannel<ProtocolMessage> SendChannel => _sendChannel;
public IMessageChannel<object> ReceiveChannel => _receiveChannel;
public IMessageChannel<HeartbeatMessage> PriorityChannel => _priorityChannel;
private readonly int _sendChannelCapacity;
private readonly int _receiveChannelCapacity;
private readonly int _priorityChannelCapacity;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="logger">日志记录器</param>
/// <param name="sendChannelCapacity">发送通道容量</param>
/// <param name="receiveChannelCapacity">接收通道容量</param>
/// <param name="priorityChannelCapacity">优先级通道容量</param>
public MessageChannelManager(
ILogger<MessageChannelManager> logger,
int sendChannelCapacity,
int receiveChannelCapacity,
int priorityChannelCapacity)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
// 验证容量参数
if (sendChannelCapacity <= 0)
throw new ArgumentOutOfRangeException(nameof(sendChannelCapacity), "发送通道容量必须大于0");
if (receiveChannelCapacity <= 0)
throw new ArgumentOutOfRangeException(nameof(receiveChannelCapacity), "接收通道容量必须大于0");
if (priorityChannelCapacity <= 0)
throw new ArgumentOutOfRangeException(nameof(priorityChannelCapacity), "优先级通道容量必须大于0");
_sendChannelCapacity = sendChannelCapacity;
_receiveChannelCapacity = receiveChannelCapacity;
_priorityChannelCapacity = priorityChannelCapacity;
_logger.LogInformation("消息通道管理器已创建 - 发送通道容量: {SendCapacity}, 接收通道容量: {ReceiveCapacity}, 优先级通道容量: {PriorityCapacity}",
sendChannelCapacity, receiveChannelCapacity, priorityChannelCapacity);
}
/// <summary>
/// 创建所有通道
/// </summary>
public void CreateChannels()
{
ThrowIfDisposed();
try
{
// 检查通道是否已存在,如果存在则先释放
if (_sendChannel != null || _receiveChannel != null || _priorityChannel != null)
{
_logger.LogWarning("通道已存在,先释放现有通道");
ReleaseChannels();
}
_sendChannel = new ChannelMessageChannel<ProtocolMessage>(_sendChannelCapacity);
_receiveChannel = new ChannelMessageChannel<object>(_receiveChannelCapacity);
_priorityChannel = new ChannelMessageChannel<HeartbeatMessage>(_priorityChannelCapacity);
_logger.LogInformation("所有通道已创建 - 发送通道容量: {SendCapacity}, 接收通道容量: {ReceiveCapacity}, 优先级通道容量: {PriorityCapacity}",
_sendChannelCapacity, _receiveChannelCapacity, _priorityChannelCapacity);
}
catch (Exception ex)
{
_logger.LogError(ex, "创建通道失败");
throw;
}
}
/// <summary>
/// 释放所有通道(完全释放资源)
/// </summary>
public void ReleaseChannels()
{
try
{
_logger.LogDebug("开始释放所有通道资源");
// 检查是否有通道需要释放
if (_sendChannel == null && _receiveChannel == null && _priorityChannel == null)
{
_logger.LogDebug("没有通道需要释放");
return;
}
// 先完成所有通道(标记不再接受新消息)
if (_sendChannel != null && !_sendChannel.IsCompleted)
_sendChannel.Complete();
if (_receiveChannel != null && !_receiveChannel.IsCompleted)
_receiveChannel.Complete();
if (_priorityChannel != null && !_priorityChannel.IsCompleted)
_priorityChannel.Complete();
// 然后释放通道资源
_sendChannel?.Dispose();
_receiveChannel?.Dispose();
_priorityChannel?.Dispose();
// 清空引用
_sendChannel = null;
_receiveChannel = null;
_priorityChannel = null;
_logger.LogInformation("所有通道资源已完全释放");
}
catch (Exception ex)
{
_logger.LogError(ex, "释放通道资源失败");
throw;
}
}
/// <summary>
/// 获取通道状态信息
/// </summary>
public ChannelStatusInfo GetStatusInfo()
{
ThrowIfDisposed();
try
{
return new ChannelStatusInfo
{
SendChannelCount = SendChannel.Count,
ReceiveChannelCount = ReceiveChannel.Count,
PriorityChannelCount = PriorityChannel.Count,
SendChannelCapacity = SendChannel.Capacity,
ReceiveChannelCapacity = ReceiveChannel.Capacity,
PriorityChannelCapacity = PriorityChannel.Capacity,
SendChannelCompleted = SendChannel.IsCompleted,
ReceiveChannelCompleted = ReceiveChannel.IsCompleted,
PriorityChannelCompleted = PriorityChannel.IsCompleted
};
}
catch (Exception ex)
{
_logger.LogError(ex, "获取通道状态信息失败");
throw;
}
}
/// <summary>
/// 清空所有通道中的消息(保持通道可用)
/// </summary>
public void ClearAllChannels()
{
ThrowIfDisposed();
try
{
// 检查通道是否存在
if (_sendChannel == null && _receiveChannel == null && _priorityChannel == null)
{
_logger.LogWarning("通道不存在,跳过清空操作");
return;
}
// 清空各个通道中的消息
if (_sendChannel != null)
_sendChannel.Clear();
if (_receiveChannel != null)
_receiveChannel.Clear();
if (_priorityChannel != null)
_priorityChannel.Clear();
_logger.LogInformation("所有通道中的消息已清空");
}
catch (Exception ex)
{
_logger.LogError(ex, "清空通道消息失败");
throw;
}
}
/// <summary>
/// 完成所有通道(标记不再接受新消息,但保持可读)
/// </summary>
public void CompleteAllChannels()
{
ThrowIfDisposed();
try
{
// 检查通道是否存在
if (_sendChannel == null && _receiveChannel == null && _priorityChannel == null)
{
_logger.LogWarning("通道不存在,跳过完成操作");
return;
}
// 完成各个通道(标记不再接受新消息)
if (_sendChannel != null && !_sendChannel.IsCompleted)
_sendChannel.Complete();
if (_receiveChannel != null && !_receiveChannel.IsCompleted)
_receiveChannel.Complete();
if (_priorityChannel != null && !_priorityChannel.IsCompleted)
_priorityChannel.Complete();
_logger.LogInformation("所有通道已完成(不再接受新消息)");
}
catch (Exception ex)
{
_logger.LogError(ex, "完成通道失败");
throw;
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
lock (_disposeLock)
{
if (!_disposed)
{
_disposed = true;
try
{
// 释放所有通道
ReleaseChannels();
_logger.LogInformation("消息通道管理器已释放");
}
catch (Exception ex)
{
_logger.LogError(ex, "释放消息通道管理器时发生异常");
}
GC.SuppressFinalize(this);
}
}
}
/// <summary>
/// 检查是否已释放
/// </summary>
private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(MessageChannelManager));
}
}
}