添加命令行参数支持和未处理异常提示
This commit is contained in:
parent
db1b7bbb7d
commit
510c70cb83
10 changed files with 281 additions and 168 deletions
|
@ -69,7 +69,10 @@ namespace iFileProxy.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
var databaseHelper = serviceProvider.GetRequiredService<DatabaseGateService>();
|
var databaseHelper = serviceProvider.GetRequiredService<DatabaseGateService>();
|
||||||
databaseHelper.TestDbConfig();
|
if (databaseHelper.TestDbConfig())
|
||||||
|
{
|
||||||
|
_logger.Information("数据库配置验证成功.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -120,40 +123,40 @@ namespace iFileProxy.Config
|
||||||
public partial class Common
|
public partial class Common
|
||||||
{
|
{
|
||||||
[JsonPropertyName("Host")]
|
[JsonPropertyName("Host")]
|
||||||
public string Host { get; set; }
|
public string Host { get; set; } = string.Empty;
|
||||||
|
|
||||||
[JsonPropertyName("Port")]
|
[JsonPropertyName("Port")]
|
||||||
public int Port { get; set; } = 3306;
|
public uint Port { get; set; } = 3306;
|
||||||
|
|
||||||
[JsonPropertyName("User")]
|
[JsonPropertyName("User")]
|
||||||
public string User { get; set; }
|
public string User { get; set; } = string.Empty;
|
||||||
|
|
||||||
[JsonPropertyName("Password")]
|
[JsonPropertyName("Password")]
|
||||||
public string Password { get; set; }
|
public string Password { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
public partial class DB
|
public partial class DB
|
||||||
{
|
{
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
[JsonPropertyName("Host")]
|
[JsonPropertyName("Host")]
|
||||||
public string Host { get; set; }
|
public string? Host { get; set; }
|
||||||
|
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
[JsonPropertyName("Port")]
|
[JsonPropertyName("Port")]
|
||||||
public long? Port { get; set; } = 3306;
|
public uint? Port { get; set; } = null;
|
||||||
|
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
[JsonPropertyName("User")]
|
[JsonPropertyName("User")]
|
||||||
public string User { get; set; }
|
public string? User { get; set; }
|
||||||
|
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
[JsonPropertyName("Password")]
|
[JsonPropertyName("Password")]
|
||||||
public string Password { get; set; }
|
public string? Password { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("DatabaseName")]
|
[JsonPropertyName("DatabaseName")]
|
||||||
public string DatabaseName { get; set; }
|
public string? DatabaseName { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("Description")]
|
[JsonPropertyName("Description")]
|
||||||
public string Description { get; set; }
|
public string? Description { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StreamProxyOptions
|
public class StreamProxyOptions
|
||||||
|
|
37
src/Handlers/CmdArgsHandler.cs
Normal file
37
src/Handlers/CmdArgsHandler.cs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
using iFileProxy.Config;
|
||||||
|
using iFileProxy.Helpers;
|
||||||
|
using iFileProxy.Services;
|
||||||
|
namespace iFileProxy.Handlers
|
||||||
|
{
|
||||||
|
public class CmdArgsHandler
|
||||||
|
{
|
||||||
|
public static void ParseArgs(string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length == 0)
|
||||||
|
return;
|
||||||
|
Dictionary<string, string> helpStrings = [];
|
||||||
|
helpStrings.Add("--init-db", "初始化数据库");
|
||||||
|
helpStrings.Add("--dev-logger", "启用开发者logger");
|
||||||
|
helpStrings.Add("--disable-startup-check", "禁用启动时程序配置自检");
|
||||||
|
helpStrings.Add("--url=<Url>", "设置程序app.run() Url 如: http://0.0.0.0:1145");
|
||||||
|
|
||||||
|
if (args.Contains("-h") || args.Contains("--help"))
|
||||||
|
{
|
||||||
|
Console.WriteLine("命令行参数帮助: ");
|
||||||
|
foreach (var hs in helpStrings)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\t{hs.Key}\t{hs.Value}");
|
||||||
|
}
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandLineArgsHelper cmdlineHelper = new(args);
|
||||||
|
|
||||||
|
if (cmdlineHelper.GetBooleanValue("--init-db"))
|
||||||
|
{
|
||||||
|
DatabaseGateService databaseGateService = new(AppConfig.GetCurrConfig());
|
||||||
|
databaseGateService.TryInitialDB();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
src/Helpers/CommandLineArgsHelper.cs
Normal file
51
src/Helpers/CommandLineArgsHelper.cs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace iFileProxy.Helpers
|
||||||
|
{
|
||||||
|
|
||||||
|
public class CommandLineArgsHelper(string[] args)
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, string> _parameters = ParseArgs(args);
|
||||||
|
|
||||||
|
// 解析命令行参数
|
||||||
|
private static Dictionary<string, string> ParseArgs(string[] args)
|
||||||
|
{
|
||||||
|
var parameters = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
for (int i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
var arg = args[i];
|
||||||
|
|
||||||
|
// 如果参数是键值对形式
|
||||||
|
if (arg.Contains('='))
|
||||||
|
{
|
||||||
|
var parts = arg.Split(['='], 2);
|
||||||
|
if (parts.Length == 2)
|
||||||
|
{
|
||||||
|
parameters[parts[0].TrimStart('-')] = parts[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 如果参数是没有值的标志性参数(比如 --dev-logger)
|
||||||
|
parameters[arg.TrimStart('-')] = "true";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取指定参数的值,若无值则返回null
|
||||||
|
public string? GetStringValue(string key)
|
||||||
|
{
|
||||||
|
return _parameters.ContainsKey(key) ? _parameters[key] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取指定参数的布尔值,若参数值是 "true" 则返回true,否则返回false
|
||||||
|
public bool GetBooleanValue(string key)
|
||||||
|
{
|
||||||
|
return _parameters.ContainsKey(key) && _parameters[key].Equals("true", StringComparison.CurrentCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,17 +24,13 @@ namespace iFileProxy.Middleware
|
||||||
await _next(context);
|
await _next(context);
|
||||||
if (context.Response.HasStarted)
|
if (context.Response.HasStarted)
|
||||||
{
|
{
|
||||||
_logger.Debug($"响应已经开始 错误处理中间件无法再修改其响应内容");
|
_logger.Debug($"响应已经开始,无法再修改其响应内容");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (context.Response.StatusCode == 404)
|
if (context.Response.StatusCode == 404)
|
||||||
{
|
{
|
||||||
context.Response.OnStarting(async () =>
|
context.Response.ContentType = "application/json";
|
||||||
{
|
await context.Response.WriteAsync(JsonSerializer.Serialize(new CommonRsp { Retcode = 404, Message = "你正在请求的资源不存在!" }));
|
||||||
context.Response.ContentType = "application/json";
|
|
||||||
await context.Response.WriteAsync(JsonSerializer.Serialize(new CommonRsp { Retcode = 404, Message = "你正在请求的资源不存在!" }));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -46,7 +42,7 @@ namespace iFileProxy.Middleware
|
||||||
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
|
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
|
||||||
{
|
{
|
||||||
var code = HttpStatusCode.InternalServerError; // 500 if unexpected
|
var code = HttpStatusCode.InternalServerError; // 500 if unexpected
|
||||||
_logger.Fatal("崩溃数据: {exception}\n上下文信息: {context}", exception, JsonSerializer.Serialize(MasterHelper.ExtractDebugInfo(context)));
|
_logger.Error("崩溃数据: {exception}\n上下文信息: {context}", exception, JsonSerializer.Serialize(MasterHelper.ExtractDebugInfo(context)));
|
||||||
switch (exception)
|
switch (exception)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,9 +14,9 @@ namespace iFileProxy.Middleware
|
||||||
|
|
||||||
public async Task InvokeAsync(HttpContext context)
|
public async Task InvokeAsync(HttpContext context)
|
||||||
{
|
{
|
||||||
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
|
var token = context.Request.Headers.Authorization.FirstOrDefault()?.Split(" ").Last();
|
||||||
var fingerprint = context.Request.Headers["X-Device-Fingerprint"].FirstOrDefault();
|
var fingerprint = context.Request.Headers["X-Device-Fingerprint"].FirstOrDefault();
|
||||||
var userAgent = context.Request.Headers["User-Agent"].FirstOrDefault();
|
var userAgent = context.Request.Headers.UserAgent.FirstOrDefault();
|
||||||
var ip = MasterHelper.GetClientIPAddr(context);
|
var ip = MasterHelper.GetClientIPAddr(context);
|
||||||
|
|
||||||
if (token != null)
|
if (token != null)
|
|
@ -1,12 +1,13 @@
|
||||||
using iFileProxy.Config;
|
using iFileProxy.Config;
|
||||||
using iFileProxy.Middleware;
|
using iFileProxy.Middleware;
|
||||||
using iFileProxy.Helpers;
|
using iFileProxy.Helpers;
|
||||||
|
using iFileProxy.Handlers;
|
||||||
using iFileProxy.Services;
|
using iFileProxy.Services;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Diagnostics;
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
namespace iFileProxy
|
namespace iFileProxy
|
||||||
{
|
{
|
||||||
|
@ -14,11 +15,16 @@ namespace iFileProxy
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
SerilogConfig.CreateLogger();
|
// 绑定异常捕获事件
|
||||||
Serilog.ILogger logger = Log.Logger.ForContext<Program>();
|
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||||
|
SerilogConfig.CreateLogger(args: args);
|
||||||
|
|
||||||
|
CommandLineArgsHelper argsHelper = new (args);
|
||||||
|
|
||||||
Console.Write(" "); // 补全日志第一行开头的空白
|
Console.Write(" "); // 补全日志第一行开头的空白
|
||||||
|
|
||||||
|
CmdArgsHandler.ParseArgs(args);
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// CORS配置
|
// CORS配置
|
||||||
|
@ -73,6 +79,10 @@ namespace iFileProxy
|
||||||
// 初始化缓存管理服务
|
// 初始化缓存管理服务
|
||||||
LocalCacheManager localCacheManager = new(app.Services);
|
LocalCacheManager localCacheManager = new(app.Services);
|
||||||
|
|
||||||
|
if (!argsHelper.GetBooleanValue("disable-startup-check"))
|
||||||
|
// 初始化验证配置文件
|
||||||
|
AppConfig.CheckAppConfig(app.Services);
|
||||||
|
|
||||||
// 1. 错误处理(放在请求管道的最前面)
|
// 1. 错误处理(放在请求管道的最前面)
|
||||||
app.UseMiddleware<ErrorHandlerMiddleware>();
|
app.UseMiddleware<ErrorHandlerMiddleware>();
|
||||||
|
|
||||||
|
@ -118,9 +128,45 @@ namespace iFileProxy
|
||||||
|
|
||||||
// 11. 启动应用
|
// 11. 启动应用
|
||||||
var dbGateService = app.Services.GetRequiredService<DatabaseGateService>();
|
var dbGateService = app.Services.GetRequiredService<DatabaseGateService>();
|
||||||
SerilogConfig.CreateLogger(dbGateService);
|
SerilogConfig.CreateLogger(dbGateService,args);
|
||||||
|
|
||||||
app.Run();
|
if (!argsHelper.GetStringValue("url").IsNullOrEmpty())
|
||||||
|
app.Run(argsHelper.GetStringValue("url"));
|
||||||
|
else
|
||||||
|
app.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
|
{
|
||||||
|
var logger = Log.ForContext<AppDomain>();
|
||||||
|
Exception exc = (Exception)e.ExceptionObject;
|
||||||
|
|
||||||
|
// 直接记录原始异常信息,不重新抛出
|
||||||
|
if (exc is MySqlException mySqlEx)
|
||||||
|
{
|
||||||
|
if (mySqlEx.Message.Contains("is not allowed to connect to this MySQL server", StringComparison.CurrentCulture))
|
||||||
|
{
|
||||||
|
logger.Fatal( "远程主机不允许你连接到该数据库, 请检查数据库服务端是否将本机IP加白! ");
|
||||||
|
}
|
||||||
|
else if (mySqlEx.Message.Contains("Unable to connect to any of the specified MySQL hosts"))
|
||||||
|
{
|
||||||
|
logger.Fatal("无法连接到远程数据库, 因为远程主机不可达, 请检查你的网络或数据库配置!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (exc is IOException ioEx)
|
||||||
|
{
|
||||||
|
if (ioEx.Message.Contains("address already in use."))
|
||||||
|
{
|
||||||
|
logger.Fatal("程序服务端口被占用!!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录所有未处理的异常信息
|
||||||
|
logger.Fatal(exc, "未处理的异常: {ExceptionMessage}", exc.Message);
|
||||||
|
|
||||||
|
// 优雅退出应用程序
|
||||||
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,29 +6,34 @@
|
||||||
using iFileProxy.Sinks;
|
using iFileProxy.Sinks;
|
||||||
using iFileProxy.Services;
|
using iFileProxy.Services;
|
||||||
using ZstdSharp.Unsafe;
|
using ZstdSharp.Unsafe;
|
||||||
|
using iFileProxy.Helpers;
|
||||||
|
|
||||||
public static class SerilogConfig
|
public static class SerilogConfig
|
||||||
{
|
{
|
||||||
private static DatabaseGateService? _dbGateService;
|
private static DatabaseGateService? _dbGateService;
|
||||||
|
|
||||||
public static void CreateLogger(DatabaseGateService? dbGateService = null)
|
public static void CreateLogger(DatabaseGateService? dbGateService = null, string[]? args = null)
|
||||||
{
|
{
|
||||||
_dbGateService = dbGateService; // 保存实例以供后续使用
|
_dbGateService = dbGateService; // 保存实例以供后续使用
|
||||||
var baseLogPath = Path.Combine(AppContext.BaseDirectory, "logs");
|
var baseLogPath = Path.Combine(AppContext.BaseDirectory, "logs");
|
||||||
var appName = AppDomain.CurrentDomain.FriendlyName;
|
var appName = AppDomain.CurrentDomain.FriendlyName;
|
||||||
|
|
||||||
// 确保日志目录存在
|
// 确保日志目录存在
|
||||||
if (!Directory.Exists(baseLogPath))
|
if (!Directory.Exists(baseLogPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(baseLogPath);
|
Directory.CreateDirectory(baseLogPath);
|
||||||
}
|
}
|
||||||
|
var loggerConfiguration = new LoggerConfiguration();
|
||||||
|
|
||||||
var loggerConfiguration = new LoggerConfiguration()
|
|
||||||
#if RELEASE
|
if (new CommandLineArgsHelper(args).GetBooleanValue("dev-logger"))
|
||||||
.MinimumLevel.Information()
|
{
|
||||||
#else
|
loggerConfiguration.MinimumLevel.Debug();
|
||||||
.MinimumLevel.Debug()
|
}
|
||||||
#endif
|
else
|
||||||
|
loggerConfiguration.MinimumLevel.Information();
|
||||||
|
|
||||||
|
loggerConfiguration
|
||||||
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
|
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
|
||||||
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
|
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
|
||||||
.Enrich.FromLogContext()
|
.Enrich.FromLogContext()
|
||||||
|
@ -43,7 +48,7 @@
|
||||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] {ClientIp} {Message:lj} {contentType} {queryString}{NewLine}{Exception}",
|
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] {ClientIp} {Message:lj} {contentType} {queryString}{NewLine}{Exception}",
|
||||||
rollingInterval: RollingInterval.Day,
|
rollingInterval: RollingInterval.Day,
|
||||||
fileSizeLimitBytes: 1073741824)) // 1GB
|
fileSizeLimitBytes: 1073741824)) // 1GB
|
||||||
// 警告日志写入单独的文件
|
// 警告日志写入单独的文件
|
||||||
.WriteTo.Logger(lc => lc
|
.WriteTo.Logger(lc => lc
|
||||||
.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Warning)
|
.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Warning)
|
||||||
.WriteTo.File(
|
.WriteTo.File(
|
||||||
|
@ -69,6 +74,7 @@
|
||||||
fileSizeLimitBytes: 1073741824))
|
fileSizeLimitBytes: 1073741824))
|
||||||
.Enrich.WithProperty("node_ip", GetIpAddress());
|
.Enrich.WithProperty("node_ip", GetIpAddress());
|
||||||
|
|
||||||
|
|
||||||
// 只有在提供了 DatabaseGateService 时才添加数据库 Sink
|
// 只有在提供了 DatabaseGateService 时才添加数据库 Sink
|
||||||
if (_dbGateService != null)
|
if (_dbGateService != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,77 +18,13 @@ namespace iFileProxy.Services
|
||||||
|
|
||||||
Dictionary<string, DB> _dbDictionary = [];
|
Dictionary<string, DB> _dbDictionary = [];
|
||||||
|
|
||||||
private const string CREATE_TASKS_TABLE_SQL = """
|
private Dictionary<string, string> createDBSqls = new Dictionary<string, string> {
|
||||||
CREATE TABLE IF NOT EXISTS `t_tasks_info` (
|
{ "任务信息",@"CREATE TABLE `t_tasks_info` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增键', `tid` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务id', `file_name` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文件名', `client_ip` varchar(46) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户端IP', `add_time` datetime NOT NULL COMMENT '任务在何时被添加', `update_time` datetime NOT NULL COMMENT '任务状态更新时间', `status` int(1) NULL DEFAULT NULL COMMENT '任务状态', `url` varchar(8192) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件url', `size` bigint(32) NULL DEFAULT NULL COMMENT '文件大小', `hash` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件hash', `tag` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标记', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `tid`(`tid`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 139915 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;"},
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增键',
|
{ "用户", @"CREATE TABLE `t_users` ( `user_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '昵称', `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '电子邮箱', `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名', `password_hash` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码哈希值', `mask` int(11) NOT NULL DEFAULT 0 COMMENT '权限掩码', `state` int(11) NOT NULL DEFAULT 0 COMMENT '状态', `create_time` datetime NOT NULL COMMENT '账号创建时间', `last_login_time` datetime NULL DEFAULT NULL COMMENT '上次登录时间', `last_login_ip` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '上次登录IP', PRIMARY KEY (`user_id`) USING BTREE, UNIQUE INDEX `username`(`username`) USING BTREE, UNIQUE INDEX `email`(`email`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;"},
|
||||||
`tid` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务id',
|
{ "用户事件", @"CREATE TABLE `t_user_events` ( `event_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `user_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `event_type` int(11) NOT NULL, `event_time` datetime NOT NULL, `event_ip` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `event_detail` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, PRIMARY KEY (`event_id`) USING BTREE, INDEX `user_id`(`user_id`) USING BTREE, CONSTRAINT `t_user_events_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `t_users` (`user_id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;"},
|
||||||
`file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
{ "系统日志", @"CREATE TABLE `t_system_logs` ( `log_id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `level` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `message` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `exception` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL, `properties` json NULL, `timestamp` datetime NOT NULL, PRIMARY KEY (`log_id`) USING BTREE, INDEX `idx_timestamp`(`timestamp`) USING BTREE, INDEX `idx_level`(`level`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;" },
|
||||||
`client_ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户端IP',
|
{"下载历史",@"CREATE TABLE `t_download_history` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `tid` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务UUID', `time` datetime NULL DEFAULT NULL COMMENT '触发时间', `client_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户端IP', PRIMARY KEY (`id`) USING BTREE, INDEX `tid`(`tid`) USING BTREE, CONSTRAINT `t_download_history_ibfk_1` FOREIGN KEY (`tid`) REFERENCES `t_tasks_info` (`tid`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE = InnoDB AUTO_INCREMENT = 532 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;" }
|
||||||
`add_time` datetime NOT NULL COMMENT '任务在何时被添加',
|
};
|
||||||
`update_time` datetime NOT NULL COMMENT '任务状态更新时间',
|
|
||||||
`status` int(11) NULL DEFAULT NULL COMMENT '任务状态',
|
|
||||||
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件url',
|
|
||||||
`size` int(11) NULL DEFAULT NULL COMMENT '文件大小',
|
|
||||||
`hash` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件hash',
|
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
|
||||||
""";
|
|
||||||
|
|
||||||
private const string CREATE_USERS_TABLE_SQL = """
|
|
||||||
CREATE TABLE IF NOT EXISTS `t_users` (
|
|
||||||
`user_id` varchar(36) NOT NULL,
|
|
||||||
`username` varchar(50) NOT NULL,
|
|
||||||
`nickname` varchar(50) NOT NULL,
|
|
||||||
`email` varchar(100) NOT NULL,
|
|
||||||
`password_hash` varchar(255) NOT NULL,
|
|
||||||
`mask` int NOT NULL DEFAULT 0,
|
|
||||||
`state` int NOT NULL DEFAULT 0,
|
|
||||||
`create_time` datetime NOT NULL,
|
|
||||||
`last_login_time` datetime NULL,
|
|
||||||
`last_login_ip` varchar(45) NULL,
|
|
||||||
PRIMARY KEY (`user_id`),
|
|
||||||
UNIQUE KEY `username` (`username`),
|
|
||||||
UNIQUE KEY `email` (`email`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
""";
|
|
||||||
|
|
||||||
private const string CREATE_USER_EVENTS_TABLE_SQL = """
|
|
||||||
CREATE TABLE IF NOT EXISTS `t_user_events` (
|
|
||||||
`event_id` varchar(36) NOT NULL,
|
|
||||||
`user_id` varchar(36) NOT NULL,
|
|
||||||
`event_type` int NOT NULL,
|
|
||||||
`event_time` datetime NOT NULL,
|
|
||||||
`event_ip` varchar(45) NULL,
|
|
||||||
`event_detail` text NULL,
|
|
||||||
PRIMARY KEY (`event_id`),
|
|
||||||
KEY `user_id` (`user_id`),
|
|
||||||
CONSTRAINT `fk_user_events_user` FOREIGN KEY (`user_id`) REFERENCES `t_users` (`user_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
""";
|
|
||||||
|
|
||||||
private const string CREATE_SYSTEM_LOGS_TABLE_SQL = """
|
|
||||||
CREATE TABLE IF NOT EXISTS `t_system_logs` (
|
|
||||||
`log_id` varchar(36) NOT NULL,
|
|
||||||
`level` varchar(20) NOT NULL,
|
|
||||||
`message` text NOT NULL,
|
|
||||||
`exception` text,
|
|
||||||
`properties` json,
|
|
||||||
`timestamp` datetime NOT NULL,
|
|
||||||
PRIMARY KEY (`log_id`),
|
|
||||||
KEY `idx_timestamp` (`timestamp`),
|
|
||||||
KEY `idx_level` (`level`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
""";
|
|
||||||
|
|
||||||
private const string CREATE_DOWNLOAD_HISTORY_TABLE_SQL = """
|
|
||||||
CREATE TABLE IF NOT EXISTS `t_download_history` (
|
|
||||||
`tid` varchar(48) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务UUID',
|
|
||||||
`time` datetime NULL DEFAULT NULL COMMENT '触发时间',
|
|
||||||
`client_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户端IP',
|
|
||||||
PRIMARY KEY (`tid`) USING BTREE,
|
|
||||||
CONSTRAINT `t_download_history_ibfk_1` FOREIGN KEY (`tid`) REFERENCES `t_tasks_info` (`tid`) ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
|
||||||
""";
|
|
||||||
|
|
||||||
public DatabaseGateService(AppConfig appConfig)
|
public DatabaseGateService(AppConfig appConfig)
|
||||||
{
|
{
|
||||||
|
@ -97,13 +33,13 @@ namespace iFileProxy.Services
|
||||||
_appConfig = appConfig;
|
_appConfig = appConfig;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
LoadDbDict();
|
||||||
_logger.Information("Done.");
|
_logger.Information("Done.");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Fatal($"程序异常: {e.Message}");
|
_logger.Fatal($"程序异常: {e.Message}");
|
||||||
}
|
}
|
||||||
LoadDbDict();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -154,7 +90,7 @@ namespace iFileProxy.Services
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var conn = new MySqlConnection(builder.ConnectionString);
|
var conn = new MySqlConnection(builder.ConnectionString);
|
||||||
conn.Open();
|
conn.Open();
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
@ -178,7 +114,7 @@ namespace iFileProxy.Services
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
_logger.Fatal($"=========== 数据库: {db.Key} 测试失败! ===========");
|
_logger.Fatal($"=========== 数据库: {db.Key} 测试失败! ===========");
|
||||||
return false;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -206,10 +142,10 @@ namespace iFileProxy.Services
|
||||||
/// <param name="sql"></param>
|
/// <param name="sql"></param>
|
||||||
/// <param name="conn"></param>
|
/// <param name="conn"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public string QueryTableData(string sql,string dbConfName)
|
public string QueryTableData(string sql, string dbConfName)
|
||||||
{
|
{
|
||||||
DataTable dataTable = new();
|
DataTable dataTable = new();
|
||||||
using (MySqlDataAdapter adapter = new(new MySqlCommand(sql,GetAndOpenDBConn(dbConfName))))
|
using (MySqlDataAdapter adapter = new(new MySqlCommand(sql, GetAndOpenDBConn(dbConfName))))
|
||||||
adapter.Fill(dataTable);
|
adapter.Fill(dataTable);
|
||||||
return JsonConvert.SerializeObject(dataTable);
|
return JsonConvert.SerializeObject(dataTable);
|
||||||
}
|
}
|
||||||
|
@ -221,8 +157,8 @@ namespace iFileProxy.Services
|
||||||
/// <param name="dbConfName">配置文件中的Description字段</param>
|
/// <param name="dbConfName">配置文件中的Description字段</param>
|
||||||
/// <returns>影响的行数</returns>
|
/// <returns>影响的行数</returns>
|
||||||
public int Query(string sql, string dbConfName)
|
public int Query(string sql, string dbConfName)
|
||||||
{
|
{
|
||||||
using MySqlCommand sqlCmd = new (sql, GetAndOpenDBConn(dbConfName));
|
using MySqlCommand sqlCmd = new(sql, GetAndOpenDBConn(dbConfName));
|
||||||
int n = sqlCmd.ExecuteNonQuery();
|
int n = sqlCmd.ExecuteNonQuery();
|
||||||
_logger.Debug($"查询完成, 受影响的行数: {n}");
|
_logger.Debug($"查询完成, 受影响的行数: {n}");
|
||||||
return n;
|
return n;
|
||||||
|
@ -242,7 +178,13 @@ namespace iFileProxy.Services
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TaskInfo> CheckCacheDependencies(string taskId,string ipAddr)
|
/// <summary>
|
||||||
|
/// 检查缓存依赖
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="taskId">任务ID</param>
|
||||||
|
/// <param name="ipAddr">排除的IP地址</param>
|
||||||
|
/// <returns>依赖任务信息列表</returns>
|
||||||
|
public List<TaskInfo> CheckCacheDependencies(string taskId, string ipAddr)
|
||||||
{
|
{
|
||||||
string sql = $"SELECT * FROM t_tasks_info WHERE `status` = @status AND `tag` = @tag AND `client_ip` <> @ip_addr";
|
string sql = $"SELECT * FROM t_tasks_info WHERE `status` = @status AND `tag` = @tag AND `client_ip` <> @ip_addr";
|
||||||
using MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
using MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||||
|
@ -253,7 +195,7 @@ namespace iFileProxy.Services
|
||||||
sqlCmd.Parameters.AddWithValue("@status", TaskState.Cached);
|
sqlCmd.Parameters.AddWithValue("@status", TaskState.Cached);
|
||||||
sqlCmd.Parameters.AddWithValue("@ip_addr", ipAddr);
|
sqlCmd.Parameters.AddWithValue("@ip_addr", ipAddr);
|
||||||
|
|
||||||
return JsonConvert.DeserializeObject<List<TaskInfo>>( QueryTableData(sqlCmd));
|
return JsonConvert.DeserializeObject<List<TaskInfo>>(QueryTableData(sqlCmd));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -271,7 +213,7 @@ namespace iFileProxy.Services
|
||||||
{
|
{
|
||||||
using MySqlCommand sqlCmd = new(sql, conn);
|
using MySqlCommand sqlCmd = new(sql, conn);
|
||||||
sqlCmd.Parameters.AddWithValue("@ip_addr", ipAddr);
|
sqlCmd.Parameters.AddWithValue("@ip_addr", ipAddr);
|
||||||
sqlCmd.Parameters.AddWithValue ("@status", status);
|
sqlCmd.Parameters.AddWithValue("@status", status);
|
||||||
return QueryTableData(sqlCmd);
|
return QueryTableData(sqlCmd);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -289,7 +231,7 @@ namespace iFileProxy.Services
|
||||||
using MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
using MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using MySqlCommand sqlCmd = new (sql,conn);
|
using MySqlCommand sqlCmd = new(sql, conn);
|
||||||
sqlCmd.Parameters.AddWithValue("@ip_addr", ipAddr);
|
sqlCmd.Parameters.AddWithValue("@ip_addr", ipAddr);
|
||||||
return QueryTableData(sqlCmd);
|
return QueryTableData(sqlCmd);
|
||||||
}
|
}
|
||||||
|
@ -322,7 +264,8 @@ namespace iFileProxy.Services
|
||||||
{
|
{
|
||||||
string sql = $"SELECT * FROM t_tasks_info WHERE url = @url AND size = @size AND `status` = @status AND file_name = @fileName";
|
string sql = $"SELECT * FROM t_tasks_info WHERE url = @url AND size = @size AND `status` = @status AND file_name = @fileName";
|
||||||
using MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
using MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
MySqlCommand sqlCmd = new MySqlCommand(sql, conn);
|
MySqlCommand sqlCmd = new MySqlCommand(sql, conn);
|
||||||
sqlCmd.Parameters.AddWithValue("@url", url);
|
sqlCmd.Parameters.AddWithValue("@url", url);
|
||||||
sqlCmd.Parameters.AddWithValue("@size", size);
|
sqlCmd.Parameters.AddWithValue("@size", size);
|
||||||
|
@ -337,10 +280,12 @@ namespace iFileProxy.Services
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e)
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
finally {
|
finally
|
||||||
|
{
|
||||||
conn.Close();
|
conn.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,21 +325,21 @@ namespace iFileProxy.Services
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public bool UpdateFieldsData(string fieldsName, string taskUUID,object val)
|
public bool UpdateFieldsData(string fieldsName, string taskUUID, object val)
|
||||||
{
|
{
|
||||||
string sql = $"UPDATE t_tasks_info set `{fieldsName}` = @Data WHERE `tid` = @tid";
|
string sql = $"UPDATE t_tasks_info set `{fieldsName}` = @Data WHERE `tid` = @tid";
|
||||||
using MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
using MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using MySqlCommand sqlCmd = new(sql, conn);
|
using MySqlCommand sqlCmd = new(sql, conn);
|
||||||
sqlCmd.Parameters.AddWithValue("@Data",val);
|
sqlCmd.Parameters.AddWithValue("@Data", val);
|
||||||
sqlCmd.Parameters.AddWithValue("@tid",taskUUID);
|
sqlCmd.Parameters.AddWithValue("@tid", taskUUID);
|
||||||
if (sqlCmd.ExecuteNonQuery() == 1)
|
if (sqlCmd.ExecuteNonQuery() == 1)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
@ -412,15 +357,15 @@ namespace iFileProxy.Services
|
||||||
{
|
{
|
||||||
string sql = @"UPDATE t_tasks_info set `status` = @status , update_time = Now() WHERE `tid` = @tid";
|
string sql = @"UPDATE t_tasks_info set `status` = @status , update_time = Now() WHERE `tid` = @tid";
|
||||||
MySqlConnection conn = connection ?? GetAndOpenDBConn("iFileProxy_Db");
|
MySqlConnection conn = connection ?? GetAndOpenDBConn("iFileProxy_Db");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using MySqlCommand sqlCmd = new (sql, conn);
|
using MySqlCommand sqlCmd = new(sql, conn);
|
||||||
sqlCmd.Parameters.AddWithValue("@status", taskInfo.Status);
|
sqlCmd.Parameters.AddWithValue("@status", taskInfo.Status);
|
||||||
sqlCmd.Parameters.AddWithValue("@tid", taskInfo.TaskId);
|
sqlCmd.Parameters.AddWithValue("@tid", taskInfo.TaskId);
|
||||||
if (sqlCmd.ExecuteNonQuery() >= 1)
|
if (sqlCmd.ExecuteNonQuery() >= 1)
|
||||||
{
|
{
|
||||||
_logger.Information($"Task: {taskInfo.TaskId} Status Change to {taskInfo.Status}");
|
_logger.Information($"Task: {taskInfo.TaskId} Status Change to {taskInfo.Status}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -433,8 +378,8 @@ namespace iFileProxy.Services
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
conn.Close ();
|
conn.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,11 +394,11 @@ namespace iFileProxy.Services
|
||||||
/// <param name="c"></param>
|
/// <param name="c"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public int DeleteTaskInfoByIpAddr(string ipAddr)
|
public int DeleteTaskInfoByIpAddr(string ipAddr)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string sql = $"DELETE FROM `t_tasks_info` WHERE `client_ip` = '{ipAddr}'";
|
string sql = $"DELETE FROM `t_tasks_info` WHERE `client_ip` = '{ipAddr}'";
|
||||||
return Query(sql,DbConfigName.iFileProxy);
|
return Query(sql, DbConfigName.iFileProxy);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
@ -466,13 +411,13 @@ namespace iFileProxy.Services
|
||||||
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 创建表
|
foreach (var sql in createDBSqls)
|
||||||
using (var cmd = new MySqlCommand(CREATE_TASKS_TABLE_SQL, conn))
|
{
|
||||||
cmd.ExecuteNonQuery();
|
_logger.Information($"尝试创建 {sql.Key} 数据表....");
|
||||||
using (var cmd = new MySqlCommand(CREATE_USERS_TABLE_SQL, conn))
|
using MySqlCommand sqlcmd = new (sql.Value,conn);
|
||||||
cmd.ExecuteNonQuery();
|
sqlcmd.ExecuteNonQuery();
|
||||||
using (var cmd = new MySqlCommand(CREATE_USER_EVENTS_TABLE_SQL, conn))
|
_logger.Information("Done.");
|
||||||
cmd.ExecuteNonQuery();
|
}
|
||||||
|
|
||||||
_logger.Information("数据库表结构初始化完成");
|
_logger.Information("数据库表结构初始化完成");
|
||||||
}
|
}
|
||||||
|
@ -482,6 +427,13 @@ namespace iFileProxy.Services
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 执行查询并获取单个指定类型的对象
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="sql"></param>
|
||||||
|
/// <param name="parameters"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public T ExecuteScalar<T>(string sql, Dictionary<string, object> parameters)
|
public T ExecuteScalar<T>(string sql, Dictionary<string, object> parameters)
|
||||||
{
|
{
|
||||||
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||||
|
@ -494,6 +446,13 @@ namespace iFileProxy.Services
|
||||||
return (T)cmd.ExecuteScalar();
|
return (T)cmd.ExecuteScalar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行SQL查询
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">预期返回的数据类型</typeparam>
|
||||||
|
/// <param name="sql">SQL语句</param>
|
||||||
|
/// <param name="parameters">参数列表</param>
|
||||||
|
/// <returns>所指定类型的数据</returns>
|
||||||
public List<T> ExecuteQuery<T>(string sql, Dictionary<string, object> parameters)
|
public List<T> ExecuteQuery<T>(string sql, Dictionary<string, object> parameters)
|
||||||
{
|
{
|
||||||
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||||
|
@ -505,6 +464,12 @@ namespace iFileProxy.Services
|
||||||
return JsonConvert.DeserializeObject<List<T>>(QueryTableData(cmd));
|
return JsonConvert.DeserializeObject<List<T>>(QueryTableData(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行SQL查询
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sql">SQL语句</param>
|
||||||
|
/// <param name="parameters">参数列表</param>
|
||||||
|
/// <returns>受影响的行数</returns>
|
||||||
public int ExecuteNonQuery(string sql, Dictionary<string, object> parameters)
|
public int ExecuteNonQuery(string sql, Dictionary<string, object> parameters)
|
||||||
{
|
{
|
||||||
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||||
|
@ -630,7 +595,7 @@ namespace iFileProxy.Services
|
||||||
""";
|
""";
|
||||||
|
|
||||||
var result = new Dictionary<TaskState, int>();
|
var result = new Dictionary<TaskState, int>();
|
||||||
|
|
||||||
// 初始化所有状态的计数为0
|
// 初始化所有状态的计数为0
|
||||||
foreach (TaskState state in Enum.GetValues(typeof(TaskState)))
|
foreach (TaskState state in Enum.GetValues(typeof(TaskState)))
|
||||||
{
|
{
|
||||||
|
@ -641,7 +606,7 @@ namespace iFileProxy.Services
|
||||||
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||||
using var cmd = new MySqlCommand(sql, conn);
|
using var cmd = new MySqlCommand(sql, conn);
|
||||||
using var reader = cmd.ExecuteReader();
|
using var reader = cmd.ExecuteReader();
|
||||||
|
|
||||||
while (reader.Read())
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
var status = (TaskState)reader.GetInt32("status");
|
var status = (TaskState)reader.GetInt32("status");
|
||||||
|
@ -686,7 +651,7 @@ namespace iFileProxy.Services
|
||||||
{
|
{
|
||||||
var sql = @"INSERT INTO t_users (user_id, username, password_hash, mask, state, create_time, last_login_time, last_login_ip, nickname, email)
|
var sql = @"INSERT INTO t_users (user_id, username, password_hash, mask, state, create_time, last_login_time, last_login_ip, nickname, email)
|
||||||
VALUES (@userId, @username, @passwordHash, @mask, @state, @createTime, @lastLoginTime, @lastLoginIp, @nickname, @email)";
|
VALUES (@userId, @username, @passwordHash, @mask, @state, @createTime, @lastLoginTime, @lastLoginIp, @nickname, @email)";
|
||||||
|
|
||||||
var parameters = new Dictionary<string, object>
|
var parameters = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "@userId", user.UserId },
|
{ "@userId", user.UserId },
|
||||||
|
@ -709,7 +674,7 @@ namespace iFileProxy.Services
|
||||||
{
|
{
|
||||||
var sql = @"INSERT INTO t_user_events (event_id, user_id, event_type, event_time, event_ip, event_detail)
|
var sql = @"INSERT INTO t_user_events (event_id, user_id, event_type, event_time, event_ip, event_detail)
|
||||||
VALUES (@eventId, @userId, @eventType, @eventTime, @eventIp, @eventDetail)";
|
VALUES (@eventId, @userId, @eventType, @eventTime, @eventIp, @eventDetail)";
|
||||||
|
|
||||||
var parameters = new Dictionary<string, object>
|
var parameters = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "@eventId", userEvent.EventId },
|
{ "@eventId", userEvent.EventId },
|
||||||
|
@ -747,7 +712,7 @@ namespace iFileProxy.Services
|
||||||
last_login_ip = @lastLoginIp,
|
last_login_ip = @lastLoginIp,
|
||||||
nickname = @nickname
|
nickname = @nickname
|
||||||
WHERE user_id = @userId";
|
WHERE user_id = @userId";
|
||||||
|
|
||||||
var parameters = new Dictionary<string, object>
|
var parameters = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "@userId", user.UserId },
|
{ "@userId", user.UserId },
|
||||||
|
@ -852,9 +817,9 @@ namespace iFileProxy.Services
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PagedResult<UserEventDetail>> GetPagedUserEventsAsync(
|
public async Task<PagedResult<UserEventDetail>> GetPagedUserEventsAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
string? userId = null,
|
string? userId = null,
|
||||||
string? keyword = null)
|
string? keyword = null)
|
||||||
{
|
{
|
||||||
// 构建基础SQL
|
// 构建基础SQL
|
||||||
|
@ -863,7 +828,7 @@ namespace iFileProxy.Services
|
||||||
FROM t_user_events e
|
FROM t_user_events e
|
||||||
LEFT JOIN t_users u ON e.user_id = u.user_id
|
LEFT JOIN t_users u ON e.user_id = u.user_id
|
||||||
WHERE 1=1");
|
WHERE 1=1");
|
||||||
|
|
||||||
var parameters = new Dictionary<string, object>();
|
var parameters = new Dictionary<string, object>();
|
||||||
|
|
||||||
// 添加用户ID过滤
|
// 添加用户ID过滤
|
||||||
|
@ -993,7 +958,7 @@ namespace iFileProxy.Services
|
||||||
(log_id, level, message, exception, properties, timestamp)
|
(log_id, level, message, exception, properties, timestamp)
|
||||||
VALUES
|
VALUES
|
||||||
(@logId, @level, @message, @exception, @properties, @timestamp)";
|
(@logId, @level, @message, @exception, @properties, @timestamp)";
|
||||||
|
|
||||||
var parameters = new Dictionary<string, object>
|
var parameters = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "@logId", log.LogId },
|
{ "@logId", log.LogId },
|
||||||
|
@ -1009,8 +974,8 @@ namespace iFileProxy.Services
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PagedResult<SystemLog>> GetPagedSystemLogsAsync(
|
public async Task<PagedResult<SystemLog>> GetPagedSystemLogsAsync(
|
||||||
int page,
|
int page,
|
||||||
int pageSize,
|
int pageSize,
|
||||||
LogEventLevel? level = null,
|
LogEventLevel? level = null,
|
||||||
string? keyword = null,
|
string? keyword = null,
|
||||||
DateTime? startTime = null,
|
DateTime? startTime = null,
|
||||||
|
@ -1086,7 +1051,7 @@ namespace iFileProxy.Services
|
||||||
{
|
{
|
||||||
var sql = @"INSERT INTO t_download_history (tid, time, client_ip)
|
var sql = @"INSERT INTO t_download_history (tid, time, client_ip)
|
||||||
VALUES (@taskId, @time, @clientIp)";
|
VALUES (@taskId, @time, @clientIp)";
|
||||||
|
|
||||||
var parameters = new Dictionary<string, object>
|
var parameters = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "@taskId", taskId },
|
{ "@taskId", taskId },
|
||||||
|
|
|
@ -32,7 +32,8 @@ namespace iFileProxy.Services
|
||||||
CACHE_LIFETIME = _appConfig.DownloadOptions.CacheLifetime;
|
CACHE_LIFETIME = _appConfig.DownloadOptions.CacheLifetime;
|
||||||
_dbGateService = serviceProvider.GetRequiredService<DatabaseGateService>();
|
_dbGateService = serviceProvider.GetRequiredService<DatabaseGateService>();
|
||||||
// 开始定时清理任务
|
// 开始定时清理任务
|
||||||
_timer = new Timer((obj) => {
|
_timer = new Timer((obj) =>
|
||||||
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
CheckAndCleanCache();
|
CheckAndCleanCache();
|
||||||
|
@ -58,7 +59,7 @@ namespace iFileProxy.Services
|
||||||
{
|
{
|
||||||
using var cmd = new MySqlCommand(sql, conn);
|
using var cmd = new MySqlCommand(sql, conn);
|
||||||
using var adapter = new MySqlDataAdapter(cmd);
|
using var adapter = new MySqlDataAdapter(cmd);
|
||||||
var dataTable = new DataTable();
|
using var dataTable = new DataTable();
|
||||||
adapter.Fill(dataTable);
|
adapter.Fill(dataTable);
|
||||||
taskInfos = JsonConvert.DeserializeObject<List<TaskInfo>>(
|
taskInfos = JsonConvert.DeserializeObject<List<TaskInfo>>(
|
||||||
JsonConvert.SerializeObject(dataTable)
|
JsonConvert.SerializeObject(dataTable)
|
||||||
|
@ -69,6 +70,16 @@ namespace iFileProxy.Services
|
||||||
{
|
{
|
||||||
foreach (TaskInfo taskInfo in taskInfos)
|
foreach (TaskInfo taskInfo in taskInfos)
|
||||||
{
|
{
|
||||||
|
var dependencies = _dbGateService.CheckCacheDependencies(taskInfo.TaskId, taskInfo.ClientIp);
|
||||||
|
// 获取依赖和已经过期的任务ID交集
|
||||||
|
var intersect = dependencies.Select(x => x.TaskId).Intersect(taskInfos.Select(x => x.TaskId)).ToList();
|
||||||
|
// 若依赖该缓存的任务也处于过期状态 则不进行缓存依赖检查
|
||||||
|
if (intersect.IndexOf(taskInfo.TaskId) == -1)
|
||||||
|
if (dependencies != null && dependencies.Count > 0)
|
||||||
|
{
|
||||||
|
_logger.Warning($"TaskId: {taskInfo.TaskId} 所产生的缓存文件正被 {string.Join(",", dependencies.Select(x => x.TaskId))} 所依赖, 不会继续执行清理任务");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
string cacheFileName = Path.Combine(_appConfig.DownloadOptions.SavePath, taskInfo.FileName);
|
string cacheFileName = Path.Combine(_appConfig.DownloadOptions.SavePath, taskInfo.FileName);
|
||||||
if (File.Exists(cacheFileName))
|
if (File.Exists(cacheFileName))
|
||||||
{
|
{
|
||||||
|
@ -85,22 +96,20 @@ namespace iFileProxy.Services
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新数据库状态
|
// 更新数据库状态
|
||||||
using (var conn = _dbGateService.GetAndOpenDBConn(DbConfigName.iFileProxy))
|
using var conn = _dbGateService.GetAndOpenDBConn(DbConfigName.iFileProxy);
|
||||||
|
// 更新标签
|
||||||
|
using (var cmd = new MySqlCommand(
|
||||||
|
"UPDATE t_tasks_info SET tag = @tag WHERE tid = @tid",
|
||||||
|
conn))
|
||||||
{
|
{
|
||||||
// 更新标签
|
cmd.Parameters.AddWithValue("@tag", "CLEANED");
|
||||||
using (var cmd = new MySqlCommand(
|
cmd.Parameters.AddWithValue("@tid", taskInfo.TaskId);
|
||||||
"UPDATE t_tasks_info SET tag = @tag WHERE tid = @tid",
|
cmd.ExecuteNonQuery();
|
||||||
conn))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@tag", "CLEANED");
|
|
||||||
cmd.Parameters.AddWithValue("@tid", taskInfo.TaskId);
|
|
||||||
cmd.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新状态
|
|
||||||
taskInfo.Status = TaskState.Cleaned;
|
|
||||||
_dbGateService.UpdateTaskStatus(taskInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新状态
|
||||||
|
taskInfo.Status = TaskState.Cleaned;
|
||||||
|
_dbGateService.UpdateTaskStatus(taskInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue