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 (properties.TryGetValue("isPartner", out var isPartner)) { if ((bool)isPartner == true) { properties = ProcessPartnerTaskDataAsync(properties); } } else if (properties.TryGetValue("isOfficial", out var isOfficial)) { if ((bool)isOfficial == true) { properties = ProcessOfficialTaskDataAsync(properties); } } else if (properties.TryGetValue("isYouChuan", out var isYouChuan)) { if ((bool)isYouChuan == true) { properties = ProcessYouChuanTaskDataAsync(properties); } } 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); } } /// /// 合作伙伴任务数据处理 /// /// /// public Dictionary ProcessPartnerTaskDataAsync(Dictionary properties) { try { string jsonStr = JsonConvert.SerializeObject(properties); dynamic data = JsonConvert.DeserializeObject(jsonStr) ?? new object { }; // 检查是否是合作伙伴任务 // 直接用dynamic访问,不做类型判断 bool isPartner = data?.isPartner ?? false; string partnerTaskId = data?.partnerTaskId ?? string.Empty; if (isPartner && !string.IsNullOrEmpty(partnerTaskId)) { _logger.LogInformation($"处理合作伙伴任务: {partnerTaskId}"); // 直接遍历,让异常处理兜底 var imageUrls = new List(); foreach (var item in data?.partnerTaskInfo?.imgUrls ?? Array.Empty()) { string url = item?.url ?? string.Empty; if (!string.IsNullOrEmpty(url)) { imageUrls.Add(new { url }); } } if (imageUrls.Count > 0) { properties["imageUrls"] = imageUrls; _logger.LogInformation($"成功提取了{imageUrls.Count}个图片URL"); } else { _logger.LogInformation("未找到partnerTaskInfo或者是图片信信息"); } } else { _logger.LogInformation($"任务不是partner任务或缺少必要信息: isPartner={isPartner}, partnerTaskId={partnerTaskId}"); } return properties; } catch (Exception ex) { _logger.LogError(ex, "处理任务数据时发生错误"); return properties; // 返回原始数据,避免处理错误导致数据丢失 } } /// /// 官方任务数据处理 /// /// /// public Dictionary ProcessOfficialTaskDataAsync(Dictionary properties) { try { string jsonStr = JsonConvert.SerializeObject(properties); dynamic data = JsonConvert.DeserializeObject(jsonStr) ?? new object { }; // 检查是否是合作伙伴任务 // 直接用dynamic访问,不做类型判断 bool isOfficial = data?.isOfficial ?? false; string officialTaskId = data?.officialTaskId ?? string.Empty; if (isOfficial && !string.IsNullOrEmpty(officialTaskId)) { _logger.LogInformation($"处理官方任务: {officialTaskId}"); // 直接遍历,让异常处理兜底 var imageUrls = new List(); foreach (var item in data?.officialTaskInfo?.imgUrls ?? Array.Empty()) { string url = item?.url ?? string.Empty; if (!string.IsNullOrEmpty(url)) { imageUrls.Add(new { url }); } } if (imageUrls.Count > 0) { properties["imageUrls"] = imageUrls; _logger.LogInformation($"成功提取了{imageUrls.Count}个图片URL"); } else { _logger.LogInformation("未找到officialTaskInfo或者是图片信信息"); } } else { _logger.LogInformation($"任务不是official任务或缺少必要信息: isOfficial={isOfficial}, officialTaskId={officialTaskId}"); } return properties; } catch (Exception ex) { _logger.LogError(ex, "处理任务数据时发生错误"); return properties; // 返回原始数据,避免处理错误导致数据丢失 } } /// /// 悠船任务数据处理 /// /// /// public Dictionary ProcessYouChuanTaskDataAsync(Dictionary properties) { try { string jsonStr = JsonConvert.SerializeObject(properties); dynamic data = JsonConvert.DeserializeObject(jsonStr) ?? new object { }; // 检查是否是合作伙伴任务 // 直接用dynamic访问,不做类型判断 bool isYouChuan = data?.isYouChuan ?? false; string youChuanTaskId = data?.youChuanTaskId ?? string.Empty; if (isYouChuan && !string.IsNullOrEmpty(youChuanTaskId)) { _logger.LogInformation($"处理悠船任务: {youChuanTaskId}"); // 直接遍历,让异常处理兜底 var imageUrls = new List(); foreach (var item in data?.youChuanTaskInfo?.imgUrls ?? Array.Empty()) { string url = item?.url ?? string.Empty; if (!string.IsNullOrEmpty(url)) { imageUrls.Add(new { url }); } } if (imageUrls.Count > 0) { properties["imageUrls"] = imageUrls; _logger.LogInformation($"成功提取了{imageUrls.Count}个图片URL"); } else { _logger.LogInformation("未找到youChuanTaskInfo或者是图片信信息"); } } else { _logger.LogInformation($"任务不是YouChuan任务或缺少必要信息: isYouChuan={isYouChuan}, youChuanTaskId={youChuanTaskId}"); } return properties; } catch (Exception ex) { _logger.LogError(ex, "处理任务数据时发生错误"); return properties; // 返回原始数据,避免处理错误导致数据丢失 } } } }