瀏覽代碼

Merge branch 'develop-rc' into develop

JAELYS 2 年之前
父節點
當前提交
020ceb16f0

+ 26 - 1
TEAMModelOS.SDK/DI/AzureSignalR/AzureSignalRExtensions.cs

@@ -6,11 +6,36 @@ using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using System.Linq;
 using System.Linq;
 using StackExchange.Redis;
 using StackExchange.Redis;
+using System.Collections.Concurrent;
+using Microsoft.Azure.SignalR.Management;
 
 
 namespace TEAMModelOS.SDK.DI
 namespace TEAMModelOS.SDK.DI
 {
 {
     public static class AzureSignalRExtensions
     public static class AzureSignalRExtensions
     {
     {
-       
+        private static ConcurrentDictionary<string, ServiceHubContext> ServiceHubContexts { get; } = new();
+
+
+
+        /// <summary>
+        /// µo°e«H®§¦Ü¹ï¦C©Î¥DÃD
+        /// </summary>       
+        /// <param name="name">QueueName or TopicName</param>
+        /// <param name="message">°T®§</param>
+        /// <returns></returns>
+        public static ServiceHubContext GetHubContext(this ServiceManager sm, string name)
+        {
+            try
+            {
+                ServiceHubContext hub = ServiceHubContexts.GetOrAdd(name, (x) =>
+                sm.CreateHubContextAsync(name, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult());
+
+                return hub;
+            }
+            catch
+            {
+                throw;
+            }
+        }
     }
     }
 }
 }

+ 9 - 9
TEAMModelOS.SDK/DI/AzureSignalR/AzureSignalRFactory.cs

@@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Options;
 using Microsoft.Extensions.Options;
 using StackExchange.Redis;
 using StackExchange.Redis;
 using System;
 using System;
+using System.Collections.Concurrent;
 
 
 namespace TEAMModelOS.SDK.DI
 namespace TEAMModelOS.SDK.DI
 {
 {
@@ -10,6 +11,7 @@ namespace TEAMModelOS.SDK.DI
     {
     {
         private readonly IServiceProvider _services;
         private readonly IServiceProvider _services;
         private readonly IOptionsMonitor<AzureSignalRFactoryOptions> _optionsMonitor;
         private readonly IOptionsMonitor<AzureSignalRFactoryOptions> _optionsMonitor;
+        private ConcurrentDictionary<string, ServiceManager> ServiceManagers { get; } = new();
         private readonly ILogger _logger;
         private readonly ILogger _logger;
 
 
         public AzureSignalRFactory(IServiceProvider services, IOptionsMonitor<AzureSignalRFactoryOptions> optionsMonitor, ILogger<AzureSignalRFactory> logger)
         public AzureSignalRFactory(IServiceProvider services, IOptionsMonitor<AzureSignalRFactoryOptions> optionsMonitor, ILogger<AzureSignalRFactory> logger)
@@ -20,18 +22,16 @@ namespace TEAMModelOS.SDK.DI
         }
         }
 
 
         public ServiceManager GetServiceManager(string name = "Default")
         public ServiceManager GetServiceManager(string name = "Default")
-        {            
+        {
             try
             try
             {
             {
+                var serviceManager = ServiceManagers.GetOrAdd(name, x =>
                 // TODO(Mickey) : Signalr SDK 1.10.0之後,aud會無法擴充,會變成asrs.u.aud,會造成無法使用restAPI,故先降回舊版
                 // TODO(Mickey) : Signalr SDK 1.10.0之後,aud會無法擴充,會變成asrs.u.aud,會造成無法使用restAPI,故先降回舊版
-                var serviceManager = new ServiceManagerBuilder()
-                     .WithOptions(option =>
-                     {
-                         option.ConnectionString = _optionsMonitor.Get(name).SignalRConnectionString;
-                         option.ServiceTransportType = ServiceTransportType.Persistent;
-                         // option.ServiceTransportType = ServiceTransportType.Persistent
-                     })
-                     .BuildServiceManager();
+                new ServiceManagerBuilder().WithOptions(option =>
+                {
+                    option.ConnectionString = _optionsMonitor.Get(name).SignalRConnectionString;
+                    option.ServiceTransportType = ServiceTransportType.Persistent;
+                }).BuildServiceManager());
 
 
                 return serviceManager;
                 return serviceManager;
             }
             }

+ 31 - 29
TEAMModelOS/Controllers/OpenApi/IRS/TianboController.cs

@@ -13,6 +13,7 @@ using System.Net.Http;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Configuration;
 using TEAMModelOS.SDK.Models.Service;
 using TEAMModelOS.SDK.Models.Service;
 using System.Threading;
 using System.Threading;
+using TEAMModelOS.SDK.Extension;
 
 
 namespace TEAMModelOS.Controllers
 namespace TEAMModelOS.Controllers
 {
 {
@@ -70,49 +71,50 @@ namespace TEAMModelOS.Controllers
 
 
                     if (!string.IsNullOrWhiteSpace(stu?.channel) && !string.IsNullOrWhiteSpace(stu?.userid))
                     if (!string.IsNullOrWhiteSpace(stu?.channel) && !string.IsNullOrWhiteSpace(stu?.userid))
                     {
                     {
-                        var serviceManager = _azureSignalR.GetServiceManager();
-                        var cancel = new CancellationToken();
-                        var hub = await serviceManager.CreateHubContextAsync($"C{stu.channel}", cancel);
-                        try
+                        // 處理單例復用,提高請求效率,避免ServiceTransportType.Persistent websocket斷線在Azure偶發的消息遺失
+                        // TODO 尚須注意釋放的問題,後續須處理
+                        var hub = _azureSignalR.GetServiceManager().GetHubContext($"C{stu.channel}");
+                        // 下面註解寫法會造成Azure上消息偶發遺失,Localhost不會發生
+                        //var serviceManager = _azureSignalR.GetServiceManager();                       
+                        //using var hub = await serviceManager.CreateHubContextAsync($"C{stu.channel}", CancellationToken.None);
+
+                        var con = content.GetString();
+                        var ans = con switch
                         {
                         {
-                            var con = content.GetString();
-                            var ans = con switch
-                            {
-                                string _ when con.Length == 1 => new string[] { con },
-                                string _ when con.Contains('+', StringComparison.OrdinalIgnoreCase) => con.Split('+'),
-                                string _ when con.Equals("true", StringComparison.OrdinalIgnoreCase) => new string[] { "A" },
-                                string _ when con.Equals("false", StringComparison.OrdinalIgnoreCase) => new string[] { "B" },
-                                _ => throw new ArgumentNullException(nameof(content))
-                            };
+                            string _ when con.Length == 1 => new string[] { con },
+                            string _ when con.Contains('+', StringComparison.OrdinalIgnoreCase) => con.Split('+'),
+                            string _ when con.Equals("true", StringComparison.OrdinalIgnoreCase) => new string[] { "A" },
+                            string _ when con.Equals("false", StringComparison.OrdinalIgnoreCase) => new string[] { "B" },
+                            _ => throw new ArgumentNullException(nameof(content))
+                        };
 
 
-                            var common = JsonSerializer.Serialize(new
-                            {
-                                action = "DirectIRS.Answer",
-                                clientType = "DI",
-                                sender = stu.stuid,
-                                timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
-                                waitReturn = false,
-                                payload = new { irsno = "", answer = ans }
-                            });
+                        var common = JsonSerializer.Serialize(new
+                        {
+                            action = "DirectIRS.Answer",
+                            clientType = "DI",
+                            sender = stu.stuid,
+                            timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                            waitReturn = false,
+                            payload = new { irsno = "", answer = ans }
+                        });
 
 
-                            await hub.Clients.User(stu.userid).SendCoreAsync("onMessage", new[]{new {
+                        await hub.Clients.User(stu.userid).SendCoreAsync("onMessage", new[]{new {
                                 connectionId = (string)null,
                                 connectionId = (string)null,
                                 to = (string)null,
                                 to = (string)null,
                                 groupname = (string)null,
                                 groupname = (string)null,
                                 sender = stu.stuid,
                                 sender = stu.stuid,
                                 text = common
                                 text = common
                             }});
                             }});
-                        }
-                        finally
-                        {
-                            hub.Dispose();
-                        }
+
                     }
                     }
+                    await _dingDing.SendBotMsg($"IES5,{_option.Location},tianbo/api/course/cardUploadData()\n{stu?.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                 }
                 }
+
                 return Ok(new { code = 200, msg = "成功", data = (string)null });
                 return Ok(new { code = 200, msg = "成功", data = (string)null });
             }
             }
-            catch
+            catch (Exception ex)
             {
             {
+                await _dingDing.SendBotMsg($"IES5,{_option.Location},tianbo/api/course/cardUploadData()\n{ex.Message}\n{ex.StackTrace}{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                 return Ok(new { code = 200, msg = "成功", data = (string)null });
                 return Ok(new { code = 200, msg = "成功", data = (string)null });
             }
             }
 
 

+ 2 - 1
TEAMModelOS/appsettings.Development.json

@@ -36,7 +36,8 @@
       "GenPdfQueue": "dep-genpdf"
       "GenPdfQueue": "dep-genpdf"
     },
     },
     "SignalR": {
     "SignalR": {
-      "ConnectionString": "Endpoint=https://channel.service.signalr.net;AccessKey=KrblW06tuA4a/GyqRPDU0ynFFmAWxbAvyJihHclSXbQ=;Version=1.0;"
+      //"ConnectionString": "Endpoint=https://channel.service.signalr.net;AccessKey=KrblW06tuA4a/GyqRPDU0ynFFmAWxbAvyJihHclSXbQ=;Version=1.0;",
+      "ConnectionString": "Endpoint=https://channel.signalr.azure.cn;AccessKey=AtcB7JYFNUbUXb1rGxa3PVksQ2X5YSv3JOHZR9J88tw=;Version=1.0;"
     }
     }
   },
   },
   "HaBookAuth": {
   "HaBookAuth": {