using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
namespace Serein.Proto.WebSocket.Handle
{
///
/// Json消息处理模块
///
public class WebSocketHandleModule
{
///
/// Json消息处理模块
///
public WebSocketHandleModule(WebSocketModuleConfig config)
{
_moduleConfig = config;
_methodInvokeConfigs = new ConcurrentDictionary();
_myMsgIdHash = new HashSet();
}
///
/// 模块的处理配置
///
private readonly WebSocketModuleConfig _moduleConfig;
///
/// 用来判断消息是否重复
///
private readonly HashSet _myMsgIdHash;
///
/// 存储处理数据的配置
///
private readonly ConcurrentDictionary _methodInvokeConfigs ;
///
/// 添加处理配置
///
/// 处理模块
internal bool AddHandleConfigs(WebSocketMethodConfig config)
{
if (!_methodInvokeConfigs.ContainsKey(config.ThemeValue))
{
_methodInvokeConfigs[config.ThemeValue] = config;
return true;
}
else
{
return false;
}
}
///
/// 移除某个处理模块
///
///
///
public bool RemoveConfig(ISocketHandleModule socketControlBase)
{
foreach (var kv in _methodInvokeConfigs.ToArray())
{
var config = kv.Value;
_methodInvokeConfigs.TryRemove(kv.Key, out _);
}
return _methodInvokeConfigs.Count == 0;
}
///
/// 卸载当前模块的所有配置
///
public void UnloadConfig()
{
var temp = _methodInvokeConfigs.Values;
_methodInvokeConfigs.Clear();
}
///
/// 处理JSON数据
///
public async Task HandleAsync(WebSocketHandleContext context)
{
var jsonObject = context.MsgRequest; // 获取到消息
if (jsonObject is null)
{
context.TriggerExceptionTracking($"请求没有获取到消息");
return; // 没有获取到消息
}
if(!jsonObject.TryGetValue(_moduleConfig.ThemeJsonKey, out var themeToken) || themeToken.IsNull)
{
context.TriggerExceptionTracking($"请求没有获取到主题\"{_moduleConfig.ThemeJsonKey}\"");
return; // 没有获取到消息
}
if(themeToken.Type != IJsonToken.TokenType.Value)
{
context.TriggerExceptionTracking($"请求主题需要值类型 \"{_moduleConfig.ThemeJsonKey}\"");
return; // 没有获取到消息
}
var theme = themeToken.ToString(); // 获取主题
// 验证主题
if (!_methodInvokeConfigs.TryGetValue(theme, out var handldConfig))
{
context.TriggerExceptionTracking($"{_moduleConfig.ThemeJsonKey} 主题不存在");
return;
}
if (!jsonObject.TryGetValue(_moduleConfig.MsgIdJsonKey, out var msgIdToken) || themeToken.IsNull)
{
context.TriggerExceptionTracking($"主题 {theme} 没有消息Id");
return; // 没有获取到消息
}
if (themeToken.Type != IJsonToken.TokenType.Value)
{
context.TriggerExceptionTracking($"请求消息Id需要值类型 \"{_moduleConfig.ThemeJsonKey}\"");
return; // 没有获取到消息
}
var msgId = msgIdToken.ToString(); // 获取主题
// 验证消息ID是否重复
if (!_myMsgIdHash.Add(msgId))
{
context.TriggerExceptionTracking($"主题 {theme} 消息Id {msgId} 消息重复");
return; // 消息重复
}
// 验证数据
if (!jsonObject.TryGetValue(_moduleConfig.DataJsonKey, out var dataToken))
{
context.TriggerExceptionTracking($"主题 {theme} 消息Id {msgId} 数据提取失败,当前指定键\"{_moduleConfig.DataJsonKey}\"");
return; // 没有主题
}
if(dataToken.Type != IJsonToken.TokenType.Object)
{
context.TriggerExceptionTracking($"主题 {theme} 消息Id {msgId} 数据需要 JSON Object");
}
context.MsgTheme = theme; // 添加主题
context.MsgId = msgId; // 添加 ID
context.MsgData = dataToken; // 添加消息
context.MsgRequest = jsonObject; // 添加原始消息
try
{
if (TryGetParameters(handldConfig, context, out var args))
{
var result = await HandleAsync(handldConfig, args);
if (handldConfig.IsReturnValue)
{
await RepliedAsync(_moduleConfig, context, result);
}
}
else
{
context.TriggerExceptionTracking($"主题 {theme} 消息Id {msgId} 参数获取失败");
}
}
catch (Exception ex)
{
context.TriggerExceptionTracking(ex);
}
finally
{
context.Handle = true;
}
}
///
/// 调用
///
///
///
///
public static async Task