using LMS.Common.Extensions; using LMS.DAO; using LMS.Repository.DB; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Quartz; namespace LMS.Tools.MJPackage { [DisallowConcurrentExecution] public class TaskStatusCheckService(ITokenService tokenService, ApplicationDbContext dbContext, ILogger logger, ITaskService taskService, ITaskConcurrencyManager taskConcurrencyManager, TokenUsageTracker tokenUsageTracker) : IJob { private readonly ITokenService _tokenService = tokenService; private readonly ApplicationDbContext _dbContext = dbContext; private readonly ILogger _logger = logger; private readonly ITaskService _taskService = taskService; private readonly ITaskConcurrencyManager _taskConcurrencyManager = taskConcurrencyManager; private readonly TokenUsageTracker _tokenUsageTracker = tokenUsageTracker; public async Task Execute(IJobExecutionContext context) { _logger.LogInformation($"开始检查TASK信息 - 检查间隔: 20 秒,同步加载 原始请求的Token!"); var startTime = BeijingTimeExtension.GetBeijingTime(); try { // 强制同步数据库数据,原请求Token await _tokenService.LoadOriginTokenAsync(); // 强制同步数据 MJ API 的 Basic URL await _tokenService.LoadMJAPIBasicUrlAsync(); // 检查Task状态和返回值 // 获取所有超过五分钟没有完成的人物 List tasks = await _dbContext.MJApiTasks.Where(t => t.Status != MJTaskStatus.CANCEL && t.Status != MJTaskStatus.SUCCESS && t.Status != MJTaskStatus.FAILURE && t.StartTime < BeijingTimeExtension.GetBeijingTime()).ToListAsync(); if (tasks.Count == 0) { _logger.LogInformation("没有需要检查的任务!"); return; } // 开始每个请求 foreach (MJApiTasks task in tasks) { try { Dictionary? properties = await _taskService.FetchTaskAsync(task); // 没有找到数据的 if (properties == null) { // 没有找到数据 直接把任务失败 task.Status = MJTaskStatus.FAILURE; var newProperties = new { failReason = "任务丢失或未找到" }; task.EndTime = BeijingTimeExtension.GetBeijingTime(); task.Properties = JsonConvert.SerializeObject(newProperties); // 尝试释放 当前缓存中的任务 _tokenUsageTracker.RemoveTaskCache(task.ThirdPartyTaskId); _logger.LogWarning("任务轮询检查,未请求到对应的MJ数据,释放Token,释放任务" + task.Token); _tokenUsageTracker.ReleaseConcurrencyPermit(task.Token); } else { // 尝试获取状态字段 string status = MJTaskStatus.SUBMITTED; if (properties.TryGetValue("status", out var statusElement)) { status = statusElement.ToString() ?? MJTaskStatus.SUBMITTED; } else if (properties.TryGetValue("Status", out var statusElementCap)) { status = statusElementCap.ToString() ?? MJTaskStatus.SUBMITTED; } task.Status = status; if (status == MJTaskStatus.SUCCESS || status == MJTaskStatus.FAILURE || status == MJTaskStatus.CANCEL) { // 当前任务已经被释放过了 // 开始修改数据 task.EndTime = BeijingTimeExtension.GetBeijingTime(); task.Properties = JsonConvert.SerializeObject(properties); _logger.LogInformation("任务轮询检查,已请求到对应的MJ数据,并且状态为成功,失败,取消,释放Token,释放任务" + task.Token); _tokenUsageTracker.ReleaseConcurrencyPermit(task.Token); // 尝试释放 当前缓存中的任务 _tokenUsageTracker.RemoveTaskCache(task.ThirdPartyTaskId); } else { // 任务还在处理中 task.EndTime = null; // 处理中没有结束时间 task.Properties = JsonConvert.SerializeObject(properties); } } // 开始修改数据 await _taskConcurrencyManager.UpdateTaskInDatabase(task); } catch (Exception ex) { // 报错 _logger.LogError(ex, $"检查任务 {task.Token} 时发生错误,释放Token,释放任务", task.TaskId); task.Status = MJTaskStatus.FAILURE; var newProperties = new { failReason = "任务报错" }; task.EndTime = BeijingTimeExtension.GetBeijingTime(); task.Properties = JsonConvert.SerializeObject(newProperties); _tokenUsageTracker.ReleaseConcurrencyPermit(task.Token); // 尝试释放 当前缓存中的任务 _tokenUsageTracker.RemoveTaskCache(task.ThirdPartyTaskId); // 开始修改数据 await _taskConcurrencyManager.UpdateTaskInDatabase(task); } } var duration = BeijingTimeExtension.GetBeijingTime() - startTime; _logger.LogInformation($"Task状态检查完成,影响的Task {tasks.Count},耗时: {duration}ms", duration.TotalMilliseconds); } catch (Exception ex) { var duration = BeijingTimeExtension.GetBeijingTime() - startTime; _logger.LogError(ex, "Token同步失败,耗时: {Duration}ms", duration.TotalMilliseconds); } } } }