diff --git a/EOM.TSHotelManagement.API/Extensions/AutofacConfigExtensions.cs b/EOM.TSHotelManagement.API/Extensions/AutofacConfigExtensions.cs index b746dbba4dc5a162827c94d030bea5a255d1d787..6c75f1490f6ab88d148e4c2e82b8bb7fa952efae 100644 --- a/EOM.TSHotelManagement.API/Extensions/AutofacConfigExtensions.cs +++ b/EOM.TSHotelManagement.API/Extensions/AutofacConfigExtensions.cs @@ -28,6 +28,7 @@ namespace EOM.TSHotelManagement.WebApi builder.RegisterType() .InstancePerDependency(); + builder.RegisterType().AsSelf().SingleInstance(); builder.RegisterType().AsSelf().InstancePerLifetimeScope(); builder.RegisterType().AsSelf().InstancePerLifetimeScope(); builder.RegisterType().AsSelf().InstancePerLifetimeScope(); @@ -55,4 +56,4 @@ namespace EOM.TSHotelManagement.WebApi #endregion } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs b/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs index 6e2b64966b258454ae8443368d54d16864f91cdb..2e9b9daed0d509005e28fd9527fb2bee66face23 100644 --- a/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs +++ b/EOM.TSHotelManagement.API/Extensions/ServiceExtensions.cs @@ -43,27 +43,64 @@ namespace EOM.TSHotelManagement.WebApi public static void ConfigureQuartz(this IServiceCollection services, IConfiguration configuration) { - var defaultDatabaseName = configuration.GetValue("DefaultDatabase") ?? SystemConstant.MariaDB.Code; services.AddQuartz(q => { var jobs = configuration.GetSection(SystemConstant.JobKeys.Code).Get() ?? Array.Empty(); foreach (var job in jobs) { - q.AddJob(opts => opts.WithIdentity(job) - .StoreDurably() - .WithDescription($"{job} 定时作业")); + var reservationJobKey = $"{job}-Reservation"; + var mailJobKey = $"{job}-Mail"; + var imageHostingJobKey = $"{job}-ImageHosting"; + var redisJobKey = $"{job}-Redis"; + + q.AddJob(opts => opts + .WithIdentity(reservationJobKey) + .StoreDurably() + .WithDescription($"{reservationJobKey} 定时作业")); - // 创建触发器(每天凌晨1点执行) q.AddTrigger(opts => opts - .ForJob(job) - .WithIdentity($"{job}-Trigger") - //.WithCronSchedule("1-2 * * * * ? ")); // Debug Use Only + .ForJob(reservationJobKey) + .WithIdentity($"{reservationJobKey}-Trigger") + //.WithCronSchedule("* * * * * ? ")); // Debug Use Only 每秒执行一次 .WithCronSchedule("0 0 1 * * ?")); // 每天1:00 AM执行 + + q.AddJob(opts => opts + .WithIdentity(mailJobKey) + .StoreDurably() + .WithDescription($"{mailJobKey} 定时作业")); + + q.AddTrigger(opts => opts + .ForJob(mailJobKey) + .WithIdentity($"{mailJobKey}-Trigger") + //.WithCronSchedule("* * * * * ? ")); // Debug Use Only 每秒执行一次 + .WithCronSchedule("0 */5 * * * ?")); // 每5分钟执行一次 + + q.AddJob(opts => opts + .WithIdentity(imageHostingJobKey) + .StoreDurably() + .WithDescription($"{imageHostingJobKey} 定时作业")); + + q.AddTrigger(opts => opts + .ForJob(imageHostingJobKey) + .WithIdentity($"{imageHostingJobKey}-Trigger") + //.WithCronSchedule("* * * * * ? ")); // Debug Use Only 每秒执行一次 + .WithCronSchedule("0 */5 * * * ?")); // 每5分钟执行一次 + + q.AddJob(opts => opts + .WithIdentity(redisJobKey) + .StoreDurably() + .WithDescription($"{redisJobKey} 定时作业")); + + q.AddTrigger(opts => opts + .ForJob(redisJobKey) + .WithIdentity($"{redisJobKey}-Trigger") + //.WithCronSchedule("* * * * * ? ")); // Debug Use Only 每秒执行一次 + .WithCronSchedule("0 */5 * * * ?")); // 每5分钟执行一次 } }); - services.AddQuartzHostedService(q => + services.AddQuartzHostedService(q => { q.WaitForJobsToComplete = true; q.AwaitApplicationStarted = true; @@ -86,9 +123,14 @@ namespace EOM.TSHotelManagement.WebApi public static void RegisterSingletonServices(this IServiceCollection services, IConfiguration configuration) { services.AddScoped(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + services.AddHttpClient("HeartBeatCheckClient", client => + { + client.Timeout = TimeSpan.FromSeconds(30); + }); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.Configure(configuration.GetSection("CsrfToken")); services.AddSingleton(); @@ -225,4 +267,4 @@ namespace EOM.TSHotelManagement.WebApi }); } } -} \ No newline at end of file +} diff --git a/EOM.TSHotelManagement.API/appsettings.Application.json b/EOM.TSHotelManagement.API/appsettings.Application.json index 1f0c6fada36838e2d5a66c5233e017d07f2a13ad..8fd1da27f0554832b0a122d5f4409662a2f469da 100644 --- a/EOM.TSHotelManagement.API/appsettings.Application.json +++ b/EOM.TSHotelManagement.API/appsettings.Application.json @@ -12,7 +12,9 @@ ], "AllowedHosts": "*", "JobKeys": [ - "ReservationExpirationCheckJob" + "ReservationExpirationCheckJob", + "MailServiceCheckJob", + "RedisServiceCheckJob" ], "ExpirationSettings": { "NotifyDaysBefore": 3, diff --git a/EOM.TSHotelManagement.API/appsettings.Database.json b/EOM.TSHotelManagement.API/appsettings.Database.json index 265b3738bbf2d1bad630e77ba186948bfd521cbf..0c020cb33fa566cef789a22a64918a785a8f5ea0 100644 --- a/EOM.TSHotelManagement.API/appsettings.Database.json +++ b/EOM.TSHotelManagement.API/appsettings.Database.json @@ -7,5 +7,10 @@ "SqlServerConnectStr": "Server=my_sqlserver_host;Database=tshoteldb;User Id=my_sqlserver_user;Password=my_sqlserver_password;", "OracleConnectStr": "User Id=my_oracle_user;Password=my_oracle_password;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=my_oracle_host)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=my_oracle_service_name)));" }, - "InitializeDatabase": true + "Redis": { + "Enabled": false, + "ConnectionString": "host:port,password=your_redis_password", //host:port,password=your_redis_password + "DefaultDatabase": 0 + }, + "InitializeDatabase": false } \ No newline at end of file diff --git a/EOM.TSHotelManagement.Common/EOM.TSHotelManagement.Common.csproj b/EOM.TSHotelManagement.Common/EOM.TSHotelManagement.Common.csproj index af3b4bcec6dd88704b53253dac693a3e557dfddc..a0d5fece4ab1882fc2fd811c905c27459c354859 100644 --- a/EOM.TSHotelManagement.Common/EOM.TSHotelManagement.Common.csproj +++ b/EOM.TSHotelManagement.Common/EOM.TSHotelManagement.Common.csproj @@ -24,11 +24,13 @@ + + diff --git a/EOM.TSHotelManagement.Common/Helper/JWTHelper.cs b/EOM.TSHotelManagement.Common/Helper/JWTHelper.cs index 6c95ca28d3a8ef9512d6f16624403be26cabfa58..5714c4dd369eaf33f8913bc260c67f08ef4856f4 100644 --- a/EOM.TSHotelManagement.Common/Helper/JWTHelper.cs +++ b/EOM.TSHotelManagement.Common/Helper/JWTHelper.cs @@ -10,9 +10,9 @@ namespace EOM.TSHotelManagement.Common { public class JWTHelper { - private readonly IJwtConfigFactory _jwtConfigFactory; + private readonly JwtConfigFactory _jwtConfigFactory; - public JWTHelper(IJwtConfigFactory jwtConfigFactory) + public JWTHelper(JwtConfigFactory jwtConfigFactory) { _jwtConfigFactory = jwtConfigFactory; } diff --git a/EOM.TSHotelManagement.Common/Helper/LskyHelper.cs b/EOM.TSHotelManagement.Common/Helper/LskyHelper.cs index 6d50d9acbb5a32272e47f624d7614f2e122324f4..7fab1b32c0b981d5f3607b022e71fb12147d251d 100644 --- a/EOM.TSHotelManagement.Common/Helper/LskyHelper.cs +++ b/EOM.TSHotelManagement.Common/Helper/LskyHelper.cs @@ -11,15 +11,78 @@ namespace EOM.TSHotelManagement.Common { public class LskyHelper { - private readonly ILskyConfigFactory lskyConfigFactory; + private const string LskyHttpClientName = "HeartBeatCheckClient"; + private readonly LskyConfigFactory lskyConfigFactory; + private readonly IHttpClientFactory httpClientFactory; private readonly ILogger logger; - public LskyHelper(ILskyConfigFactory lskyConfigFactory, ILogger logger) + public LskyHelper( + LskyConfigFactory lskyConfigFactory, + IHttpClientFactory httpClientFactory, + ILogger logger) { this.lskyConfigFactory = lskyConfigFactory; + this.httpClientFactory = httpClientFactory; this.logger = logger; } + public async Task CheckServiceStatusAsync() + { + var lskyConfig = lskyConfigFactory.GetLskyConfig(); + var address = lskyConfig.BaseAddress; + var enabled = lskyConfig.Enabled; + + try + { + if (!enabled) + { + logger.LogWarning("Lsky图床服务未启用,跳过状态检查。"); + return false; + } + + var domain = UrlHelper.ExtractDomainFromBaseAddress(lskyConfig.BaseAddress); + + if (string.IsNullOrWhiteSpace(domain)) + { + logger.LogError("无法从BaseAddress中提取有效域名: {BaseAddress}", lskyConfig.BaseAddress); + return false; + } + + logger.LogInformation("使用域名进行健康检查: {Domain}", domain); + + var httpClient = httpClientFactory.CreateClient(LskyHttpClientName); + httpClient.Timeout = TimeSpan.FromSeconds(10); + + var response = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, domain)); + + if (response.IsSuccessStatusCode) + { + logger.LogInformation("Lsky图床服务状态检查成功,状态码: {StatusCode}", response.StatusCode); + return true; + } + else + { + logger.LogWarning("Lsky图床服务返回异常状态码: {StatusCode}", response.StatusCode); + return false; + } + } + catch (HttpRequestException httpEx) + { + logger.LogError(httpEx, "HTTP请求异常,Lsky图床服务可能不可用"); + return false; + } + catch (TaskCanceledException timeoutEx) when (timeoutEx.CancellationToken == CancellationToken.None) + { + logger.LogError(timeoutEx, "Lsky图床服务连接超时"); + return false; + } + catch (Exception ex) + { + logger.LogError(ex, "Lsky图床服务状态检查发生未知异常"); + return false; + } + } + public async Task GetEnabledState() { logger.LogError("Checking if Lsky image storage is enabled."); @@ -29,7 +92,7 @@ namespace EOM.TSHotelManagement.Common public async Task GetImageStorageTokenAsync() { var lskConfig = lskyConfigFactory.GetLskyConfig(); - using var httpClient = new HttpClient(); + var httpClient = httpClientFactory.CreateClient(LskyHttpClientName); var tokenRequest = new { email = lskConfig.Email, @@ -65,7 +128,7 @@ namespace EOM.TSHotelManagement.Common if (string.IsNullOrEmpty(lskConfig?.BaseAddress)) throw new InvalidOperationException(LocalizationHelper.GetLocalizedString("The base URL for the Lsky service is not configured.", "兰空图床基础地址未配置")); - using var httpClient = new HttpClient(); + var httpClient = httpClientFactory.CreateClient(LskyHttpClientName); using var content = new MultipartFormDataContent(); var fileContent = new StreamContent(fileStream); diff --git a/EOM.TSHotelManagement.Common/Helper/MailHelper.cs b/EOM.TSHotelManagement.Common/Helper/MailHelper.cs index cd76c38617026fa02fc2109378fc35527d639a9e..ca0aa7370bfd86881aa91181bad77841e113b33b 100644 --- a/EOM.TSHotelManagement.Common/Helper/MailHelper.cs +++ b/EOM.TSHotelManagement.Common/Helper/MailHelper.cs @@ -1,22 +1,25 @@ using EOM.TSHotelManagement.Infrastructure; using MailKit.Net.Smtp; using MailKit.Security; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using MimeKit; +using Quartz.Logging; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Mime; +using System.Net.Sockets; namespace EOM.TSHotelManagement.Common { public class MailHelper { - private readonly IMailConfigFactory mailConfigFactory; + private readonly MailConfigFactory mailConfigFactory; private readonly ILogger logger; - public MailHelper(IMailConfigFactory mailConfigFactory, ILogger logger) + public MailHelper(MailConfigFactory mailConfigFactory, ILogger logger) { this.mailConfigFactory = mailConfigFactory; this.logger = logger; @@ -105,6 +108,48 @@ namespace EOM.TSHotelManagement.Common } } + + public async Task CheckServiceStatusAsync() + { + var mailConfig = mailConfigFactory.GetMailConfig(); + var host = mailConfig.Host; + var port = mailConfig.Port; + var enabled = mailConfig.Enabled; + + try + { + if (!enabled) + { + logger.LogWarning("邮件服务未启用, 跳过检查"); + return false; + } + + if (port == 0) + { + logger.LogError("邮件服务配置信息缺失"); + return false; + } + + using var client = new TcpClient(); + await client.ConnectAsync(host, port); + using var stream = client.GetStream(); + using var reader = new StreamReader(stream); + string response = await reader.ReadLineAsync(); + if (response?.StartsWith("220") == true) + { + using var writer = new StreamWriter(stream); + await writer.WriteLineAsync("QUIT"); + return true; + } + return false; + } + catch (Exception ex) + { + logger.LogError(ex, "邮件服务连接异常"); + return false; + } + } + #region Private Methods private bool IsMailConfigValid() diff --git a/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs b/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..98deaa6b06f4c33b63df2968e3107f69653d2ca7 --- /dev/null +++ b/EOM.TSHotelManagement.Common/Helper/RedisHelper.cs @@ -0,0 +1,144 @@ +using EOM.TSHotelManagement.Infrastructure; +using Microsoft.Extensions.Logging; +using StackExchange.Redis; +using System; + +namespace EOM.TSHotelManagement.Common +{ + public class RedisHelper + { + private readonly object _lock = new object(); + private IConnectionMultiplexer _connection; + private readonly ILogger logger; + private readonly RedisConfigFactory configFactory; + + public RedisHelper(RedisConfigFactory configFactory, ILogger logger) + { + this.configFactory = configFactory; + this.logger = logger; + Initialize(); + } + + public void Initialize() + { + lock (_lock) + { + if (_connection != null) return; + try + { + var redisConfig = configFactory.GetRedisConfig(); + + if (!redisConfig.Enable) + { + logger.LogInformation("Redis功能未启用,跳过初始化"); + return; + } + + if (string.IsNullOrWhiteSpace(redisConfig?.ConnectionString)) + throw new ArgumentException("Redis连接字符串不能为空"); + + var options = ConfigurationOptions.Parse(redisConfig.ConnectionString); + options.AbortOnConnectFail = false; + options.ConnectTimeout = 5000; + options.ReconnectRetryPolicy = new ExponentialRetry(3000); + + _connection = ConnectionMultiplexer.Connect(options); + _connection.GetDatabase().Ping(); + } + catch (Exception ex) + { + logger.LogCritical(ex, "Redis初始化失败"); + throw; + } + } + } + + public IDatabase GetDatabase() + { + if (_connection == null) + throw new System.Exception("RedisHelper not initialized. Call Initialize first."); + + return _connection.GetDatabase(); + } + + public async Task CheckServiceStatusAsync() + { + try + { + var db = GetDatabase(); + var ping = await db.PingAsync(); + logger.LogInformation($"Redis响应时间:{ping.TotalMilliseconds} ms"); + return true; + } + catch (Exception ex) + { + logger.LogError(ex, "Redis服务检查失败"); + return false; + } + } + + public async Task SetAsync(string key, string value, TimeSpan? expiry = null) + { + try + { + var db = GetDatabase(); + if (expiry.HasValue) + { + return await db.StringSetAsync(key, value, new StackExchange.Redis.Expiration(expiry.Value)); + } + else + { + return await db.StringSetAsync(key, value); + } + } + catch (Exception ex) + { + logger.LogError(ex, $"Redis设置值失败,键:{key}!"); + return false; + } + } + + public async Task GetAsync(string key) + { + try + { + var db = GetDatabase(); + return await db.StringGetAsync(key); + } + catch (Exception ex) + { + logger.LogError(ex, $"Redis获取值失败,键:{key}!"); + return null; + } + } + + public async Task DeleteAsync(string key) + { + try + { + var db = GetDatabase(); + return await db.KeyDeleteAsync(key); + } + catch (Exception ex) + { + logger.LogError(ex, $"Redis删除键失败,键:{key}!"); + return false; + } + } + + public async Task KeyExistsAsync(string key) + { + try + { + var db = GetDatabase(); + return await db.KeyExistsAsync(key); + } + catch (Exception ex) + { + logger.LogError(ex, $"Redis键存在检查失败,键:{key}!"); + return false; + } + } + + } +} diff --git a/EOM.TSHotelManagement.Common/Helper/UrlHelper.cs b/EOM.TSHotelManagement.Common/Helper/UrlHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..214723c62798cf8b0aec74118366e9aeba82ca90 --- /dev/null +++ b/EOM.TSHotelManagement.Common/Helper/UrlHelper.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Common +{ + public static class UrlHelper + { + /// + /// 从 BaseAddress 中提取域名(不包含 API 路径) + /// + /// 完整的 BaseAddress + /// 提取的域名 + public static string ExtractDomainFromBaseAddress(string baseAddress) + { + if (string.IsNullOrWhiteSpace(baseAddress)) + { + return string.Empty; + } + + try + { + // 确保地址是有效的 URI + if (!Uri.TryCreate(baseAddress, UriKind.Absolute, out Uri uri)) + { + // 如果不是完整 URI,尝试添加协议 + if (!baseAddress.StartsWith("http://") && !baseAddress.StartsWith("https://")) + { + var httpsAddress = "https://" + baseAddress; + if (Uri.TryCreate(httpsAddress, UriKind.Absolute, out uri)) + { + return $"{uri.Scheme}://{uri.Host}"; + } + } + return baseAddress; // 返回原始地址作为后备方案 + } + + // 提取协议和主机名 + return $"{uri.Scheme}://{uri.Host}"; + } + catch (Exception) + { + return baseAddress; // 如果解析失败,返回原始地址 + } + } + + /// + /// 获取干净的域名(不包含协议) + /// + public static string ExtractCleanDomain(string baseAddress) + { + if (string.IsNullOrWhiteSpace(baseAddress)) + { + return string.Empty; + } + + try + { + if (Uri.TryCreate(baseAddress, UriKind.Absolute, out Uri uri)) + { + return uri.Host; + } + + // 尝试处理不完整的地址 + var cleanAddress = baseAddress + .Replace("https://", "") + .Replace("http://", "") + .Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); // 取第一个部分(域名) + + return cleanAddress; + } + catch (Exception) + { + return baseAddress; + } + } + } +} diff --git a/EOM.TSHotelManagement.Common/QuartzWorkspace/ImageHosting/ImageHostingServiceCheckJob.cs b/EOM.TSHotelManagement.Common/QuartzWorkspace/ImageHosting/ImageHostingServiceCheckJob.cs new file mode 100644 index 0000000000000000000000000000000000000000..7ce390c0139629d787a860f93632b4fcc5a55c09 --- /dev/null +++ b/EOM.TSHotelManagement.Common/QuartzWorkspace/ImageHosting/ImageHostingServiceCheckJob.cs @@ -0,0 +1,49 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Quartz; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Common +{ + [DisallowConcurrentExecution] + public class ImageHostingServiceCheckJob : IJob + { + private readonly ILogger _logger; + private readonly IServiceProvider _serviceProvider; + private readonly IConfiguration _configuration; + + public ImageHostingServiceCheckJob( + ILogger logger, + IServiceProvider serviceProvider, + IConfiguration configuration) + { + _logger = logger; + _serviceProvider = serviceProvider; + _configuration = configuration; + } + + public async Task Execute(IJobExecutionContext context) + { + _logger.LogInformation("开始检测图床服务状态..."); + + using var scope = _serviceProvider.CreateScope(); + var imageHostingService = scope.ServiceProvider.GetRequiredService(); + + bool isHealthy = false; + try + { + isHealthy = await imageHostingService.CheckServiceStatusAsync(); + } + catch (Exception ex) + { + _logger.LogError(ex, "图床服务检测异常"); + } + + _logger.LogInformation($"图床服务检测完成,状态:{(isHealthy ? "健康" : "故障")}"); + } + + } +} diff --git a/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs b/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs index 4b7076d00f3ee38d0e1c8ba3c588e6a1888c017c..6431906bb483d9a28921f8e58700bf04d03ea051 100644 --- a/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs +++ b/EOM.TSHotelManagement.Common/QuartzWorkspace/Job/ReservationExpirationCheckJob.cs @@ -38,6 +38,13 @@ namespace EOM.TSHotelManagement.Common var db = scope.ServiceProvider.GetRequiredService(); var emailService = scope.ServiceProvider.GetRequiredService(); + var isHealthForMailService = await emailService.CheckServiceStatusAsync(); + + if (!isHealthForMailService) + { + _logger.LogWarning("邮件服务不可用,跳过发送过期提醒邮件的步骤。"); + } + // 获取配置的提前提醒天数 var notifyDays = _configuration.GetValue("ExpirationSettings:NotifyDaysBefore", 3); var currentDate = DateOnly.FromDateTime(DateTime.Now.Date); @@ -73,7 +80,7 @@ namespace EOM.TSHotelManagement.Common var helper = new EnumHelper(); var channelDescription = helper.GetDescriptionByName(item.ReservationChannel); - + var mailTemplate = EmailTemplate.SendReservationExpirationNotificationTemplate( item.ReservationRoomNumber, channelDescription ?? "我店", @@ -83,13 +90,16 @@ namespace EOM.TSHotelManagement.Common daysLeft ); - emailService.SendMail( - null, // To-do: Add recipient email address - mailTemplate.Subject, - mailTemplate.Body - ); + if (isHealthForMailService) + { + emailService.SendMail( + null, // To-do: Add recipient email address + mailTemplate.Subject, + mailTemplate.Body + ); + } - if (shouldDeleteReservations.Any() && shouldReleaseRooms.Any()) + if (shouldDeleteReservations.Any() && shouldReleaseRooms.Any()) { db.Updateable() .SetColumns(r => new Room { RoomStateId = (int)RoomState.Vacant }) diff --git a/EOM.TSHotelManagement.Common/QuartzWorkspace/Mail/MailServiceCheckJob.cs b/EOM.TSHotelManagement.Common/QuartzWorkspace/Mail/MailServiceCheckJob.cs new file mode 100644 index 0000000000000000000000000000000000000000..91e10904be390c4ce7a5c892b613ace663a92396 --- /dev/null +++ b/EOM.TSHotelManagement.Common/QuartzWorkspace/Mail/MailServiceCheckJob.cs @@ -0,0 +1,51 @@ +using EOM.TSHotelManagement.Domain; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Quartz; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Common +{ + [DisallowConcurrentExecution] + public class MailServiceCheckJob : IJob + { + private readonly ILogger _logger; + private readonly IServiceProvider _serviceProvider; + private readonly IConfiguration _configuration; + + public MailServiceCheckJob( + ILogger logger, + IServiceProvider serviceProvider, + IConfiguration configuration) + { + _logger = logger; + _serviceProvider = serviceProvider; + _configuration = configuration; + } + + public async Task Execute(IJobExecutionContext context) + { + _logger.LogInformation("开始检测邮件服务状态..."); + + using var scope = _serviceProvider.CreateScope(); + var emailService = scope.ServiceProvider.GetRequiredService(); + + bool isHealthy = false; + try + { + isHealthy = await emailService.CheckServiceStatusAsync(); + } + catch (Exception ex) + { + _logger.LogError(ex, "邮件服务检测异常"); + } + + _logger.LogInformation($"邮件服务检测完成,状态:{(isHealthy ? "健康" : "故障")}"); + } + + } +} diff --git a/EOM.TSHotelManagement.Common/QuartzWorkspace/Redis/RedisServiceCheckJob.cs b/EOM.TSHotelManagement.Common/QuartzWorkspace/Redis/RedisServiceCheckJob.cs new file mode 100644 index 0000000000000000000000000000000000000000..1257fcac544709ff90d3bbbc81e3c792bd9f9df1 --- /dev/null +++ b/EOM.TSHotelManagement.Common/QuartzWorkspace/Redis/RedisServiceCheckJob.cs @@ -0,0 +1,49 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Quartz; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Common +{ + [DisallowConcurrentExecution] + public class RedisServiceCheckJob : IJob + { + private readonly ILogger _logger; + private readonly IServiceProvider _serviceProvider; + private readonly IConfiguration _configuration; + + public RedisServiceCheckJob( + ILogger logger, + IServiceProvider serviceProvider, + IConfiguration configuration) + { + _logger = logger; + _serviceProvider = serviceProvider; + _configuration = configuration; + } + + public async Task Execute(IJobExecutionContext context) + { + _logger.LogInformation("开始检测Redis服务状态..."); + + using var scope = _serviceProvider.CreateScope(); + var redisHelper = scope.ServiceProvider.GetRequiredService(); + + bool isHealthy = false; + try + { + isHealthy = await redisHelper.CheckServiceStatusAsync(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Redis服务检测异常"); + } + + _logger.LogInformation($"Redis服务检测完成,状态:{(isHealthy ? "健康" : "故障")}"); + } + + } +} diff --git a/EOM.TSHotelManagement.Infrastructure/Config/RedisConfig.cs b/EOM.TSHotelManagement.Infrastructure/Config/RedisConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..c4e27a12f44f66eac9c3ceb439ca798ec55ff0cd --- /dev/null +++ b/EOM.TSHotelManagement.Infrastructure/Config/RedisConfig.cs @@ -0,0 +1,8 @@ +namespace EOM.TSHotelManagement.Infrastructure +{ + public class RedisConfig + { + public string ConnectionString { get; set; } + public bool Enable { get; set; } + } +} diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/IJwtConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/IJwtConfigFactory.cs deleted file mode 100644 index 3f8a5e407309ba8b5a853b4d90223d8676ae8ca8..0000000000000000000000000000000000000000 --- a/EOM.TSHotelManagement.Infrastructure/Factory/IJwtConfigFactory.cs +++ /dev/null @@ -1,8 +0,0 @@ - -namespace EOM.TSHotelManagement.Infrastructure -{ - public interface IJwtConfigFactory - { - JwtConfig GetJwtConfig(); - } -} diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/ILskyConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/ILskyConfigFactory.cs deleted file mode 100644 index ad3b7ee528425db75673caf2832e351dec0305ab..0000000000000000000000000000000000000000 --- a/EOM.TSHotelManagement.Infrastructure/Factory/ILskyConfigFactory.cs +++ /dev/null @@ -1,8 +0,0 @@ - -namespace EOM.TSHotelManagement.Infrastructure -{ - public interface ILskyConfigFactory - { - LskyConfig GetLskyConfig(); - } -} diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/IMailConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/IMailConfigFactory.cs deleted file mode 100644 index 0a441ff9207f846cdc36de05794b60b22b460c8f..0000000000000000000000000000000000000000 --- a/EOM.TSHotelManagement.Infrastructure/Factory/IMailConfigFactory.cs +++ /dev/null @@ -1,8 +0,0 @@ - -namespace EOM.TSHotelManagement.Infrastructure -{ - public interface IMailConfigFactory - { - MailConfig GetMailConfig(); - } -} diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/JwtConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/JwtConfigFactory.cs index 451ed40b0e70f0e292d193c8a1f4a9543c555b6d..216268add7e014947d21afa451e5087f1c423295 100644 --- a/EOM.TSHotelManagement.Infrastructure/Factory/JwtConfigFactory.cs +++ b/EOM.TSHotelManagement.Infrastructure/Factory/JwtConfigFactory.cs @@ -2,7 +2,7 @@ namespace EOM.TSHotelManagement.Infrastructure { - public class JwtConfigFactory : IJwtConfigFactory + public class JwtConfigFactory { private readonly IConfiguration _configuration; diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/LskyConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/LskyConfigFactory.cs index 08fb4c6ffe517d0276468c4ae04ffea02a6d9bae..f36a3d5d97b2eab4084736eca908b7bebe70cd1d 100644 --- a/EOM.TSHotelManagement.Infrastructure/Factory/LskyConfigFactory.cs +++ b/EOM.TSHotelManagement.Infrastructure/Factory/LskyConfigFactory.cs @@ -2,7 +2,7 @@ namespace EOM.TSHotelManagement.Infrastructure { - public class LskyConfigFactory : ILskyConfigFactory + public class LskyConfigFactory { private readonly IConfiguration _configuration; diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/MailConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/MailConfigFactory.cs index 56a0c94dd4ae94803a8a5363cd446e6821b5ab83..63a8bef3abff09d8e55e0e66765397c6bfd96597 100644 --- a/EOM.TSHotelManagement.Infrastructure/Factory/MailConfigFactory.cs +++ b/EOM.TSHotelManagement.Infrastructure/Factory/MailConfigFactory.cs @@ -2,7 +2,7 @@ namespace EOM.TSHotelManagement.Infrastructure { - public class MailConfigFactory : IMailConfigFactory + public class MailConfigFactory { private readonly IConfiguration _configuration; diff --git a/EOM.TSHotelManagement.Infrastructure/Factory/RedisConfigFactory.cs b/EOM.TSHotelManagement.Infrastructure/Factory/RedisConfigFactory.cs new file mode 100644 index 0000000000000000000000000000000000000000..415087eedb3958bea489b16aec96fbf7a19767c8 --- /dev/null +++ b/EOM.TSHotelManagement.Infrastructure/Factory/RedisConfigFactory.cs @@ -0,0 +1,28 @@ +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EOM.TSHotelManagement.Infrastructure +{ + public class RedisConfigFactory + { + private readonly IConfiguration _configuration; + + public RedisConfigFactory(IConfiguration configuration) + { + _configuration = configuration; + } + + public RedisConfig GetRedisConfig() + { + var redisSection = _configuration.GetSection("Redis"); + var redisConfig = new RedisConfig + { + ConnectionString = redisSection.GetValue("ConnectionString"), + Enable = redisSection.GetValue("Enable") + }; + return redisConfig; + } + } +}