使代码更加合理
This commit is contained in:
parent
69296bd413
commit
bc589471f3
9 changed files with 284 additions and 88 deletions
|
@ -1,4 +1,4 @@
|
|||
using iFileProxy.Helpers;
|
||||
using iFileProxy.Services;
|
||||
using Serilog;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
@ -23,7 +23,7 @@ namespace iFileProxy.Config
|
|||
[JsonPropertyName("Database")]
|
||||
public Database Database { get; set; }
|
||||
|
||||
public static AppConfig? GetCurrConfig(string configPath = "iFileProxy.json")
|
||||
public static AppConfig GetCurrConfig(string configPath = "iFileProxy.json")
|
||||
{
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
|
@ -41,7 +41,7 @@ namespace iFileProxy.Config
|
|||
_logger.Fatal($"Config File: {configPath} not exists!");
|
||||
return null;
|
||||
}
|
||||
public static void CheckAppConfig()
|
||||
public static void CheckAppConfig(IServiceProvider serviceProvider)
|
||||
{
|
||||
AppConfig? c = GetCurrConfig();
|
||||
if (c != null)
|
||||
|
@ -59,7 +59,7 @@ namespace iFileProxy.Config
|
|||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
DatabaseHelper databaseHelper = new(c);
|
||||
var databaseHelper = serviceProvider.GetRequiredService<DatabaseGateService>();
|
||||
databaseHelper.TestDbConfig();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using iFileProxy.Helpers;
|
||||
using iFileProxy.Services;
|
||||
using iFileProxy.Models;
|
||||
using iFileProxy.Config;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
@ -14,7 +15,11 @@ namespace iFileProxy.Controllers
|
|||
[ApiController]
|
||||
public class VisitorManagementController : ControllerBase
|
||||
{
|
||||
static DatabaseHelper _dbHelper = new DatabaseHelper(AppConfig.GetCurrConfig());
|
||||
private readonly DatabaseGateService _dbGateService;
|
||||
public VisitorManagementController(DatabaseGateService dbGate)
|
||||
{
|
||||
_dbGateService = dbGate;
|
||||
}
|
||||
private readonly static Serilog.ILogger _logger = Log.Logger.ForContext<VisitorManagementController>();
|
||||
|
||||
|
||||
|
@ -22,14 +27,14 @@ namespace iFileProxy.Controllers
|
|||
public ActionResult<CommonRsp> DeleteInfo()
|
||||
{
|
||||
string ipAddr = MasterHelper.GetClientIPAddr(HttpContext);
|
||||
var d = JsonConvert.DeserializeObject<List<TaskInfo>>(_dbHelper.GetTaskListByStateAndIp(ipAddr, TaskState.Running));
|
||||
var d = JsonConvert.DeserializeObject<List<TaskInfo>>(_dbGateService.GetTaskListByStateAndIp(ipAddr, TaskState.Running));
|
||||
int rd = (d != null) ? d.Count : 0;
|
||||
if (rd <= 0)
|
||||
{
|
||||
d = JsonConvert.DeserializeObject<List<TaskInfo>>(_dbHelper.GetTaskListByIP(ipAddr));
|
||||
d = JsonConvert.DeserializeObject<List<TaskInfo>>(_dbGateService.GetTaskListByIP(ipAddr));
|
||||
foreach (var taskInfo in d)
|
||||
{
|
||||
var dep = _dbHelper.CheckCacheDependencies(taskInfo.TaskId,ipAddr);
|
||||
var dep = _dbGateService.CheckCacheDependencies(taskInfo.TaskId,ipAddr);
|
||||
if (dep.Count <= 0)
|
||||
{
|
||||
if (MasterHelper.CheckDownloadFileExists(taskInfo.FileName))
|
||||
|
@ -42,7 +47,7 @@ namespace iFileProxy.Controllers
|
|||
_logger.Warning($"准备删除的文件正在被以下Task所依赖: {JsonConvert.SerializeObject(dep)} 文件将不会被删除");
|
||||
|
||||
}
|
||||
return Ok(new CommonRsp() { Retcode = 0, Message = "succ", Data = _dbHelper.DeleteTaskInfoByIpAddr(ipAddr)});
|
||||
return Ok(new CommonRsp() { Retcode = 0, Message = "succ", Data = _dbGateService.DeleteTaskInfoByIpAddr(ipAddr)});
|
||||
}
|
||||
else
|
||||
return Ok(new CommonRsp() {Retcode = -1, Message = "你还有正在运行的任务, 你现在不能删除你的数据, 请稍后等待任务完成后重试", Data = rd });
|
||||
|
|
|
@ -10,14 +10,20 @@ namespace iFileProxy.Controllers
|
|||
{
|
||||
public class iProxyController : ControllerBase
|
||||
{
|
||||
static readonly TaskManager taskManager = new ();
|
||||
static AppConfig? appConfig = AppConfig.GetCurrConfig();
|
||||
private readonly TaskManager _taskManager;
|
||||
private readonly AppConfig _appConfig;
|
||||
|
||||
public iProxyController(TaskManager taskManager, AppConfig appConfig)
|
||||
{
|
||||
_taskManager = taskManager;
|
||||
_appConfig = appConfig;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("/AddOfflineTask")]
|
||||
public ActionResult<CommonRsp> AddOfflineTask()
|
||||
{
|
||||
return taskManager.AddTask(HttpContext) switch
|
||||
return _taskManager.AddTask(HttpContext) switch
|
||||
{
|
||||
TaskAddState.Success => (ActionResult<CommonRsp>)Ok(new CommonRsp() { Retcode = (int)TaskAddState.Success, Message = "succ" }),
|
||||
TaskAddState.Fail => (ActionResult<CommonRsp>)Ok(new CommonRsp() { Retcode = (int)TaskAddState.Fail, Message = "unkown error!" }),
|
||||
|
@ -43,12 +49,12 @@ namespace iFileProxy.Controllers
|
|||
[Route("/GetMyTasks")]
|
||||
public ActionResult<CommonRsp> GetMyTasks()
|
||||
{
|
||||
var data = taskManager.GetTaskListByIpAddr(HttpContext);
|
||||
var data = _taskManager.GetTaskListByIpAddr(HttpContext);
|
||||
foreach (var d in data)
|
||||
{
|
||||
if (d.Status == TaskState.Queuing)
|
||||
{
|
||||
d.QueuePosition = taskManager.GetQueuePosition(d.TaskId);
|
||||
d.QueuePosition = _taskManager.GetQueuePosition(d.TaskId);
|
||||
}
|
||||
}
|
||||
return Ok(new CommonRsp() { Retcode = 0, Data = data ,Message = "succ" });
|
||||
|
@ -58,7 +64,7 @@ namespace iFileProxy.Controllers
|
|||
[HttpGet]
|
||||
[Route("/GetServerLoad")]
|
||||
public ActionResult<CommonRsp> GetServerLoad() {
|
||||
return Ok(new CommonRsp { Retcode = 0, Message = "succ", Data = taskManager.GetServerTaskLoadInfo() });
|
||||
return Ok(new CommonRsp { Retcode = 0, Message = "succ", Data = _taskManager.GetServerTaskLoadInfo() });
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
|
@ -67,12 +73,12 @@ namespace iFileProxy.Controllers
|
|||
public async Task<IActionResult> DownloadFile(string taskID)
|
||||
{
|
||||
string fileName = "";
|
||||
var d = taskManager.GetTaskListByIpAddr(HttpContext);
|
||||
var taskInfo = taskManager.GetTaskInfo(taskID);
|
||||
var d = _taskManager.GetTaskListByIpAddr(HttpContext);
|
||||
var taskInfo = _taskManager.GetTaskInfo(taskID);
|
||||
|
||||
if ((!appConfig.SecurityOptions.AllowDifferentIPsForDownload && d.Where(x => x.TaskId == taskID).Any()) || taskInfo != null)
|
||||
if ((!_appConfig.SecurityOptions.AllowDifferentIPsForDownload && d.Where(x => x.TaskId == taskID).Any()) || taskInfo != null)
|
||||
{
|
||||
if (appConfig.SecurityOptions.AllowDifferentIPsForDownload)
|
||||
if (_appConfig.SecurityOptions.AllowDifferentIPsForDownload)
|
||||
{
|
||||
fileName = taskInfo[0].FileName;
|
||||
}
|
||||
|
@ -83,7 +89,7 @@ namespace iFileProxy.Controllers
|
|||
if (fileName == null)
|
||||
return Ok(new CommonRsp() { Message = "file not exists or taskId error", Retcode = -1 });
|
||||
|
||||
var filePath = Path.Combine(AppConfig.GetCurrConfig().DownloadOptions.SavePath, fileName);
|
||||
var filePath = Path.Combine(_appConfig.DownloadOptions.SavePath, fileName);
|
||||
if (!MasterHelper.CheckDownloadFileExists(fileName))
|
||||
{
|
||||
return Ok(new CommonRsp() { Message = "file not exists", Retcode = 1 });
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
/// 正在排队
|
||||
/// </summary>
|
||||
Queuing = 6,
|
||||
/// <summary>
|
||||
/// 任务因为各种原因被取消
|
||||
/// </summary>
|
||||
Canceled = 7,
|
||||
}
|
||||
/// <summary>
|
||||
/// 任务添加状态
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
using iFileProxy.Config;
|
||||
using iFileProxy.Helpers;
|
||||
using iFileProxy.Middleware;
|
||||
|
@ -16,11 +15,6 @@ namespace iFileProxy
|
|||
|
||||
Console.Write(" "); // 强迫症,看着开始的那条日志不对齐不得劲
|
||||
|
||||
AppConfig.CheckAppConfig();
|
||||
|
||||
// 初始化缓存管理服务
|
||||
LocalCacheManager localCacheManager = new ();
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
|
@ -32,8 +26,23 @@ namespace iFileProxy
|
|||
|
||||
builder.Host.UseSerilog(logger: Log.Logger);
|
||||
|
||||
builder.Services.AddSingleton<Dictionary<string, Dictionary<string, uint>>>(serviceProvider =>
|
||||
{
|
||||
return new Dictionary<string, Dictionary<string, uint>>();
|
||||
});
|
||||
|
||||
builder.Services.AddSingleton(AppConfig.GetCurrConfig());
|
||||
|
||||
builder.Services.AddSingleton<DatabaseGateService>();
|
||||
|
||||
builder.Services.AddSingleton<TaskManager>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
AppConfig.CheckAppConfig(app.Services);
|
||||
|
||||
LocalCacheManager localCacheManager = new(app.Services);
|
||||
|
||||
app.UseSerilogRequestLogging(options =>
|
||||
{
|
||||
options.EnrichDiagnosticContext = (diagCtx, httpCtx) =>
|
||||
|
@ -51,6 +60,9 @@ namespace iFileProxy
|
|||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
// ´íÎó´¦ÀíÖмä¼þ
|
||||
app.UseMiddleware<ErrorHandlerMiddleware>();
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
// 配置默认文件选项
|
||||
|
@ -64,11 +76,9 @@ namespace iFileProxy
|
|||
|
||||
app.UseAuthorization();
|
||||
|
||||
var IPAccessCountDict = new Dictionary<string, Dictionary<string, uint>>();
|
||||
var dailyRequestLimitPerIP = AppConfig.GetCurrConfig().SecurityOptions.DailyRequestLimitPerIP;
|
||||
app.UseMiddleware<IPAccessLimitMiddleware>(IPAccessCountDict, dailyRequestLimitPerIP);
|
||||
|
||||
app.UseMiddleware<ErrorHandlerMiddleware>(); // 错误处理中间件
|
||||
app.UseMiddleware<IPAccessLimitMiddleware>(
|
||||
app.Services.GetRequiredService<Dictionary<string, Dictionary<string, uint>>>(),
|
||||
AppConfig.GetCurrConfig().SecurityOptions.DailyRequestLimitPerIP);
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
|||
<_TargetId>Folder</_TargetId>
|
||||
<SiteUrlToLaunchAfterPublish />
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<ProjectGuid>e343bd8a-27ed-47e2-b50d-e3000730e65e</ProjectGuid>
|
||||
<SelfContained>false</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
|
|
|
@ -1,24 +1,32 @@
|
|||
using iFileProxy.Config;
|
||||
using Serilog;
|
||||
using System.Data;
|
||||
using System.Text.Json;
|
||||
using iFileProxy.Helpers;
|
||||
using MySql.Data.MySqlClient;
|
||||
using iFileProxy.Models;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace iFileProxy.Helpers
|
||||
namespace iFileProxy.Services
|
||||
{
|
||||
public class DatabaseHelper
|
||||
/// <summary>
|
||||
/// 数据库访问网关服务
|
||||
/// 提供统一的数据库操作接口,管理数据库连接和查询
|
||||
/// </summary>
|
||||
public class DatabaseGateService
|
||||
{
|
||||
Database _db;
|
||||
AppConfig _appConfig;
|
||||
private readonly static Serilog.ILogger _logger = Log.Logger.ForContext<DatabaseHelper>();
|
||||
private readonly Serilog.ILogger _logger = Log.Logger.ForContext<DatabaseGateService>();
|
||||
|
||||
Dictionary<string, DB> _dbDictionary = [];
|
||||
|
||||
public DatabaseHelper(AppConfig appConfig)
|
||||
/// <summary>
|
||||
/// 初始化数据库网关服务
|
||||
/// </summary>
|
||||
/// <param name="appConfig">应用程序配置</param>
|
||||
public DatabaseGateService(AppConfig appConfig)
|
||||
{
|
||||
_logger.Information("Initializing DatabaseHelper...");
|
||||
_logger.Information("Initializing DatabaseGateService...");
|
||||
_db = appConfig.Database;
|
||||
_appConfig = appConfig;
|
||||
try
|
||||
|
@ -33,7 +41,7 @@ namespace iFileProxy.Helpers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载数据库描述字典
|
||||
/// 加载数据库配置字典
|
||||
/// </summary>
|
||||
public void LoadDbDict()
|
||||
{
|
||||
|
@ -43,13 +51,14 @@ namespace iFileProxy.Helpers
|
|||
_logger.Debug($"Db Config: {item.Description} <=> {item.DatabaseName} Loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个指定数据库的连接
|
||||
/// 获取并打开指定数据库的连接
|
||||
/// </summary>
|
||||
/// <param name="db_desc">数据库描述字段 对应AppConfig的description字段</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception">若某些不允许为空的字段出现空值 则抛出此异常</exception>
|
||||
///
|
||||
/// <param name="db_desc">数据库描述符,对应配置文件中的 Description 字段</param>
|
||||
/// <returns>已打开的数据库连接</returns>
|
||||
/// <exception cref="Exception">当找不到匹配的数据库配置时抛出</exception>
|
||||
/// <exception cref="NoNullAllowedException">当必需的配置字段为空时抛出</exception>
|
||||
public MySqlConnection GetAndOpenDBConn(string db_desc)
|
||||
{
|
||||
if (!_dbDictionary.TryGetValue(db_desc, out DB Db))
|
||||
|
@ -80,6 +89,10 @@ namespace iFileProxy.Helpers
|
|||
return conn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试所有数据库配置的连接
|
||||
/// </summary>
|
||||
/// <returns>测试是否全部成功</returns>
|
||||
public bool TestDbConfig()
|
||||
{
|
||||
foreach (var db in _dbDictionary)
|
||||
|
@ -105,11 +118,10 @@ namespace iFileProxy.Helpers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个json格式的数据表
|
||||
/// 执行查询并返回 JSON 格式的结果
|
||||
/// </summary>
|
||||
/// <param name="sql"></param>
|
||||
/// <param name="conn"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="sqlCmd">SQL 命令对象</param>
|
||||
/// <returns>JSON 格式的查询结果</returns>
|
||||
public static string QueryTableData(MySqlCommand sqlCmd)
|
||||
{
|
||||
DataTable dataTable = new();
|
||||
|
@ -119,34 +131,43 @@ namespace iFileProxy.Helpers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个json格式的数据表
|
||||
/// 执行查询并返回 JSON 格式的结果
|
||||
/// </summary>
|
||||
/// <param name="sql"></param>
|
||||
/// <param name="conn"></param>
|
||||
/// <returns></returns>
|
||||
public string QueryTableData(string sql,string dbConfName)
|
||||
/// <param name="sql">SQL 查询语句</param>
|
||||
/// <param name="dbConfName">数据库配置名称</param>
|
||||
/// <returns>JSON 格式的查询结果</returns>
|
||||
public string QueryTableData(string sql, string dbConfName)
|
||||
{
|
||||
DataTable dataTable = new();
|
||||
using (MySqlDataAdapter adapter = new(new MySqlCommand(sql,GetAndOpenDBConn(dbConfName))))
|
||||
using (MySqlDataAdapter adapter = new(new MySqlCommand(sql, GetAndOpenDBConn(dbConfName))))
|
||||
adapter.Fill(dataTable);
|
||||
return JsonConvert.SerializeObject(dataTable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内部查询数据专用 当此方法暴露给C端可能造成sql注入等安全问题
|
||||
/// 执行非查询SQL语句
|
||||
/// </summary>
|
||||
/// <param name="sql">SQL语句</param>
|
||||
/// <param name="dbConfName">配置文件中的Description字段</param>
|
||||
/// <returns>影响的行数</returns>
|
||||
/// <param name="dbConfName">数据库配置名称</param>
|
||||
/// <returns>受影响的行数</returns>
|
||||
/// <remarks>
|
||||
/// 警告:此方法仅供内部使用,直接暴露给客户端可能导致SQL注入风险
|
||||
/// </remarks>
|
||||
public int Query(string sql, string dbConfName)
|
||||
{
|
||||
{
|
||||
using MySqlCommand sqlCmd = new (sql, GetAndOpenDBConn(dbConfName));
|
||||
int n = sqlCmd.ExecuteNonQuery();
|
||||
_logger.Debug($"查询完成, 受影响的行数: {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";
|
||||
MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||
|
@ -157,7 +178,7 @@ namespace iFileProxy.Helpers
|
|||
sqlCmd.Parameters.AddWithValue("@status", TaskState.Cached);
|
||||
sqlCmd.Parameters.AddWithValue("@ip_addr", ipAddr);
|
||||
|
||||
return JsonConvert.DeserializeObject<List<TaskInfo>>( QueryTableData(sqlCmd));
|
||||
return JsonConvert.DeserializeObject<List<TaskInfo>>(QueryTableData(sqlCmd));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -167,6 +188,12 @@ namespace iFileProxy.Helpers
|
|||
finally { conn.Close(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据状态和IP地址获取任务列表
|
||||
/// </summary>
|
||||
/// <param name="ipAddr">IP地址</param>
|
||||
/// <param name="status">任务状态</param>
|
||||
/// <returns>JSON格式的任务列表</returns>
|
||||
public string GetTaskListByStateAndIp(string ipAddr, TaskState status)
|
||||
{
|
||||
string sql = $"SELECT * FROM t_tasks_info WHERE client_ip = @ip_addr AND `status` = @status";
|
||||
|
@ -175,7 +202,7 @@ namespace iFileProxy.Helpers
|
|||
{
|
||||
using MySqlCommand sqlCmd = new(sql, conn);
|
||||
sqlCmd.Parameters.AddWithValue("@ip_addr", ipAddr);
|
||||
sqlCmd.Parameters.AddWithValue ("@status", status);
|
||||
sqlCmd.Parameters.AddWithValue("@status", status);
|
||||
return QueryTableData(sqlCmd);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -186,7 +213,11 @@ namespace iFileProxy.Helpers
|
|||
finally { conn.Close(); }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据IP地址获取任务列表
|
||||
/// </summary>
|
||||
/// <param name="ipAddr">IP地址</param>
|
||||
/// <returns>JSON格式的任务列表</returns>
|
||||
public string GetTaskListByIP(string ipAddr)
|
||||
{
|
||||
string sql = $"SELECT * FROM t_tasks_info WHERE client_ip = @ip_addr";
|
||||
|
@ -204,6 +235,12 @@ namespace iFileProxy.Helpers
|
|||
}
|
||||
finally { conn.Close(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据任务ID获取任务信息
|
||||
/// </summary>
|
||||
/// <param name="tid">任务ID</param>
|
||||
/// <returns>JSON格式的任务信息</returns>
|
||||
public string GetTaskInfoByTid(string tid)
|
||||
{
|
||||
string sql = $"SELECT * FROM t_tasks_info WHERE `tid` =@tid";
|
||||
|
@ -222,6 +259,14 @@ namespace iFileProxy.Helpers
|
|||
finally { conn.Close(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询任务信息
|
||||
/// </summary>
|
||||
/// <param name="fileName">文件名</param>
|
||||
/// <param name="url">URL</param>
|
||||
/// <param name="size">文件大小</param>
|
||||
/// <param name="status">任务状态</param>
|
||||
/// <returns>任务信息对象,如果未找到则返回null</returns>
|
||||
public TaskInfo? QueryTaskInfo(string fileName, string url, long size, TaskState status)
|
||||
{
|
||||
string sql = $"SELECT * FROM t_tasks_info WHERE url = @url AND size = @size AND `status` = @status AND file_name = @fileName";
|
||||
|
@ -250,6 +295,11 @@ namespace iFileProxy.Helpers
|
|||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插入任务数据
|
||||
/// </summary>
|
||||
/// <param name="taskInfo">任务信息对象</param>
|
||||
/// <returns>是否插入成功</returns>
|
||||
public bool InsertTaskData(TaskInfo taskInfo)
|
||||
{
|
||||
_logger.Debug(System.Text.Json.JsonSerializer.Serialize(taskInfo));
|
||||
|
@ -284,7 +334,15 @@ namespace iFileProxy.Helpers
|
|||
}
|
||||
return true;
|
||||
}
|
||||
public bool UpdateFieldsData(string fieldsName, string key,string val)
|
||||
|
||||
/// <summary>
|
||||
/// 更新指定字段的数据
|
||||
/// </summary>
|
||||
/// <param name="fieldsName">字段名</param>
|
||||
/// <param name="key">主键值</param>
|
||||
/// <param name="val">更新值</param>
|
||||
/// <returns>是否更新成功</returns>
|
||||
public bool UpdateFieldsData(string fieldsName, string key, string val)
|
||||
{
|
||||
string sql = $"UPDATE t_tasks_info set `{fieldsName}` = @Data WHERE `tid` = @tid";
|
||||
MySqlConnection conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||
|
@ -312,6 +370,11 @@ namespace iFileProxy.Helpers
|
|||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新任务状态
|
||||
/// </summary>
|
||||
/// <param name="taskInfo">任务信息对象</param>
|
||||
/// <returns>是否更新成功</returns>
|
||||
public bool UpdateTaskStatus(TaskInfo taskInfo)
|
||||
{
|
||||
string sql = @"UPDATE t_tasks_info set `status` = @status , update_time = Now() WHERE `tid` = @tid";
|
||||
|
@ -341,16 +404,21 @@ namespace iFileProxy.Helpers
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新任务的哈希值
|
||||
/// </summary>
|
||||
/// <param name="taskInfo">任务信息对象</param>
|
||||
/// <returns>是否更新成功</returns>
|
||||
public bool UpdateTaskHash(TaskInfo taskInfo)
|
||||
{
|
||||
return UpdateFieldsData("hash", taskInfo.TaskId, MasterHelper.GetFileHash(Path.Combine(_appConfig.DownloadOptions.SavePath, taskInfo.FileName), FileHashAlgorithm.MD5));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定IP的任务信息
|
||||
/// 删除指定IP地址的所有任务信息
|
||||
/// </summary>
|
||||
/// <param name="c"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="ipAddr">IP地址</param>
|
||||
/// <returns>受影响的行数,-1表示操作失败</returns>
|
||||
public int DeleteTaskInfoByIpAddr(string ipAddr)
|
||||
{
|
||||
try
|
||||
|
@ -364,6 +432,12 @@ namespace iFileProxy.Helpers
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试初始化数据库
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 创建必要的数据库表结构
|
||||
/// </remarks>
|
||||
public void TryInitialDB()
|
||||
{
|
||||
string sql = """
|
||||
|
@ -398,5 +472,58 @@ namespace iFileProxy.Helpers
|
|||
conn.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行标量查询
|
||||
/// </summary>
|
||||
/// <typeparam name="T">返回值类型</typeparam>
|
||||
/// <param name="sql">SQL查询语句</param>
|
||||
/// <param name="parameters">查询参数</param>
|
||||
/// <returns>查询结果</returns>
|
||||
public T ExecuteScalar<T>(string sql, Dictionary<string, object> parameters)
|
||||
{
|
||||
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||
using var cmd = new MySqlCommand(sql, conn);
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
cmd.Parameters.AddWithValue(param.Key, param.Value);
|
||||
}
|
||||
return (T)cmd.ExecuteScalar();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行查询并返回实体列表
|
||||
/// </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)
|
||||
{
|
||||
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||
using var cmd = new MySqlCommand(sql, conn);
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
cmd.Parameters.AddWithValue(param.Key, param.Value);
|
||||
}
|
||||
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)
|
||||
{
|
||||
using var conn = GetAndOpenDBConn("iFileProxy_Db");
|
||||
using var cmd = new MySqlCommand(sql, conn);
|
||||
foreach (var param in parameters)
|
||||
{
|
||||
cmd.Parameters.AddWithValue(param.Key, param.Value);
|
||||
}
|
||||
return cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,17 +17,17 @@ namespace iFileProxy.Services
|
|||
private readonly static Serilog.ILogger _logger = Log.Logger.ForContext<LocalCacheManager>();
|
||||
|
||||
private readonly Timer _timer;
|
||||
private readonly DatabaseHelper _dbHelper;
|
||||
private readonly DatabaseGateService _dbGateService;
|
||||
private readonly int CACHE_LIFETIME;
|
||||
|
||||
/// <summary>
|
||||
/// 缓存管理器
|
||||
/// </summary>
|
||||
public LocalCacheManager()
|
||||
public LocalCacheManager(IServiceProvider serviceProvider)
|
||||
{
|
||||
_logger.Information("Initializing LocalCacheManager.");
|
||||
CACHE_LIFETIME = _appConfig.DownloadOptions.CacheLifetime;
|
||||
_dbHelper = new DatabaseHelper(_appConfig);
|
||||
_dbGateService = serviceProvider.GetRequiredService<DatabaseGateService>();
|
||||
// 开始定时清理任务
|
||||
_timer = new Timer(CheckAndCleanCache, null, TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(60));
|
||||
_logger.Information("succ.");
|
||||
|
@ -39,7 +39,7 @@ namespace iFileProxy.Services
|
|||
public void CheckAndCleanCache(object state)
|
||||
{
|
||||
// 获取数据库中超出生命周期的缓存数据
|
||||
string result = _dbHelper.QueryTableData($"SELECT * FROM t_tasks_info WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(update_time) > {CACHE_LIFETIME} AND (tag <> 'CLEANED' OR tag IS NULL)", DbConfigName.iFileProxy);
|
||||
string result = _dbGateService.QueryTableData($"SELECT * FROM t_tasks_info WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(update_time) > {CACHE_LIFETIME} AND (tag <> 'CLEANED' OR tag IS NULL)", DbConfigName.iFileProxy);
|
||||
List<TaskInfo>? taskInfos = JsonConvert.DeserializeObject<List<TaskInfo>>(result);
|
||||
if (taskInfos != null)
|
||||
{
|
||||
|
@ -59,9 +59,9 @@ namespace iFileProxy.Services
|
|||
throw;
|
||||
}
|
||||
}
|
||||
_dbHelper.Query($"UPDATE t_tasks_info SET `tag` = \"CLEANED\" WHERE `tid` = '{taskInfo.TaskId}'", DbConfigName.iFileProxy);
|
||||
_dbGateService.Query($"UPDATE t_tasks_info SET `tag` = \"CLEANED\" WHERE `tid` = '{taskInfo.TaskId}'", DbConfigName.iFileProxy);
|
||||
taskInfo.Status = TaskState.Cleaned;
|
||||
_dbHelper.UpdateTaskStatus(taskInfo);
|
||||
_dbGateService.UpdateTaskStatus(taskInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using iFileProxy.Config;
|
||||
using iFileProxy.Helpers;
|
||||
using iFileProxy.Models;
|
||||
using Org.BouncyCastle.Asn1.Tsp;
|
||||
using Serilog;
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
|
@ -50,16 +49,16 @@ namespace iFileProxy.Services
|
|||
|
||||
private readonly static Serilog.ILogger _logger = Log.Logger.ForContext<TaskManager>();
|
||||
private readonly AppConfig? _appConfig = AppConfig.GetCurrConfig("iFileProxy.json");
|
||||
private readonly DatabaseHelper _dbHelper;
|
||||
private readonly DatabaseGateService _dbGateService;
|
||||
private Dictionary<string, TaskInfo> _runningTasks = [];
|
||||
private Queue<TaskInfo> _pendingTasks = new();
|
||||
private readonly object _taskLock = new();
|
||||
|
||||
public TaskManager()
|
||||
public TaskManager(IServiceProvider serviceProvider)
|
||||
{
|
||||
_logger.Information("Initializing TaskManager...");
|
||||
if (_appConfig != null)
|
||||
_dbHelper = new DatabaseHelper(_appConfig);
|
||||
_dbGateService = serviceProvider.GetRequiredService<DatabaseGateService>();
|
||||
else
|
||||
{
|
||||
_logger.Fatal($"Failed to load application configuration");
|
||||
|
@ -140,7 +139,7 @@ namespace iFileProxy.Services
|
|||
|
||||
if (MasterHelper.CheckDownloadFileExists(taskInfo.FileName))
|
||||
{
|
||||
var r = _dbHelper.QueryTaskInfo(taskInfo.FileName, taskInfo.Url, taskInfo.Size, TaskState.End);
|
||||
var r = _dbGateService.QueryTaskInfo(taskInfo.FileName, taskInfo.Url, taskInfo.Size, TaskState.End);
|
||||
if (r != null)
|
||||
{
|
||||
taskInfo.Status = TaskState.Cached;
|
||||
|
@ -163,7 +162,7 @@ namespace iFileProxy.Services
|
|||
/// <returns></returns>
|
||||
public TaskAddState AddTaskInfoToDb(TaskInfo taskInfo, bool queuing = false)
|
||||
{
|
||||
if (_dbHelper.InsertTaskData(taskInfo))
|
||||
if (_dbGateService.InsertTaskData(taskInfo))
|
||||
{
|
||||
if (!queuing) // 如果不是正在排队的任务
|
||||
{
|
||||
|
@ -178,7 +177,7 @@ namespace iFileProxy.Services
|
|||
{
|
||||
taskInfo.Status = TaskState.Queuing;
|
||||
}
|
||||
_dbHelper.UpdateTaskStatus(taskInfo);
|
||||
_dbGateService.UpdateTaskStatus(taskInfo);
|
||||
|
||||
return TaskAddState.Success;
|
||||
}
|
||||
|
@ -222,7 +221,7 @@ namespace iFileProxy.Services
|
|||
if (taskInfo.Status != TaskState.Running)
|
||||
{
|
||||
taskInfo.Status = TaskState.Running;
|
||||
_dbHelper.UpdateTaskStatus(taskInfo);
|
||||
_dbGateService.UpdateTaskStatus(taskInfo);
|
||||
}
|
||||
_logger.Information($"[TaskId: {taskInfo.TaskId}] Started.");
|
||||
aria2c.BeginOutputReadLine();
|
||||
|
@ -237,14 +236,14 @@ namespace iFileProxy.Services
|
|||
{
|
||||
_logger.Error($"task: {taskInfo.TaskId} 进程退出状态异常 ExitCode: {aria2c.ExitCode}");
|
||||
taskInfo.Status = TaskState.Error;
|
||||
_dbHelper.UpdateTaskStatus(taskInfo);
|
||||
_dbGateService.UpdateTaskStatus(taskInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
taskInfo.Status = TaskState.End;
|
||||
_dbHelper.UpdateTaskStatus(taskInfo);
|
||||
_dbGateService.UpdateTaskStatus(taskInfo);
|
||||
taskInfo.Hash = MasterHelper.GetFileHash(Path.Combine(_appConfig.DownloadOptions.SavePath, taskInfo.FileName), FileHashAlgorithm.MD5);
|
||||
_dbHelper.UpdateTaskHash(taskInfo);
|
||||
_dbGateService.UpdateTaskHash(taskInfo);
|
||||
}
|
||||
|
||||
// 触发任务完成事件
|
||||
|
@ -282,7 +281,7 @@ namespace iFileProxy.Services
|
|||
public List<TaskInfo> GetTaskListByIpAddr(HttpContext c)
|
||||
{
|
||||
string? clientIp = MasterHelper.GetClientIPAddr(c);
|
||||
return JsonSerializer.Deserialize<List<TaskInfo>>(_dbHelper.GetTaskListByIP(clientIp)) ?? [];
|
||||
return JsonSerializer.Deserialize<List<TaskInfo>>(_dbGateService.GetTaskListByIP(clientIp)) ?? [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -292,8 +291,8 @@ namespace iFileProxy.Services
|
|||
/// <returns></returns>
|
||||
public List<TaskInfo> GetTaskInfo(string taskId)
|
||||
{
|
||||
_logger.Debug(_dbHelper.GetTaskInfoByTid(taskId));
|
||||
return JsonSerializer.Deserialize<List<TaskInfo>>(_dbHelper.GetTaskInfoByTid(taskId)) ?? [];
|
||||
_logger.Debug(_dbGateService.GetTaskInfoByTid(taskId));
|
||||
return JsonSerializer.Deserialize<List<TaskInfo>>(_dbGateService.GetTaskInfoByTid(taskId)) ?? [];
|
||||
}
|
||||
|
||||
public Dictionary<string, TaskInfo> GetRunningTasks() => _runningTasks;
|
||||
|
@ -333,9 +332,54 @@ namespace iFileProxy.Services
|
|||
return new ServerTaskLoadInfo { Queuing = _pendingTasks.Count , Running = _runningTasks.Count};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试中断指定的任务
|
||||
/// </summary>
|
||||
/// <param name="taskInfo">要中断的任务信息</param>
|
||||
/// <returns>是否成功中断任务</returns>
|
||||
public void TryKillTask(TaskInfo taskInfo)
|
||||
{
|
||||
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查任务是否在运行中
|
||||
if (_runningTasks.TryGetValue(taskInfo.TaskId, out var runningTask))
|
||||
{
|
||||
_logger.Information($"正在尝试中断任务: {taskInfo.TaskId}");
|
||||
|
||||
// 从运行任务字典中移除
|
||||
_runningTasks.Remove(taskInfo.TaskId);
|
||||
|
||||
// 更新任务状态为错误
|
||||
taskInfo.Status = TaskState.Canceled;
|
||||
_dbGateService.UpdateTaskStatus(taskInfo);
|
||||
|
||||
// 删除未完成的文件
|
||||
var filePath = Path.Combine(_appConfig.DownloadOptions.SavePath, taskInfo.FileName);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
_logger.Debug($"已删除未完成的文件: {filePath}");
|
||||
}
|
||||
|
||||
// 删除aria2c的临时文件
|
||||
if (File.Exists(filePath + ".aria2"))
|
||||
{
|
||||
File.Delete(filePath + ".aria2");
|
||||
_logger.Debug("已删除aria2临时文件");
|
||||
}
|
||||
|
||||
_logger.Information($"任务 {taskInfo.TaskId} 已中断");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warning($"任务 {taskInfo.TaskId} 不在运行状态,无需中断");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"中断任务时发生错误: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
//public bool DeleteTask(HttpContext c)
|
||||
|
|
Loading…
Reference in a new issue