Files
simapi-net/Synapse/RpcServer.cs
T

120 lines
5.1 KiB
C#
Raw Normal View History

2023-10-20 12:33:18 +08:00
using System;
using System.Linq;
2023-10-20 15:29:32 +08:00
using System.Reflection;
2024-07-26 05:03:28 +08:00
using System.Threading;
using System.Threading.Tasks;
2023-10-20 12:33:18 +08:00
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
2024-07-26 05:03:28 +08:00
using MQTTnet;
using MQTTnet.Protocol;
2023-10-20 12:33:18 +08:00
using SimApi.Communications;
using SimApi.Exceptions;
2023-10-20 14:13:53 +08:00
using SimApi.Helpers;
2023-10-20 12:33:18 +08:00
using JsonSerializer = System.Text.Json.JsonSerializer;
namespace SimApi;
public partial class Synapse
{
2024-08-03 19:19:42 +08:00
private string RpcServerTopicPrefix => $"{Options.SysName}/{Options.AppName}/rpc/server/";
2023-10-20 12:33:18 +08:00
private void RunRpcServer()
{
2024-07-26 08:11:21 +08:00
Client!.ApplicationMessageReceivedAsync += e =>
2023-10-20 12:33:18 +08:00
{
2024-08-03 19:19:42 +08:00
if (!e.ApplicationMessage.Topic.StartsWith(RpcServerTopicPrefix)) return Task.CompletedTask;
2024-07-26 05:03:28 +08:00
var reqBody = e.ApplicationMessage.ConvertPayloadToString();
2024-08-03 19:19:42 +08:00
var action = e.ApplicationMessage.Topic.Replace(RpcServerTopicPrefix, string.Empty);
2024-07-26 05:03:28 +08:00
var appInfo = e.ApplicationMessage.ResponseTopic.Split(",");
logger.LogDebug(
"Synapse RPC Server Receive: ({BasicPropertiesMessageId}) {BasicPropertiesReplyTo} -> {BasicPropertiesType}@{OptionsAppName}\n{S}",
2024-09-05 12:59:57 +08:00
appInfo[2], appInfo[0], action, Options.AppName, reqBody);
2024-07-26 08:11:21 +08:00
SimApiBaseResponse res;
2024-07-26 05:03:28 +08:00
var method = RpcRegistry.FirstOrDefault(x => x.Key == action);
if (method == null)
2023-10-20 12:33:18 +08:00
{
res = new SimApiBaseResponse(404, "method not found");
2024-07-26 05:03:28 +08:00
}
else
2024-07-26 05:03:28 +08:00
{
var callClass = sp.CreateScope().ServiceProvider.GetRequiredService(method.Class!);
var mt = callClass.GetType().GetMethod(method.Method!);
try
2024-07-26 05:03:28 +08:00
{
var methodParams = mt!.GetParameters();
object? ret;
2024-09-05 12:59:57 +08:00
switch (methodParams.Length)
{
2024-09-05 12:59:57 +08:00
case 1:
var pt = mt.GetParameters()[0].ParameterType;
var param = pt == typeof(string)
? [reqBody]
: new[] { JsonSerializer.Deserialize(reqBody, pt, SimApiUtil.JsonOption) };
ret = mt.Invoke(callClass, param);
break;
case 2:
var headerData =
e.ApplicationMessage.UserProperties.ToDictionary(x => x.Name, x => x.Value);
var pt2 = mt.GetParameters()[0].ParameterType;
var param2 = pt2 == typeof(string)
? [reqBody]
: new[] { JsonSerializer.Deserialize(reqBody, pt2, SimApiUtil.JsonOption), headerData };
ret = mt.Invoke(callClass, param2);
break;
default:
ret = mt.Invoke(callClass, []);
break;
}
res = new SimApiBaseResponse<object?>
{
Data = ret
};
2023-10-20 12:33:18 +08:00
}
catch (TargetInvocationException ex)
2023-10-20 14:13:53 +08:00
{
if (ex.InnerException is SimApiException ie)
{
logger.LogDebug("Synapse RPC调用错误: {Err}", ie.Message);
res = new SimApiBaseResponse(ie.Code, ie.Message);
}
else
{
2024-09-05 12:59:57 +08:00
logger.LogError("Synapse RPC 方法异常: {Err}\n{Stack}", ex.Message, ex.StackTrace);
res = new SimApiBaseResponse(500, ex.Message);
}
}
catch (Exception ex)
{
logger.LogDebug("Synapse RPC调用失败: {Err}", ex.Message);
2024-07-26 05:03:28 +08:00
res = new SimApiBaseResponse(500, ex.Message);
2023-10-20 14:13:53 +08:00
}
2023-10-20 12:33:18 +08:00
}
2024-07-26 08:11:21 +08:00
2023-10-23 17:39:27 +08:00
var returnJson = JsonSerializer.Serialize((object)res, SimApiUtil.JsonOption);
2024-09-05 12:59:57 +08:00
var reply = $"{Options.SysName}/{appInfo[0]}/rpc/client/{appInfo[1]}/{appInfo[2]}";
2024-07-26 05:03:28 +08:00
var message = new MqttApplicationMessageBuilder()
.WithTopic(reply)
.WithPayload(returnJson)
.WithRetainFlag(false)
.Build();
2024-07-26 08:11:21 +08:00
if (!Client.IsConnected) return Task.CompletedTask;
Client.PublishAsync(message, CancellationToken.None).Wait();
2024-07-26 05:03:28 +08:00
logger.LogDebug(
"Synapse Rpc Server Return: ({BasicPropertiesMessageId}) {BasicPropertiesType}@{OptionsAppName} -> {BasicPropertiesReplyTo}\n{ReturnJson}",
2024-09-05 12:59:57 +08:00
appInfo[2], action, Options.AppName, appInfo[0], returnJson);
2024-07-26 05:03:28 +08:00
return Task.CompletedTask;
2023-10-20 12:33:18 +08:00
};
2024-08-03 19:19:42 +08:00
SubRpcServerTopic();
}
2024-08-03 19:37:40 +08:00
private void SubRpcServerTopic()
2024-08-03 19:19:42 +08:00
{
var rsSubOpts = MqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(o =>
o.WithTopic($"$queue/{RpcServerTopicPrefix}+").WithRetainHandling(MqttRetainHandling.SendAtSubscribe))
.Build();
Client!.SubscribeAsync(rsSubOpts).Wait();
2023-10-20 12:33:18 +08:00
}
}