Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af6bc86a0c | ||
|
|
fc7714198f | ||
|
|
d2b5f14e78 | ||
|
|
116cbcdc7f | ||
|
|
4e1b7d4845 | ||
|
|
71acb35df9 | ||
|
|
67cc7346dc | ||
|
|
8627ae61fa | ||
|
|
02523028db | ||
|
|
7d39ab5e0b | ||
|
|
87fda473d3 |
@@ -14,7 +14,7 @@ jobs:
|
|||||||
- name: Setup .NET Core
|
- name: Setup .NET Core
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: "8.0.200"
|
dotnet-version: "9.0.305"
|
||||||
- name: Publish
|
- name: Publish
|
||||||
run: |
|
run: |
|
||||||
version=`git describe --tags`
|
version=`git describe --tags`
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
namespace SimApi.Communications;
|
||||||
|
|
||||||
namespace SimApi.Communications;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 只有ID的请求
|
/// 只有ID的请求
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SimApiIdOnlyRequest
|
public class SimApiIdOnlyRequest
|
||||||
{
|
{
|
||||||
[Required] public int Id { get; set; }
|
public required int Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -15,7 +13,7 @@ public class SimApiIdOnlyRequest
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SimApiStringIdOnlyRequest
|
public class SimApiStringIdOnlyRequest
|
||||||
{
|
{
|
||||||
[Required] public string? Id { get; set; }
|
public required string Id { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -24,7 +22,7 @@ public class SimApiStringIdOnlyRequest
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
public class SimApiOneFieldRequest<T>
|
public class SimApiOneFieldRequest<T>
|
||||||
{
|
{
|
||||||
[Required] public T? Data { get; set; }
|
public required T Data { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -32,6 +30,6 @@ public class SimApiOneFieldRequest<T>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SimApiBasePageRequest
|
public class SimApiBasePageRequest
|
||||||
{
|
{
|
||||||
[Required] public int Page { get; set; }
|
public required int Page { get; set; }
|
||||||
[Required] public int Count { get; set; }
|
public required int Count { get; set; }
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,8 @@ namespace SimApi.Communications;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SimApiLoginItem
|
public class SimApiLoginItem
|
||||||
{
|
{
|
||||||
public string? Id { get; set; }
|
public string Id { get; set; } = null!;
|
||||||
public string[] Type { get; set; } = new[] { "user" };
|
public string[] Type { get; set; } = ["user"];
|
||||||
public Dictionary<string, string>? Meta { get; set; } = null;
|
public Dictionary<string, string> Meta { get; set; } = [];
|
||||||
public object? Extra { get; set; } = null;
|
public object? Extra { get; set; }
|
||||||
};
|
};
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using SimApi.Communications;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using SimApi.Communications;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
@@ -53,7 +54,7 @@ public class SimApiBaseController : Controller
|
|||||||
/// <param name="condition">检测条件</param>
|
/// <param name="condition">检测条件</param>
|
||||||
/// <param name="code">错误代码</param>
|
/// <param name="code">错误代码</param>
|
||||||
/// <param name="message">错误描述</param>
|
/// <param name="message">错误描述</param>
|
||||||
protected static void ErrorWhen(bool condition, int code = 400, string message = "")
|
protected static void ErrorWhen([DoesNotReturnIf(true)] bool condition, int code = 400, string message = "")
|
||||||
{
|
{
|
||||||
if (condition)
|
if (condition)
|
||||||
{
|
{
|
||||||
@@ -68,7 +69,7 @@ public class SimApiBaseController : Controller
|
|||||||
/// <param name="condition">检测条件</param>
|
/// <param name="condition">检测条件</param>
|
||||||
/// <param name="code">错误代码</param>
|
/// <param name="code">错误代码</param>
|
||||||
/// <param name="message">错误描述</param>
|
/// <param name="message">错误描述</param>
|
||||||
protected static void ErrorWhenTrue(bool condition, int code = 400, string message = "")
|
protected static void ErrorWhenTrue([DoesNotReturnIf(true)] bool condition, int code = 400, string message = "")
|
||||||
{
|
{
|
||||||
ErrorWhen(condition, code, message);
|
ErrorWhen(condition, code, message);
|
||||||
}
|
}
|
||||||
@@ -80,7 +81,7 @@ public class SimApiBaseController : Controller
|
|||||||
/// <param name="condition"></param>
|
/// <param name="condition"></param>
|
||||||
/// <param name="code"></param>
|
/// <param name="code"></param>
|
||||||
/// <param name="message"></param>
|
/// <param name="message"></param>
|
||||||
protected static void ErrorWhenFalse(bool condition, int code = 400, string message = "")
|
protected static void ErrorWhenFalse([DoesNotReturnIf(false)] bool condition, int code = 400, string message = "")
|
||||||
{
|
{
|
||||||
ErrorWhen(!condition, code, message);
|
ErrorWhen(!condition, code, message);
|
||||||
}
|
}
|
||||||
@@ -91,7 +92,7 @@ public class SimApiBaseController : Controller
|
|||||||
/// <param name="condition">检测条件</param>
|
/// <param name="condition">检测条件</param>
|
||||||
/// <param name="code">错误代码</param>
|
/// <param name="code">错误代码</param>
|
||||||
/// <param name="message">错误描述</param>
|
/// <param name="message">错误描述</param>
|
||||||
protected static void ErrorWhenNull(object? condition, int code = 404, string message = "请求的资源不存在")
|
protected static void ErrorWhenNull([NotNull] object? condition, int code = 404, string message = "请求的资源不存在")
|
||||||
{
|
{
|
||||||
ErrorWhen(condition == null, code, message);
|
ErrorWhen(condition == null, code, message);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-3
@@ -1,6 +1,4 @@
|
|||||||
#nullable enable
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
using SimApi.Communications;
|
using SimApi.Communications;
|
||||||
@@ -25,6 +23,18 @@ public class SimApiAuth(IDistributedCache cache)
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新登陆信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="loginItem"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string Update(SimApiLoginItem loginItem, string token)
|
||||||
|
{
|
||||||
|
cache.SetString(token, JsonSerializer.Serialize(loginItem));
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取登陆信息
|
/// 获取登陆信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -33,7 +43,7 @@ public class SimApiAuth(IDistributedCache cache)
|
|||||||
public SimApiLoginItem? GetLogin(string token)
|
public SimApiLoginItem? GetLogin(string token)
|
||||||
{
|
{
|
||||||
var login = cache.GetString(token);
|
var login = cache.GetString(token);
|
||||||
return login != null ? JsonSerializer.Deserialize<SimApiLoginItem>(login) : default;
|
return login != null ? JsonSerializer.Deserialize<SimApiLoginItem>(login) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace SimApi.Helpers;
|
|||||||
|
|
||||||
public class SimApiCache(IDistributedCache cache)
|
public class SimApiCache(IDistributedCache cache)
|
||||||
{
|
{
|
||||||
private const string Prefix = "SimApi:Cache";
|
private const string Prefix = "SimApi:Cache:";
|
||||||
|
|
||||||
public void Set(string key, object value, DistributedCacheEntryOptions? options = null)
|
public void Set(string key, object value, DistributedCacheEntryOptions? options = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class SimApiJobWebAuth(string user, string pass) : IDashboardAuthorizatio
|
|||||||
var authHeader = httpContext.Request.Headers["Authorization"].FirstOrDefault();
|
var authHeader = httpContext.Request.Headers["Authorization"].FirstOrDefault();
|
||||||
if (authHeader != null && authHeader.StartsWith("Basic "))
|
if (authHeader != null && authHeader.StartsWith("Basic "))
|
||||||
{
|
{
|
||||||
var encodedUsernamePassword = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim();
|
var encodedUsernamePassword = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1].Trim();
|
||||||
var decodedUsernamePassword = Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword));
|
var decodedUsernamePassword = Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword));
|
||||||
var username = decodedUsernamePassword.Split(':', 2)[0];
|
var username = decodedUsernamePassword.Split(':', 2)[0];
|
||||||
var password = decodedUsernamePassword.Split(':', 2)[1];
|
var password = decodedUsernamePassword.Split(':', 2)[1];
|
||||||
|
|||||||
+36
-2
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -7,6 +8,7 @@ using System.Text.Json;
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Text.Unicode;
|
using System.Text.Unicode;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace SimApi.Helpers;
|
namespace SimApi.Helpers;
|
||||||
|
|
||||||
@@ -22,9 +24,10 @@ public static class SimApiUtil
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static JsonSerializerOptions JsonOption => new()
|
public static JsonSerializerOptions JsonOption => new()
|
||||||
{
|
{
|
||||||
|
// ReferenceHandler = ReferenceHandler.Preserve,
|
||||||
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
|
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
// DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -62,12 +65,43 @@ public static class SimApiUtil
|
|||||||
return stringBuilder.ToString();
|
return stringBuilder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sha1加密字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">源字符串</param>
|
||||||
|
/// <param name="mode">加密结果"x2"结果为32位,"x3"结果为48位,"x4"结果为64位</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string Sha1(string source, string mode = "x2")
|
||||||
|
{
|
||||||
|
var hash = SHA1.HashData(Encoding.UTF8.GetBytes(source));
|
||||||
|
var sb = new StringBuilder(hash.Length * 2);
|
||||||
|
foreach (var b in hash)
|
||||||
|
{
|
||||||
|
sb.Append(b.ToString(mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将XML字符串序列化为对象
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source"></param>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T XmlDeserialize<T>(string source)
|
||||||
|
{
|
||||||
|
var xmlConvertor = new XmlSerializer(typeof(T));
|
||||||
|
using var reader = new StringReader(source);
|
||||||
|
return (T)xmlConvertor.Deserialize(reader)!;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 将对象序列化成JSON (控制台输出中文不会被编码)
|
/// 将对象序列化成JSON (控制台输出中文不会被编码)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj"></param>
|
/// <param name="obj"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string Json(object obj)
|
public static string Json(object? obj)
|
||||||
{
|
{
|
||||||
return JsonSerializer.Serialize(obj, JsonOption);
|
return JsonSerializer.Serialize(obj, JsonOption);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -14,8 +14,8 @@
|
|||||||
<SynchReleaseVersion>false</SynchReleaseVersion>
|
<SynchReleaseVersion>false</SynchReleaseVersion>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<PackageVersion>5.0.2</PackageVersion>
|
<PackageVersion>5.0.2</PackageVersion>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -23,14 +23,15 @@
|
|||||||
<Folder Include="Exceptions\"/>
|
<Folder Include="Exceptions\"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.17" />
|
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.18" />
|
||||||
<PackageReference Include="Hangfire.Console" Version="1.4.3" />
|
<PackageReference Include="Hangfire.Console" Version="1.4.3" />
|
||||||
<PackageReference Include="Hangfire.Redis.StackExchange" Version="1.9.4" />
|
<PackageReference Include="Hangfire.Redis.StackExchange" Version="1.12.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.5" />
|
||||||
<PackageReference Include="Minio" Version="6.0.4" />
|
<PackageReference Include="Minio" Version="6.0.4" />
|
||||||
<PackageReference Include="MQTTnet" Version="5.0.1.1416" />
|
<PackageReference Include="MQTTnet" Version="5.0.1.1416" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="7.2.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="8.1.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="7.2.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="8.1.1" />
|
||||||
|
<PackageReference Include="System.Text.Json" Version="9.0.10" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<MonoDevelop>
|
<MonoDevelop>
|
||||||
|
|||||||
+34
-7
@@ -247,7 +247,10 @@ public static class SimApiExtensions
|
|||||||
{
|
{
|
||||||
builder.AddControllers(opt => opt.Filters.Add<SimApiResponseFilter>())
|
builder.AddControllers(opt => opt.Filters.Add<SimApiResponseFilter>())
|
||||||
.AddXmlSerializerFormatters()
|
.AddXmlSerializerFormatters()
|
||||||
.AddJsonOptions(opt => opt.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase);
|
.AddJsonOptions(opt =>
|
||||||
|
{
|
||||||
|
opt.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.AddSingleton(simApiOptions);
|
builder.AddSingleton(simApiOptions);
|
||||||
@@ -328,22 +331,46 @@ public static class SimApiExtensions
|
|||||||
logger.LogInformation("开始配置SimApiAuth...");
|
logger.LogInformation("开始配置SimApiAuth...");
|
||||||
builder.UseMiddleware<SimApiAuthMiddleware>();
|
builder.UseMiddleware<SimApiAuthMiddleware>();
|
||||||
builder.MapControllerRoute(name: "GetUserInfo", pattern: "/user/info",
|
builder.MapControllerRoute(name: "GetUserInfo", pattern: "/user/info",
|
||||||
defaults: new { controller = "SimApiCommon", action = "UserInfo" });
|
defaults: new
|
||||||
|
{
|
||||||
|
controller = "SimApiCommon",
|
||||||
|
action = "UserInfo"
|
||||||
|
});
|
||||||
builder.MapControllerRoute(name: "CheckLogin", pattern: "/auth/check",
|
builder.MapControllerRoute(name: "CheckLogin", pattern: "/auth/check",
|
||||||
defaults: new { controller = "SimApiCommon", action = "CheckLogin" });
|
defaults: new
|
||||||
|
{
|
||||||
|
controller = "SimApiCommon",
|
||||||
|
action = "CheckLogin"
|
||||||
|
});
|
||||||
builder.MapControllerRoute(name: "Logout", pattern: "/auth/logout",
|
builder.MapControllerRoute(name: "Logout", pattern: "/auth/logout",
|
||||||
defaults: new { controller = "SimApiCommon", action = "Logout" });
|
defaults: new
|
||||||
|
{
|
||||||
|
controller = "SimApiCommon",
|
||||||
|
action = "Logout"
|
||||||
|
});
|
||||||
if (options.EnableCoceSdk)
|
if (options.EnableCoceSdk)
|
||||||
{
|
{
|
||||||
logger.LogInformation("开始配置CoceAppSdk...\nApi入口: {ApiUrl}\nAuth入口:{AuthUrl}n\nAppId: {AppId}",
|
logger.LogInformation("开始配置CoceAppSdk...\nApi入口: {ApiUrl}\nAuth入口:{AuthUrl}n\nAppId: {AppId}",
|
||||||
options.CoceSdkOptions.ApiEndpoint, options.CoceSdkOptions.AuthEndpoint,
|
options.CoceSdkOptions.ApiEndpoint, options.CoceSdkOptions.AuthEndpoint,
|
||||||
options.CoceSdkOptions.AppId);
|
options.CoceSdkOptions.AppId);
|
||||||
builder.MapControllerRoute(name: "LoginUseCoce", pattern: "/auth/login",
|
builder.MapControllerRoute(name: "LoginUseCoce", pattern: "/auth/login",
|
||||||
defaults: new { controller = "Coce", action = "Login" });
|
defaults: new
|
||||||
|
{
|
||||||
|
controller = "Coce",
|
||||||
|
action = "Login"
|
||||||
|
});
|
||||||
builder.MapControllerRoute(name: "LoginUseCoce", pattern: "/user/groups",
|
builder.MapControllerRoute(name: "LoginUseCoce", pattern: "/user/groups",
|
||||||
defaults: new { controller = "Coce", action = "ListGroups" });
|
defaults: new
|
||||||
|
{
|
||||||
|
controller = "Coce",
|
||||||
|
action = "ListGroups"
|
||||||
|
});
|
||||||
builder.MapControllerRoute(name: "LoginUseCoce", pattern: "/auth/config",
|
builder.MapControllerRoute(name: "LoginUseCoce", pattern: "/auth/config",
|
||||||
defaults: new { controller = "Coce", action = "GetConfig" });
|
defaults: new
|
||||||
|
{
|
||||||
|
controller = "Coce",
|
||||||
|
action = "GetConfig"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ public partial class Synapse
|
|||||||
private void RunEventServer()
|
private void RunEventServer()
|
||||||
{
|
{
|
||||||
Client!.ApplicationMessageReceivedAsync += async e =>
|
Client!.ApplicationMessageReceivedAsync += async e =>
|
||||||
|
{
|
||||||
|
await Task.Run(async () =>
|
||||||
{
|
{
|
||||||
if (!e.ApplicationMessage.Topic.StartsWith(EventServerTopicPrefix)) return;
|
if (!e.ApplicationMessage.Topic.StartsWith(EventServerTopicPrefix)) return;
|
||||||
var reqBody = e.ApplicationMessage.ConvertPayloadToString();
|
var reqBody = e.ApplicationMessage.ConvertPayloadToString();
|
||||||
@@ -37,8 +39,8 @@ public partial class Synapse
|
|||||||
{
|
{
|
||||||
var pt = mt.GetParameters()[1].ParameterType;
|
var pt = mt.GetParameters()[1].ParameterType;
|
||||||
mt.Invoke(callClass, pt == typeof(string)
|
mt.Invoke(callClass, pt == typeof(string)
|
||||||
? new object?[] { eventName, reqBody }
|
? [eventName, reqBody]
|
||||||
: new object?[] { eventName, JsonSerializer.Deserialize(reqBody, pt, SimApiUtil.JsonOption) });
|
: [eventName, JsonSerializer.Deserialize(reqBody, pt, SimApiUtil.JsonOption)]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -52,6 +54,7 @@ public partial class Synapse
|
|||||||
}))
|
}))
|
||||||
.ToList();
|
.ToList();
|
||||||
await Task.WhenAll(tasks);
|
await Task.WhenAll(tasks);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
SubEventServerTopic();
|
SubEventServerTopic();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MQTTnet;
|
using MQTTnet;
|
||||||
using MQTTnet.Packets;
|
|
||||||
using SimApi.Communications;
|
using SimApi.Communications;
|
||||||
using SimApi.Helpers;
|
using SimApi.Helpers;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace SimApi;
|
namespace SimApi;
|
||||||
|
|
||||||
public partial class Synapse
|
public partial class Synapse
|
||||||
{
|
{
|
||||||
private Dictionary<string, TaskCompletionSource<string>> ResponseCompletionSources { get; } = new();
|
private ConcurrentDictionary<string, TaskCompletionSource<string>> ResponseCompletionSources { get; } = new();
|
||||||
|
|
||||||
private string EventClientTopicPrefix => $"{Options.SysName}/{Options.AppName}/rpc/client/{Options.AppId}/";
|
private string EventClientTopicPrefix => $"{Options.SysName}/{Options.AppName}/rpc/client/{Options.AppId}/";
|
||||||
|
|
||||||
@@ -27,7 +26,7 @@ public partial class Synapse
|
|||||||
var messageId = e.ApplicationMessage.Topic.Replace(EventClientTopicPrefix, string.Empty);
|
var messageId = e.ApplicationMessage.Topic.Replace(EventClientTopicPrefix, string.Empty);
|
||||||
if (!ResponseCompletionSources.TryGetValue(messageId, out var tcs)) return Task.CompletedTask;
|
if (!ResponseCompletionSources.TryGetValue(messageId, out var tcs)) return Task.CompletedTask;
|
||||||
tcs.SetResult(reqBody);
|
tcs.SetResult(reqBody);
|
||||||
ResponseCompletionSources.Remove(messageId);
|
ResponseCompletionSources.Remove(messageId, out _);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
SubRpcClientTopic();
|
SubRpcClientTopic();
|
||||||
@@ -43,6 +42,7 @@ public partial class Synapse
|
|||||||
private string? FireRpc(string app, string action, object? param, Dictionary<string, string>? headers = null,
|
private string? FireRpc(string app, string action, object? param, Dictionary<string, string>? headers = null,
|
||||||
int? timeout = null)
|
int? timeout = null)
|
||||||
{
|
{
|
||||||
|
// 移除锁语句
|
||||||
string paramJson;
|
string paramJson;
|
||||||
if (param is string strParam)
|
if (param is string strParam)
|
||||||
{
|
{
|
||||||
@@ -56,7 +56,7 @@ public partial class Synapse
|
|||||||
var topic = $"{Options.SysName}/{app}/rpc/server/{action}";
|
var topic = $"{Options.SysName}/{app}/rpc/server/{action}";
|
||||||
var messageId = Guid.NewGuid().ToString();
|
var messageId = Guid.NewGuid().ToString();
|
||||||
var tcs = new TaskCompletionSource<string>();
|
var tcs = new TaskCompletionSource<string>();
|
||||||
ResponseCompletionSources.Add(messageId, tcs);
|
ResponseCompletionSources.TryAdd(messageId, tcs);
|
||||||
var messageBuilder = new MqttApplicationMessageBuilder()
|
var messageBuilder = new MqttApplicationMessageBuilder()
|
||||||
.WithTopic(topic)
|
.WithTopic(topic)
|
||||||
.WithPayload(paramJson)
|
.WithPayload(paramJson)
|
||||||
|
|||||||
+10
-6
@@ -20,9 +20,11 @@ public partial class Synapse
|
|||||||
|
|
||||||
private void RunRpcServer()
|
private void RunRpcServer()
|
||||||
{
|
{
|
||||||
Client!.ApplicationMessageReceivedAsync += e =>
|
Client!.ApplicationMessageReceivedAsync += async e =>
|
||||||
{
|
{
|
||||||
if (!e.ApplicationMessage.Topic.StartsWith(RpcServerTopicPrefix)) return Task.CompletedTask;
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
if (!e.ApplicationMessage.Topic.StartsWith(RpcServerTopicPrefix)) return;
|
||||||
var reqBody = e.ApplicationMessage.ConvertPayloadToString();
|
var reqBody = e.ApplicationMessage.ConvertPayloadToString();
|
||||||
var action = e.ApplicationMessage.Topic.Replace(RpcServerTopicPrefix, string.Empty);
|
var action = e.ApplicationMessage.Topic.Replace(RpcServerTopicPrefix, string.Empty);
|
||||||
var appInfo = e.ApplicationMessage.ResponseTopic.Split(",");
|
var appInfo = e.ApplicationMessage.ResponseTopic.Split(",");
|
||||||
@@ -58,7 +60,10 @@ public partial class Synapse
|
|||||||
var pt2 = mt.GetParameters()[0].ParameterType;
|
var pt2 = mt.GetParameters()[0].ParameterType;
|
||||||
var param2 = pt2 == typeof(string)
|
var param2 = pt2 == typeof(string)
|
||||||
? [reqBody]
|
? [reqBody]
|
||||||
: new[] { JsonSerializer.Deserialize(reqBody, pt2, SimApiUtil.JsonOption), headerData };
|
: new[]
|
||||||
|
{
|
||||||
|
JsonSerializer.Deserialize(reqBody, pt2, SimApiUtil.JsonOption), headerData
|
||||||
|
};
|
||||||
ret = mt.Invoke(callClass, param2);
|
ret = mt.Invoke(callClass, param2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -98,13 +103,12 @@ public partial class Synapse
|
|||||||
.WithPayload(returnJson)
|
.WithPayload(returnJson)
|
||||||
.WithRetainFlag(false)
|
.WithRetainFlag(false)
|
||||||
.Build();
|
.Build();
|
||||||
if (!Client.IsConnected) return Task.CompletedTask;
|
if (!Client.IsConnected) return;
|
||||||
Client.PublishAsync(message, CancellationToken.None).Wait();
|
Client.PublishAsync(message, CancellationToken.None).Wait();
|
||||||
logger.LogDebug(
|
logger.LogDebug(
|
||||||
"Synapse Rpc Server Return: ({BasicPropertiesMessageId}) {BasicPropertiesType}@{OptionsAppName} -> {BasicPropertiesReplyTo}\n{ReturnJson}",
|
"Synapse Rpc Server Return: ({BasicPropertiesMessageId}) {BasicPropertiesType}@{OptionsAppName} -> {BasicPropertiesReplyTo}\n{ReturnJson}",
|
||||||
appInfo[2], action, Options.AppName, appInfo[0], returnJson);
|
appInfo[2], action, Options.AppName, appInfo[0], returnJson);
|
||||||
|
});
|
||||||
return Task.CompletedTask;
|
|
||||||
};
|
};
|
||||||
SubRpcServerTopic();
|
SubRpcServerTopic();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user